23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
# File 'lib/odin/transform/verbs/object_verbs.rb', line 23
def register(registry)
dv = Types::DynValue
registry["keys"] = ->(args, _ctx) {
obj = ObjectVerbs.(args[0])
return dv.of_null if obj.nil?
dv.of_array(obj.keys.map { |k| dv.of_string(k) })
}
registry["values"] = ->(args, _ctx) {
obj = ObjectVerbs.(args[0])
return dv.of_null if obj.nil?
dv.of_array(obj.values)
}
registry["entries"] = ->(args, _ctx) {
obj = ObjectVerbs.(args[0])
return dv.of_null if obj.nil?
result = obj.map { |k, v| dv.of_array([dv.of_string(k), v]) }
dv.of_array(result)
}
registry["has"] = ->(args, _ctx) {
obj = ObjectVerbs.(args[0])
key = args[1]&.to_string || ""
dv.of_bool(obj&.key?(key) || false)
}
registry["get"] = ->(args, _ctx) {
obj = ObjectVerbs.(args[0])
key = args[1]&.to_string || ""
default_val = args[2] || dv.of_null
if obj && obj.key?(key)
obj[key]
else
default_val
end
}
registry["merge"] = ->(args, _ctx) {
result = {}
args.each do |a|
obj = ObjectVerbs.(a)
result.merge!(obj) if obj
end
result.empty? ? dv.of_null : dv.of_object(result)
}
registry["jsonPath"] = ->(args, _ctx) {
root = args[0]
path = args[1]&.to_string || ""
return dv.of_null if root.nil? || root.null? || path.empty?
parts = path.sub(/^\$\.?/, "").split(".")
current = root
parts.each do |part|
break if current.nil? || current.null?
if part =~ /^(.+)\[(\d+)\]$/
field = $1
idx = $2.to_i
current = current.object? ? current.get(field) : nil
current = current&.array? ? (current.value[idx] || dv.of_null) : dv.of_null
elsif current.object?
current = current.get(part)
elsif current.array?
idx = part.to_i
current = current.value[idx] || dv.of_null
else
current = nil
end
end
current || dv.of_null
}
registry["extract"] = ->(args, _ctx) {
obj = args[0]
keys_arg = args[1]
return dv.of_null if obj.nil? || obj.null? || !obj.object?
key_list = if keys_arg&.array?
keys_arg.value.map(&:to_string)
elsif keys_arg&.string?
keys_arg.value.split(",").map(&:strip)
else
[]
end
result = {}
key_list.each do |k|
val = obj.get(k)
result[k] = val if val
end
dv.of_object(result)
}
end
|