@shwfed/nuxt 0.7.8 → 0.7.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (174) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/runtime/components/app.d.vue.ts +7 -58
  3. package/dist/runtime/components/app.vue +18 -411
  4. package/dist/runtime/components/app.vue.d.ts +7 -58
  5. package/dist/runtime/components/fields.d.vue.ts +177 -0
  6. package/dist/runtime/components/fields.vue +47 -0
  7. package/dist/runtime/components/fields.vue.d.ts +177 -0
  8. package/dist/runtime/components/table.d.vue.ts +63 -59
  9. package/dist/runtime/components/table.vue +52 -617
  10. package/dist/runtime/components/table.vue.d.ts +63 -59
  11. package/dist/runtime/components/ui/app/App.d.vue.ts +86 -0
  12. package/dist/runtime/components/ui/app/App.vue +414 -0
  13. package/dist/runtime/components/ui/app/App.vue.d.ts +86 -0
  14. package/dist/runtime/components/ui/button-group/ButtonGroupSeparator.vue +1 -1
  15. package/dist/runtime/components/ui/button-group/ButtonGroupText.vue +1 -1
  16. package/dist/runtime/components/ui/calendar/Calendar.d.vue.ts +5 -12
  17. package/dist/runtime/components/ui/calendar/Calendar.vue +77 -92
  18. package/dist/runtime/components/ui/calendar/Calendar.vue.d.ts +5 -12
  19. package/dist/runtime/components/ui/calendar/CalendarCellTrigger.vue +1 -1
  20. package/dist/runtime/components/ui/calendar/index.d.ts +1 -1
  21. package/dist/runtime/components/ui/checkbox/Checkbox.vue +6 -2
  22. package/dist/runtime/components/ui/command/CommandGroup.vue +4 -0
  23. package/dist/runtime/components/ui/dialog/DialogOverlay.vue +1 -1
  24. package/dist/runtime/components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue +1 -1
  25. package/dist/runtime/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue +1 -1
  26. package/dist/runtime/components/ui/expression-editor/ExpressionEditor.d.vue.ts +30 -0
  27. package/dist/runtime/components/ui/expression-editor/ExpressionEditor.vue +87 -0
  28. package/dist/runtime/components/ui/expression-editor/ExpressionEditor.vue.d.ts +30 -0
  29. package/dist/runtime/components/ui/expression-editor/index.d.ts +1 -0
  30. package/dist/runtime/components/ui/expression-editor/index.js +1 -0
  31. package/dist/runtime/components/ui/field/FieldContent.vue +1 -1
  32. package/dist/runtime/components/ui/field/FieldDescription.vue +1 -1
  33. package/dist/runtime/components/ui/field/FieldError.vue +2 -2
  34. package/dist/runtime/components/ui/field/FieldLabel.vue +1 -1
  35. package/dist/runtime/components/ui/field/FieldSeparator.vue +1 -1
  36. package/dist/runtime/components/ui/field/index.js +7 -5
  37. package/dist/runtime/components/ui/fields/Fields.d.vue.ts +376 -0
  38. package/dist/runtime/components/ui/fields/Fields.vue +441 -0
  39. package/dist/runtime/components/ui/fields/Fields.vue.d.ts +376 -0
  40. package/dist/runtime/components/ui/fields-configurator/FieldsConfiguratorDialog.d.vue.ts +163 -0
  41. package/dist/runtime/components/ui/fields-configurator/FieldsConfiguratorDialog.vue +363 -0
  42. package/dist/runtime/components/ui/fields-configurator/FieldsConfiguratorDialog.vue.d.ts +163 -0
  43. package/dist/runtime/components/ui/input/Input.d.vue.ts +1 -0
  44. package/dist/runtime/components/ui/input/Input.vue +3 -1
  45. package/dist/runtime/components/ui/input/Input.vue.d.ts +1 -0
  46. package/dist/runtime/components/ui/input-group/InputGroup.vue +3 -0
  47. package/dist/runtime/components/ui/input-group/InputGroupAddon.vue +4 -1
  48. package/dist/runtime/components/ui/input-group/InputGroupCombobox.d.vue.ts +11 -3
  49. package/dist/runtime/components/ui/input-group/InputGroupCombobox.vue +16 -5
  50. package/dist/runtime/components/ui/input-group/InputGroupCombobox.vue.d.ts +11 -3
  51. package/dist/runtime/components/ui/input-group/InputGroupComboboxInput.d.vue.ts +8 -1
  52. package/dist/runtime/components/ui/input-group/InputGroupComboboxInput.vue +12 -1
  53. package/dist/runtime/components/ui/input-group/InputGroupComboboxInput.vue.d.ts +8 -1
  54. package/dist/runtime/components/ui/input-group/InputGroupInput.vue +1 -1
  55. package/dist/runtime/components/ui/input-group/InputGroupNumberField.d.vue.ts +5 -2
  56. package/dist/runtime/components/ui/input-group/InputGroupNumberField.vue +10 -4
  57. package/dist/runtime/components/ui/input-group/InputGroupNumberField.vue.d.ts +5 -2
  58. package/dist/runtime/components/ui/input-group/InputGroupText.vue +1 -1
  59. package/dist/runtime/components/ui/input-group/InputGroupTextarea.vue +1 -1
  60. package/dist/runtime/components/ui/input-group/index.js +2 -2
  61. package/dist/runtime/components/ui/label/Label.vue +1 -1
  62. package/dist/runtime/components/ui/locale/Locale.d.vue.ts +20 -0
  63. package/dist/runtime/components/ui/locale/Locale.vue +291 -0
  64. package/dist/runtime/components/ui/locale/Locale.vue.d.ts +20 -0
  65. package/dist/runtime/components/ui/locale/index.d.ts +1 -0
  66. package/dist/runtime/components/ui/locale/index.js +1 -0
  67. package/dist/runtime/components/ui/native-select/NativeSelect.vue +3 -3
  68. package/dist/runtime/components/ui/native-select/NativeSelectOption.d.vue.ts +1 -0
  69. package/dist/runtime/components/ui/native-select/NativeSelectOption.vue +4 -1
  70. package/dist/runtime/components/ui/native-select/NativeSelectOption.vue.d.ts +1 -0
  71. package/dist/runtime/components/ui/navigation-menu/NavigationMenuLink.vue +1 -1
  72. package/dist/runtime/components/ui/navigation-menu/NavigationMenuViewport.vue +1 -1
  73. package/dist/runtime/components/ui/number-field/NumberFieldInput.vue +1 -1
  74. package/dist/runtime/components/ui/range-calendar/RangeCalendarCell.vue +1 -1
  75. package/dist/runtime/components/ui/range-calendar/RangeCalendarCellTrigger.vue +1 -1
  76. package/dist/runtime/components/ui/sheet/SheetOverlay.vue +1 -1
  77. package/dist/runtime/components/ui/switch/Switch.d.vue.ts +24 -0
  78. package/dist/runtime/components/ui/switch/Switch.vue +46 -0
  79. package/dist/runtime/components/ui/switch/Switch.vue.d.ts +24 -0
  80. package/dist/runtime/components/ui/switch/index.d.ts +1 -0
  81. package/dist/runtime/components/ui/switch/index.js +1 -0
  82. package/dist/runtime/components/ui/table/Table.d.vue.ts +81 -0
  83. package/dist/runtime/components/ui/table/Table.vue +792 -0
  84. package/dist/runtime/components/ui/table/Table.vue.d.ts +81 -0
  85. package/dist/runtime/components/ui/table/schema.d.ts +48 -0
  86. package/dist/runtime/components/ui/table/schema.js +126 -0
  87. package/dist/runtime/components/ui/table-configurator/TableConfiguratorDialog.d.vue.ts +62 -0
  88. package/dist/runtime/components/ui/table-configurator/TableConfiguratorDialog.vue +2233 -0
  89. package/dist/runtime/components/ui/table-configurator/TableConfiguratorDialog.vue.d.ts +62 -0
  90. package/dist/runtime/components/ui/table-configurator/menu.d.ts +37 -0
  91. package/dist/runtime/components/ui/table-configurator/menu.js +227 -0
  92. package/dist/runtime/components/ui/tabs/Tabs.d.vue.ts +24 -0
  93. package/dist/runtime/components/ui/tabs/Tabs.vue +30 -0
  94. package/dist/runtime/components/ui/tabs/Tabs.vue.d.ts +24 -0
  95. package/dist/runtime/components/ui/tabs/TabsContent.d.vue.ts +18 -0
  96. package/dist/runtime/components/ui/tabs/TabsContent.vue +23 -0
  97. package/dist/runtime/components/ui/tabs/TabsContent.vue.d.ts +18 -0
  98. package/dist/runtime/components/ui/tabs/TabsList.d.vue.ts +18 -0
  99. package/dist/runtime/components/ui/tabs/TabsList.vue +25 -0
  100. package/dist/runtime/components/ui/tabs/TabsList.vue.d.ts +18 -0
  101. package/dist/runtime/components/ui/tabs/TabsTrigger.d.vue.ts +18 -0
  102. package/dist/runtime/components/ui/tabs/TabsTrigger.vue +27 -0
  103. package/dist/runtime/components/ui/tabs/TabsTrigger.vue.d.ts +18 -0
  104. package/dist/runtime/components/ui/tabs/index.d.ts +4 -0
  105. package/dist/runtime/components/ui/tabs/index.js +4 -0
  106. package/dist/runtime/components/ui/textarea/Textarea.d.vue.ts +1 -0
  107. package/dist/runtime/components/ui/textarea/Textarea.vue +4 -2
  108. package/dist/runtime/components/ui/textarea/Textarea.vue.d.ts +1 -0
  109. package/dist/runtime/components/ui/toggle/Toggle.d.vue.ts +34 -0
  110. package/dist/runtime/components/ui/toggle/Toggle.vue +32 -0
  111. package/dist/runtime/components/ui/toggle/Toggle.vue.d.ts +34 -0
  112. package/dist/runtime/components/ui/toggle/index.d.ts +7 -0
  113. package/dist/runtime/components/ui/toggle/index.js +22 -0
  114. package/dist/runtime/composables/useTableRenderers.d.ts +2 -1
  115. package/dist/runtime/composables/useTableRenderers.js +2 -1
  116. package/dist/runtime/plugins/cel/env.d.ts +2 -2
  117. package/dist/runtime/plugins/cel/env.js +5 -4
  118. package/dist/runtime/plugins/cel/index.d.ts +3 -3
  119. package/dist/runtime/plugins/cel/index.js +7 -3
  120. package/dist/runtime/plugins/markdown/index.d.ts +1 -1
  121. package/dist/runtime/style.css +1 -1
  122. package/dist/runtime/table-renderers/builtins.js +213 -98
  123. package/dist/runtime/table-renderers/registry.d.ts +1 -0
  124. package/dist/runtime/table-renderers/registry.js +3 -0
  125. package/dist/runtime/utils/coders.d.ts +32 -0
  126. package/dist/runtime/utils/coders.js +64 -0
  127. package/dist/runtime/vendor/cel/index.d.ts +17 -0
  128. package/dist/runtime/vendor/cel/index.js +10 -0
  129. package/dist/runtime/vendor/cel-js/LICENSE +21 -0
  130. package/dist/runtime/vendor/cel-js/UPSTREAM.md +17 -0
  131. package/dist/runtime/vendor/cel-js/lib/errors.d.ts +21 -0
  132. package/dist/runtime/vendor/cel-js/lib/errors.js +97 -0
  133. package/dist/runtime/vendor/cel-js/lib/evaluator.d.ts +4 -0
  134. package/dist/runtime/vendor/cel-js/lib/evaluator.js +192 -0
  135. package/dist/runtime/vendor/cel-js/lib/functions.d.ts +53 -0
  136. package/dist/runtime/vendor/cel-js/lib/functions.js +513 -0
  137. package/dist/runtime/vendor/cel-js/lib/globals.d.ts +27 -0
  138. package/dist/runtime/vendor/cel-js/lib/globals.js +33 -0
  139. package/dist/runtime/vendor/cel-js/lib/index.d.ts +469 -0
  140. package/dist/runtime/vendor/cel-js/lib/index.js +18 -0
  141. package/dist/runtime/vendor/cel-js/lib/macros.d.ts +1 -0
  142. package/dist/runtime/vendor/cel-js/lib/macros.js +230 -0
  143. package/dist/runtime/vendor/cel-js/lib/operators.d.ts +117 -0
  144. package/dist/runtime/vendor/cel-js/lib/operators.js +739 -0
  145. package/dist/runtime/vendor/cel-js/lib/optional.d.ts +14 -0
  146. package/dist/runtime/vendor/cel-js/lib/optional.js +161 -0
  147. package/dist/runtime/vendor/cel-js/lib/options.d.ts +23 -0
  148. package/dist/runtime/vendor/cel-js/lib/options.js +47 -0
  149. package/dist/runtime/vendor/cel-js/lib/overloads.d.ts +1 -0
  150. package/dist/runtime/vendor/cel-js/lib/overloads.js +214 -0
  151. package/dist/runtime/vendor/cel-js/lib/parser.d.ts +56 -0
  152. package/dist/runtime/vendor/cel-js/lib/parser.js +827 -0
  153. package/dist/runtime/vendor/cel-js/lib/registry.d.ts +279 -0
  154. package/dist/runtime/vendor/cel-js/lib/registry.js +1596 -0
  155. package/dist/runtime/vendor/cel-js/lib/serialize.d.ts +1 -0
  156. package/dist/runtime/vendor/cel-js/lib/serialize.js +259 -0
  157. package/dist/runtime/vendor/cel-js/lib/type-checker.d.ts +26 -0
  158. package/dist/runtime/vendor/cel-js/lib/type-checker.js +81 -0
  159. package/package.json +9 -4
  160. package/dist/runtime/components/locale.d.vue.ts +0 -14
  161. package/dist/runtime/components/locale.vue +0 -89
  162. package/dist/runtime/components/locale.vue.d.ts +0 -14
  163. package/dist/runtime/components/query.d.vue.ts +0 -30
  164. package/dist/runtime/components/query.vue +0 -266
  165. package/dist/runtime/components/query.vue.d.ts +0 -30
  166. package/dist/runtime/utilities/query-config/global.d.ts +0 -4
  167. package/dist/runtime/utilities/query-config/global.js +0 -18
  168. package/dist/runtime/utilities/query-config/index.d.ts +0 -3
  169. package/dist/runtime/utilities/query-config/index.js +0 -14
  170. package/dist/runtime/utilities/query-config/schema.d.ts +0 -96
  171. package/dist/runtime/utilities/query-config/schema.js +0 -51
  172. /package/dist/runtime/components/{logo.d.vue.ts → ui/logo/Logo.d.vue.ts} +0 -0
  173. /package/dist/runtime/components/{logo.vue → ui/logo/Logo.vue} +0 -0
  174. /package/dist/runtime/components/{logo.vue.d.ts → ui/logo/Logo.vue.d.ts} +0 -0
@@ -0,0 +1,1596 @@
1
+ import {EvaluationError} from './errors.js'
2
+ import {UnsignedInt} from './functions.js'
3
+ import {Optional, OPTIONAL_NONE, toggleOptionalTypes} from './optional.js'
4
+ import {isAsync, hasOwn, objFreeze, objKeys, objEntries, RESERVED} from './globals.js'
5
+
6
+ export class Type {
7
+ #name
8
+ constructor(name) {
9
+ this.#name = name
10
+ objFreeze(this)
11
+ }
12
+
13
+ get name() {
14
+ return this.#name
15
+ }
16
+
17
+ get [Symbol.toStringTag]() {
18
+ return `Type<${this.#name}>`
19
+ }
20
+
21
+ toString() {
22
+ return `Type<${this.#name}>`
23
+ }
24
+ }
25
+
26
+ export const TYPES = {
27
+ string: new Type('string'),
28
+ bool: new Type('bool'),
29
+ int: new Type('int'),
30
+ uint: new Type('uint'),
31
+ double: new Type('double'),
32
+ map: new Type('map'),
33
+ list: new Type('list'),
34
+ bytes: new Type('bytes'),
35
+ null_type: new Type('null'),
36
+ type: new Type('type')
37
+ }
38
+
39
+ // not exposed to cel expression
40
+ const optionalType = new Type('optional')
41
+
42
+ export class TypeDeclaration {
43
+ #matchesCache = new WeakMap()
44
+ constructor({kind, type, name, keyType, valueType}) {
45
+ this.kind = kind
46
+ this.type = type
47
+ this.name = name
48
+ this.keyType = keyType
49
+ this.valueType = valueType
50
+
51
+ this.unwrappedType = kind === 'dyn' && valueType ? valueType.unwrappedType : this
52
+ this.wrappedType = kind === 'dyn' ? this : _createDynType(this.unwrappedType)
53
+
54
+ this.hasDynType =
55
+ this.kind === 'dyn' || this.valueType?.hasDynType || this.keyType?.hasDynType || false
56
+
57
+ this.hasPlaceholderType =
58
+ this.kind === 'param' ||
59
+ this.keyType?.hasPlaceholderType ||
60
+ this.valueType?.hasPlaceholderType ||
61
+ false
62
+
63
+ if (kind === 'list') this.fieldLazy = this.#getListField
64
+ else if (kind === 'map') this.fieldLazy = this.#getMapField
65
+ else if (kind === 'message') this.fieldLazy = this.#getMessageField
66
+ else if (kind === 'optional') this.fieldLazy = this.#getOptionalField
67
+
68
+ objFreeze(this)
69
+ }
70
+
71
+ /** @deprecated Please use .hasDynType */
72
+ hasDyn() {
73
+ return this.hasDynType
74
+ }
75
+
76
+ /** @deprecated Please use .hasDynType === false */
77
+ hasNoDynTypes() {
78
+ return this.hasDynType === false
79
+ }
80
+
81
+ isDynOrBool() {
82
+ return this.type === 'bool' || this.kind === 'dyn'
83
+ }
84
+
85
+ isEmpty() {
86
+ return this.valueType && this.valueType.kind === 'param'
87
+ }
88
+
89
+ /** @deprecated Please use .hasPlaceholderType */
90
+ hasPlaceholder() {
91
+ return this.hasPlaceholderType
92
+ }
93
+
94
+ unify(r, t2) {
95
+ const t1 = this
96
+ if (t1 === t2 || t1.kind === 'dyn' || t2.kind === 'param') return t1
97
+ if (t2.kind === 'dyn' || t1.kind === 'param') return t2
98
+ if (t1.kind !== t2.kind) return null
99
+ if (!(t1.hasPlaceholderType || t2.hasPlaceholderType || t1.hasDynType || t2.hasDynType))
100
+ return null
101
+
102
+ const valueType = t1.valueType.unify(r, t2.valueType)
103
+ if (!valueType) return null
104
+ switch (t1.kind) {
105
+ case 'optional':
106
+ return r.getOptionalType(valueType)
107
+ case 'list':
108
+ return r.getListType(valueType)
109
+ case 'map':
110
+ const keyType = t1.keyType.unify(r, t2.keyType)
111
+ return keyType ? r.getMapType(keyType, valueType) : null
112
+ }
113
+ }
114
+
115
+ templated(r, bind) {
116
+ if (!this.hasPlaceholderType) return this
117
+
118
+ switch (this.kind) {
119
+ case 'dyn':
120
+ return this.valueType.templated(r, bind)
121
+ case 'param':
122
+ return bind?.get(this.name) || this
123
+ case 'map':
124
+ return r.getMapType(this.keyType.templated(r, bind), this.valueType.templated(r, bind))
125
+ case 'list':
126
+ return r.getListType(this.valueType.templated(r, bind))
127
+ case 'optional':
128
+ return r.getOptionalType(this.valueType.templated(r, bind))
129
+ default:
130
+ return this
131
+ }
132
+ }
133
+
134
+ toString() {
135
+ return this.name
136
+ }
137
+
138
+ #getOptionalField(obj, key, ast, ev) {
139
+ obj = obj instanceof Optional ? obj.orValue() : obj
140
+ if (obj === undefined) return OPTIONAL_NONE
141
+
142
+ const type = ev.debugType(obj)
143
+ try {
144
+ return Optional.of(type.fieldLazy(obj, key, ast, ev))
145
+ } catch (e) {
146
+ if (e instanceof EvaluationError) return OPTIONAL_NONE
147
+ throw e
148
+ }
149
+ }
150
+
151
+ #getMessageField(obj, key, ast, ev) {
152
+ const message = obj ? ev.objectTypesByConstructor.get(obj.constructor) : undefined
153
+ if (!message) return
154
+
155
+ const type = message.fields ? message.fields[key] : dynType
156
+ if (!type) return undefined
157
+
158
+ const value = obj instanceof Map ? obj.get(key) : obj[key]
159
+ if (value === undefined) return
160
+
161
+ const valueType = ev.debugType(value)
162
+ if (type.matchesDebugType(valueType)) return value
163
+ throw new EvaluationError(`Field '${key}' is not of type '${type}', got '${valueType}'`, ast)
164
+ }
165
+
166
+ #getMapField(obj, key, ast, ev) {
167
+ if (obj instanceof Map) {
168
+ const value = obj.get(key)
169
+ if (value === undefined) return
170
+
171
+ const type = ev.debugType(value)
172
+ if (this.valueType.matchesDebugType(type)) return value
173
+
174
+ throw new EvaluationError(
175
+ `Field '${key}' is not of type '${this.valueType}', got '${type}'`,
176
+ ast
177
+ )
178
+ }
179
+
180
+ if (!obj) return
181
+
182
+ // Read through the proxy first so Vue can track missing-to-present updates.
183
+ const value = obj[key]
184
+ if (!hasOwn(obj, key) || value === undefined) return
185
+
186
+ const type = ev.debugType(value)
187
+ if (this.valueType.matchesDebugType(type)) return value
188
+
189
+ throw new EvaluationError(
190
+ `Field '${key}' is not of type '${this.valueType}', got '${type}'`,
191
+ ast
192
+ )
193
+ }
194
+
195
+ #getListElementAtIndex(list, pos) {
196
+ switch (list?.constructor) {
197
+ case Array:
198
+ return list[pos]
199
+ case Set: {
200
+ let i = 0
201
+ for (const item of list) {
202
+ if (i++ !== pos) continue
203
+ return item
204
+ }
205
+ }
206
+ }
207
+ }
208
+
209
+ #getListField(obj, key, ast, ev) {
210
+ if (typeof key === 'bigint') key = Number(key)
211
+ else if (typeof key !== 'number') return
212
+
213
+ const value = this.#getListElementAtIndex(obj, key)
214
+ if (value === undefined) {
215
+ if (!obj) return
216
+ throw new EvaluationError(
217
+ `No such key: index out of bounds, index ${key} ${
218
+ key < 0 ? '< 0' : `>= size ${obj.length || obj.size}`
219
+ }`,
220
+ ast
221
+ )
222
+ }
223
+
224
+ const type = ev.debugType(value)
225
+ if (this.valueType.matchesDebugType(type)) return value
226
+
227
+ throw new EvaluationError(
228
+ `List item with index '${key}' is not of type '${this.valueType}', got '${type}'`,
229
+ ast
230
+ )
231
+ }
232
+
233
+ fieldLazy() {}
234
+
235
+ field(obj, key, ast, ev) {
236
+ const v = this.fieldLazy(obj, key, ast, ev)
237
+ if (v !== undefined) return v
238
+ throw new EvaluationError(`No such key: ${key}`, ast)
239
+ }
240
+
241
+ matchesBoth(other) {
242
+ return this.matches(other) && other.matches(this)
243
+ }
244
+
245
+ matchesDebugType(o) {
246
+ return this === o || this === dynType || !!this.valueType
247
+ }
248
+
249
+ matches(o) {
250
+ const s = this.unwrappedType
251
+ o = o.unwrappedType
252
+ if (s === o || s.kind === 'dyn' || o.kind === 'dyn' || o.kind === 'param') return true
253
+ return this.#matchesCache.get(o) ?? this.#matchesCache.set(o, this.#matches(s, o)).get(o)
254
+ }
255
+
256
+ #matches(s, o) {
257
+ switch (s.kind) {
258
+ case 'dyn':
259
+ case 'param':
260
+ return true
261
+ case 'list':
262
+ return o.kind === 'list' && s.valueType.matches(o.valueType)
263
+ case 'map':
264
+ return o.kind === 'map' && s.keyType.matches(o.keyType) && s.valueType.matches(o.valueType)
265
+ case 'optional':
266
+ return o.kind === 'optional' && s.valueType.matches(o.valueType)
267
+ default:
268
+ return s.name === o.name
269
+ }
270
+ }
271
+ }
272
+
273
+ const macroEvaluateErr = `have a .callAst property or .evaluate(checker, macro, ctx) method.`
274
+ const macroTypeCheckErr = `have a .callAst property or .typeCheck(checker, macro, ctx) method.`
275
+ function wrapMacroExpander(name, handler) {
276
+ const p = `Macro '${name}' must`
277
+ return function macroExpander(opts) {
278
+ const macro = handler(opts)
279
+ if (!macro || typeof macro !== 'object') throw new Error(`${p} return an object.`)
280
+ if (macro.callAst) return macro
281
+ if (!macro.evaluate) throw new Error(`${p} ${macroEvaluateErr}`)
282
+ if (!macro.typeCheck) throw new Error(`${p} ${macroTypeCheckErr}`)
283
+ return macro
284
+ }
285
+ }
286
+
287
+ export class VariableDeclaration {
288
+ constructor(name, type, description, value) {
289
+ this.name = name
290
+ this.type = type
291
+ this.description = description ?? null
292
+ this.constant = value !== undefined
293
+ this.value = value
294
+ objFreeze(this)
295
+ }
296
+ }
297
+
298
+ export class FunctionDeclaration {
299
+ constructor({name, receiverType, returnType, handler, description, params, async}) {
300
+ if (typeof name !== 'string') throw new Error('name must be a string')
301
+ if (typeof handler !== 'function') throw new Error('handler must be a function')
302
+
303
+ this.name = name
304
+ this.async = isAsync(handler, async)
305
+ this.receiverType = receiverType ?? null
306
+ this.returnType = returnType
307
+ this.description = description ?? null
308
+ this.params = params
309
+ this.argTypes = params.map((p) => p.type)
310
+ this.macro = this.argTypes.includes(astType)
311
+
312
+ const receiverString = receiverType ? `${receiverType}.` : ''
313
+ this.signature = `${receiverString}${name}(${this.argTypes.join(', ')}): ${returnType}`
314
+ this.handler = this.macro ? wrapMacroExpander(this.signature, handler) : handler
315
+ this.partitionKey = `${receiverType ? 'rcall' : 'call'}:${name}:${params.length}`
316
+
317
+ this.hasPlaceholderType =
318
+ this.returnType.hasPlaceholderType ||
319
+ this.receiverType?.hasPlaceholderType ||
320
+ this.argTypes.some((t) => t.hasPlaceholderType) ||
321
+ false
322
+
323
+ objFreeze(this)
324
+ }
325
+
326
+ hasPlaceholder() {
327
+ return this.hasPlaceholderType
328
+ }
329
+
330
+ matchesArgs(argTypes) {
331
+ return argTypes.length === this.argTypes.length &&
332
+ this.argTypes.every((t, i) => t.matches(argTypes[i]))
333
+ ? this
334
+ : null
335
+ }
336
+ }
337
+
338
+ export class OperatorDeclaration {
339
+ constructor({op, leftType, rightType, handler, returnType, async}) {
340
+ this.operator = op
341
+ this.leftType = leftType
342
+ this.rightType = rightType || null
343
+ this.handler = handler
344
+ this.async = isAsync(handler, async)
345
+ this.returnType = returnType
346
+
347
+ if (rightType) this.signature = `${leftType} ${op} ${rightType}: ${returnType}`
348
+ else this.signature = `${op}${leftType}: ${returnType}`
349
+
350
+ this.hasPlaceholderType =
351
+ this.leftType.hasPlaceholderType || this.rightType?.hasPlaceholderType || false
352
+
353
+ objFreeze(this)
354
+ }
355
+
356
+ hasPlaceholder() {
357
+ return this.hasPlaceholderType
358
+ }
359
+
360
+ equals(other) {
361
+ return (
362
+ this.operator === other.operator &&
363
+ this.leftType === other.leftType &&
364
+ this.rightType === other.rightType
365
+ )
366
+ }
367
+ }
368
+
369
+ function _createListType(valueType) {
370
+ return new TypeDeclaration({
371
+ kind: 'list',
372
+ name: `list<${valueType}>`,
373
+ type: 'list',
374
+ valueType
375
+ })
376
+ }
377
+
378
+ function _createPrimitiveType(name) {
379
+ return new TypeDeclaration({kind: 'primitive', name, type: name})
380
+ }
381
+
382
+ function _createMessageType(name) {
383
+ return new TypeDeclaration({kind: 'message', name, type: name})
384
+ }
385
+
386
+ function _createDynType(valueType) {
387
+ const name = valueType ? `dyn<${valueType}>` : 'dyn'
388
+ return new TypeDeclaration({kind: 'dyn', name, type: name, valueType})
389
+ }
390
+
391
+ function _createOptionalType(valueType) {
392
+ const name = `optional<${valueType}>`
393
+ return new TypeDeclaration({kind: 'optional', name, type: 'optional', valueType})
394
+ }
395
+
396
+ function _createMapType(keyType, valueType) {
397
+ return new TypeDeclaration({
398
+ kind: 'map',
399
+ name: `map<${keyType}, ${valueType}>`,
400
+ type: 'map',
401
+ keyType: keyType,
402
+ valueType: valueType
403
+ })
404
+ }
405
+
406
+ function _createPlaceholderType(name) {
407
+ return new TypeDeclaration({kind: 'param', name, type: name})
408
+ }
409
+
410
+ // Global immutable cache for built-in primitive types (shared across all registries)
411
+ const dynType = _createDynType()
412
+ const astType = _createPrimitiveType('ast')
413
+ const listType = _createListType(dynType)
414
+ const mapType = _createMapType(dynType, dynType)
415
+ export const celTypes = {
416
+ string: _createPrimitiveType('string'),
417
+ bool: _createPrimitiveType('bool'),
418
+ int: _createPrimitiveType('int'),
419
+ uint: _createPrimitiveType('uint'),
420
+ double: _createPrimitiveType('double'),
421
+ bytes: _createPrimitiveType('bytes'),
422
+ dyn: dynType,
423
+ null: _createPrimitiveType('null'),
424
+ type: _createPrimitiveType('type'),
425
+ optional: _createOptionalType(dynType),
426
+ list: listType,
427
+ 'list<dyn>': listType,
428
+ map: mapType,
429
+ 'map<dyn, dyn>': mapType
430
+ }
431
+
432
+ for (const t of [celTypes.string, celTypes.double, celTypes.int]) {
433
+ const list = _createListType(t)
434
+ const map = _createMapType(celTypes.string, t)
435
+ celTypes[list.name] = list
436
+ celTypes[map.name] = map
437
+ }
438
+
439
+ Object.freeze(celTypes)
440
+
441
+ class Candidates {
442
+ returnType = null
443
+ async = false
444
+ macro = false
445
+ #matchCache = null
446
+ #checkCache = null
447
+ /** @type {Array<FunctionDeclaration>|Array<OperatorDeclaration>} */
448
+ declarations = []
449
+ constructor(registry) {
450
+ this.registry = registry
451
+ }
452
+
453
+ [Symbol.iterator]() {
454
+ return this.declarations[Symbol.iterator]()
455
+ }
456
+
457
+ add(decl) {
458
+ this.returnType =
459
+ (this.returnType || decl.returnType).unify(this.registry, decl.returnType) || dynType
460
+
461
+ if (decl.macro) this.macro = decl
462
+ if (decl.async && !this.async) this.async = true
463
+ this.declarations.push(decl)
464
+ this.#matchCache?.clear()
465
+ this.#checkCache?.clear()
466
+ }
467
+
468
+ findFunction(argTypes, receiverType = null) {
469
+ for (let i = 0; i < this.declarations.length; i++) {
470
+ const match = this.#matchesFunction(this.declarations[i], argTypes, receiverType)
471
+ if (match) return match
472
+ }
473
+ return null
474
+ }
475
+
476
+ findUnaryOverload(left) {
477
+ const cached = (this.#matchCache ??= new Map()).get(left)
478
+ if (cached !== undefined) return cached
479
+
480
+ let value = false
481
+ for (const decl of this.declarations) {
482
+ if (decl.leftType !== left) continue
483
+ value = decl
484
+ break
485
+ }
486
+
487
+ this.#matchCache.set(left, value)
488
+ return value
489
+ }
490
+
491
+ findBinaryOverload(left, right) {
492
+ if (left.kind === 'dyn' && left.valueType) right = right.wrappedType
493
+ else if (right.kind === 'dyn' && right.valueType) left = left.wrappedType
494
+ return (
495
+ (this.#matchCache ??= new Map()).get(left)?.get(right) ??
496
+ this.#cacheBinary(this.#matchCache, left, right, this.#findBinaryUncached(left, right))
497
+ )
498
+ }
499
+
500
+ checkBinaryOverload(left, right) {
501
+ return (
502
+ (this.#checkCache ??= new Map()).get(left)?.get(right) ??
503
+ this.#cacheBinary(this.#checkCache, left, right, this.#checkBinaryUncached(left, right))
504
+ )
505
+ }
506
+
507
+ #cacheBinary(cache, left, right, result) {
508
+ cache = cache.get(left) || cache.set(left, new Map()).get(left)
509
+ return (cache.set(right, result), result)
510
+ }
511
+
512
+ #findBinaryUncached(left, right) {
513
+ const ops = this.#findBinaryOverloads(left, right)
514
+ if (ops.length === 0) return false
515
+ if (ops.length === 1) return ops[0]
516
+ throw new Error(`Operator overload '${ops[0].signature}' overlaps with '${ops[1].signature}'.`)
517
+ }
518
+
519
+ #checkBinaryUncached(left, right) {
520
+ const ops = this.#findBinaryOverloads(left, right)
521
+ if (ops.length === 0) return false
522
+ let rt = ops[0].returnType
523
+ for (let i = 1; i < ops.length; i++) rt = rt.unify(this.registry, ops[i].returnType) || dynType
524
+ return rt
525
+ }
526
+
527
+ #findBinaryOverloads(leftType, rightType) {
528
+ const nonexactMatches = []
529
+ for (const decl of this.declarations) {
530
+ if (decl.leftType === leftType && decl.rightType === rightType) return [decl]
531
+ const secondary = this.#matchBinaryOverload(decl, leftType, rightType)
532
+ if (secondary) nonexactMatches.push(secondary)
533
+ }
534
+
535
+ if (nonexactMatches.length === 0) {
536
+ const op = this.declarations[0]?.operator
537
+ if ((op === '==' || op === '!=') && leftType.kind === 'dyn') {
538
+ return fallbackDynEqualityMatchers[op]
539
+ }
540
+ }
541
+
542
+ return nonexactMatches
543
+ }
544
+
545
+ #matchBinaryOverload(decl, actualLeft, actualRight) {
546
+ const bindings = decl.hasPlaceholderType ? new Map() : null
547
+ const leftType = this.registry.matchTypeWithPlaceholders(decl.leftType, actualLeft, bindings)
548
+ if (!leftType) return
549
+ const rightType = this.registry.matchTypeWithPlaceholders(decl.rightType, actualRight, bindings)
550
+ if (!rightType) return
551
+
552
+ if (
553
+ (decl.operator === '==' || decl.operator === '!=') &&
554
+ decl.leftType.kind === 'dyn' &&
555
+ decl.leftType.valueType &&
556
+ actualLeft.kind !== 'dyn' &&
557
+ actualRight.kind !== 'dyn'
558
+ )
559
+ return false
560
+
561
+ return decl.hasPlaceholderType
562
+ ? {
563
+ async: decl.async,
564
+ signature: decl.signature,
565
+ handler: decl.handler,
566
+ leftType,
567
+ rightType,
568
+ returnType: decl.returnType.templated(this.registry, bindings)
569
+ }
570
+ : decl
571
+ }
572
+
573
+ #matchesFunction(fn, argTypes, receiverType) {
574
+ if (fn.hasPlaceholderType) return this.#matchWithPlaceholders(fn, argTypes, receiverType)
575
+ if (receiverType && fn.receiverType && !receiverType.matches(fn.receiverType)) return
576
+ return fn.matchesArgs(argTypes)
577
+ }
578
+
579
+ #matchWithPlaceholders(fn, argTypes, receiverType) {
580
+ const bindings = new Map()
581
+ if (receiverType && fn.receiverType) {
582
+ if (!this.registry.matchTypeWithPlaceholders(fn.receiverType, receiverType, bindings)) {
583
+ return null
584
+ }
585
+ }
586
+
587
+ for (let i = 0; i < argTypes.length; i++) {
588
+ if (!this.registry.matchTypeWithPlaceholders(fn.argTypes[i], argTypes[i], bindings)) {
589
+ return null
590
+ }
591
+ }
592
+
593
+ return {
594
+ async: fn.async,
595
+ handler: fn.handler,
596
+ signature: fn.signature,
597
+ returnType: fn.returnType.templated(this.registry, bindings)
598
+ }
599
+ }
600
+ }
601
+
602
+ // Helper function for splitting map type parameters
603
+ function splitByComma(str) {
604
+ const parts = []
605
+ let current = ''
606
+ let depth = 0
607
+
608
+ for (const char of str) {
609
+ if (char === '<') depth++
610
+ else if (char === '>') depth--
611
+ else if (char === ',' && depth === 0) {
612
+ parts.push(current.trim())
613
+ current = ''
614
+ continue
615
+ }
616
+ current += char
617
+ }
618
+
619
+ if (current) parts.push(current.trim())
620
+ return parts
621
+ }
622
+
623
+ const objTypesDecls = [
624
+ [UnsignedInt, 'uint', TYPES.uint, celTypes.uint],
625
+ [Type, 'type', TYPES.type, celTypes.type],
626
+ [Optional, 'optional', optionalType, celTypes.optional],
627
+ [Uint8Array, 'bytes', TYPES.bytes, celTypes.bytes],
628
+ ...(typeof Buffer !== 'undefined' ? [[Buffer, 'bytes', TYPES.bytes, celTypes.bytes]] : [])
629
+ ].map(([ctor, name, typeType, type]) => Object.freeze({name, typeType, type, ctor}))
630
+
631
+ const objTypes = objTypesDecls.map((t) => [t.name, t])
632
+ const objTypesCtor = objTypesDecls.map((t) => [t.ctor, t])
633
+
634
+ const invalidVar = (postfix) => new Error(`Invalid variable declaration: ${postfix}`)
635
+ const invalidType = (postfix) => new Error(`Invalid type declaration: ${postfix}`)
636
+
637
+ const fallbackDynEqualityMatchers = {
638
+ '==': [{handler: (a, b) => a === b, returnType: celTypes.bool}],
639
+ '!=': [{handler: (a, b) => a !== b, returnType: celTypes.bool}]
640
+ }
641
+
642
+ export class Registry {
643
+ #parent = null
644
+ #typeDeclarations
645
+
646
+ #ownsVariables = true
647
+ #operators = null
648
+ #functions = null
649
+ #operatorsByOp = null
650
+ #functionsByKey = null
651
+ #listTypes = null
652
+ #mapTypes = null
653
+ #optionalTypes = null
654
+ #others = null
655
+
656
+ #locked = false
657
+
658
+ constructor(opts = {}) {
659
+ this.enableOptionalTypes = opts.enableOptionalTypes ?? false
660
+ this.unlistedVariablesAreDyn = opts.unlistedVariablesAreDyn ?? false
661
+
662
+ const parent = opts.parent instanceof Registry ? opts.parent : null
663
+ if (parent) {
664
+ this.#parent = parent
665
+
666
+ let opParent = parent
667
+ while (opParent && !opParent.#operators) opParent = opParent.#parent
668
+
669
+ let fnParent = parent
670
+ while (fnParent && !fnParent.#functions) fnParent = fnParent.#parent
671
+
672
+ this.#operatorsByOp = parent.#operatorsByOp
673
+ this.#functionsByKey = parent.#functionsByKey
674
+ this.#others = {operators: opParent.#operators, functions: fnParent.#functions}
675
+
676
+ this.objectTypes = new Map(parent.objectTypes)
677
+ this.objectTypesByConstructor = new Map(parent.objectTypesByConstructor)
678
+ this.variables = parent.variables
679
+ this.#ownsVariables = false
680
+ this.#typeDeclarations = parent.#typeDeclarations
681
+ this.#listTypes = parent.#listTypes
682
+ this.#mapTypes = parent.#mapTypes
683
+ this.#optionalTypes = parent.#optionalTypes
684
+
685
+ if (
686
+ this.enableOptionalTypes !== parent.enableOptionalTypes ||
687
+ this.unlistedVariablesAreDyn !== parent.unlistedVariablesAreDyn
688
+ ) {
689
+ toggleOptionalTypes(this, this.enableOptionalTypes)
690
+ }
691
+ } else {
692
+ this.#operators = []
693
+ this.#functions = []
694
+ this.objectTypes = new Map(objTypes)
695
+ this.objectTypesByConstructor = new Map(objTypesCtor)
696
+ this.#typeDeclarations = new Map(objEntries(celTypes))
697
+ this.#listTypes = new Map()
698
+ this.#mapTypes = new Map()
699
+ this.#optionalTypes = new Map()
700
+ this.variables = new Map()
701
+ this.variables.dyn = this.unlistedVariablesAreDyn
702
+ for (const n in TYPES) this.registerConstant(n, 'type', TYPES[n])
703
+ }
704
+ }
705
+
706
+ #ensureOwnVariables() {
707
+ if (this.#ownsVariables) return
708
+ this.variables = new Map(this.variables)
709
+ this.variables.dyn = this.unlistedVariablesAreDyn
710
+ this.#ownsVariables = true
711
+ }
712
+
713
+ // Used by toggleOptionalTypes in optional.js to clear a variable before re-registering it
714
+ deleteVariable(name) {
715
+ this.#ensureOwnVariables()
716
+ this.variables.delete(name)
717
+ }
718
+
719
+ #pushOperator(decl) {
720
+ if (!this.#operators) this.#operatorsByOp = null
721
+ this.operatorCandidates(decl.operator).add(decl)
722
+ this.#operators.push(decl)
723
+ }
724
+
725
+ #pushFunction(decl) {
726
+ if (!this.#functions) this.#functionsByKey = null
727
+ this.#functionCandidates(decl.partitionKey).add(decl)
728
+ this.#functions.push(decl)
729
+ }
730
+
731
+ #ensureCandiate(c, key) {
732
+ return c.get(key) || c.set(key, new Candidates(this)).get(key)
733
+ }
734
+
735
+ #getOperators() {
736
+ if (this.#operators) return this.#operators
737
+ return (this.#operators = [...this.#others.operators])
738
+ }
739
+
740
+ #getFunctions() {
741
+ if (this.#functions) return this.#functions
742
+ return (this.#functions = [...this.#others.functions])
743
+ }
744
+
745
+ operatorCandidates(op) {
746
+ if (this.#operatorsByOp) return this.#ensureCandiate(this.#operatorsByOp, op)
747
+ const c = (this.#operatorsByOp = new Map())
748
+ for (const decl of this.#getOperators()) this.#ensureCandiate(c, decl.operator).add(decl)
749
+ return this.#ensureCandiate(c, op)
750
+ }
751
+
752
+ functionCandidates(rec, name, argLen) {
753
+ return this.#functionCandidates(`${rec ? 'rcall' : 'call'}:${name}:${argLen}`)
754
+ }
755
+
756
+ #functionCandidates(key) {
757
+ if (this.#functionsByKey) return this.#ensureCandiate(this.#functionsByKey, key)
758
+ const c = (this.#functionsByKey = new Map())
759
+ for (const decl of this.#getFunctions()) this.#ensureCandiate(c, decl.partitionKey).add(decl)
760
+ return this.#ensureCandiate(c, key)
761
+ }
762
+
763
+ registerVariable(name, type, opts) {
764
+ if (this.#locked) throw new Error('Cannot modify frozen registry')
765
+ let description = opts?.description
766
+ let value
767
+ if (
768
+ typeof name === 'string' &&
769
+ typeof type === 'object' &&
770
+ !(type instanceof TypeDeclaration)
771
+ ) {
772
+ description = type.description
773
+ value = type.value
774
+ if (type.schema) type = this.registerType({name: `$${name}`, schema: type.schema}).type
775
+ else type = type.type
776
+ } else if (typeof name === 'object') {
777
+ if (name.schema) type = this.registerType({name: `$${name.name}`, schema: name.schema}).type
778
+ else type = name.type
779
+ description = name.description
780
+ value = name.value
781
+ name = name.name
782
+ }
783
+
784
+ if (typeof name !== 'string' || !name) throw invalidVar(`name must be a string`)
785
+ if (RESERVED.has(name)) throw invalidVar(`'${name}' is a reserved name`)
786
+ if (this.variables.get(name) !== undefined) throw invalidVar(`'${name}' is already registered`)
787
+
788
+ if (typeof type === 'string') type = this.getType(type)
789
+ else if (!(type instanceof TypeDeclaration)) throw invalidVar(`type is required`)
790
+
791
+ this.#ensureOwnVariables()
792
+ this.variables.set(name, new VariableDeclaration(name, type, description, value))
793
+ return this
794
+ }
795
+
796
+ #registerSchemaAsType(name, schema) {
797
+ const fields = Object.create(null)
798
+ for (const key of objKeys(schema)) {
799
+ const def = schema[key]
800
+ if (typeof def === 'object' && def) {
801
+ fields[key] = this.registerType({name: `${name}.${key}`, schema: def}).type.name
802
+ } else if (typeof def === 'string') {
803
+ fields[key] = def
804
+ } else {
805
+ throw new Error(`Invalid field definition for '${name}.${key}'`)
806
+ }
807
+ }
808
+ return fields
809
+ }
810
+
811
+ registerConstant(name, type, value) {
812
+ if (typeof name === 'object') this.registerVariable(name)
813
+ else this.registerVariable({name, type, value})
814
+ return this
815
+ }
816
+
817
+ getType(typename) {
818
+ return this.#parseTypeString(typename, true)
819
+ }
820
+
821
+ getListType(type) {
822
+ return (
823
+ this.#listTypes.get(type) ||
824
+ this.#listTypes.set(type, this.#parseTypeString(`list<${type}>`, true)).get(type)
825
+ )
826
+ }
827
+
828
+ getMapType(a, b) {
829
+ return (
830
+ this.#mapTypes.get(a)?.get(b) ||
831
+ (this.#mapTypes.get(a) || this.#mapTypes.set(a, new Map()).get(a))
832
+ .set(b, this.#parseTypeString(`map<${a}, ${b}>`, true))
833
+ .get(b)
834
+ )
835
+ }
836
+
837
+ getOptionalType(type) {
838
+ return (
839
+ this.#optionalTypes.get(type) ||
840
+ this.#optionalTypes.set(type, this.#parseTypeString(`optional<${type}>`, true)).get(type)
841
+ )
842
+ }
843
+
844
+ assertType(typename, type, signature) {
845
+ try {
846
+ return this.#parseTypeString(typename, true)
847
+ } catch (e) {
848
+ e.message = `Invalid ${type} '${e.unknownType || typename}' in '${signature}'`
849
+ throw e
850
+ }
851
+ }
852
+
853
+ getFunctionType(typename) {
854
+ if (typename === 'ast') return astType
855
+ const t = this.#parseTypeString(typename, true)
856
+ if (t.kind === 'dyn' && t.valueType) throw new Error(`type '${t.name}' is not supported`)
857
+ return t
858
+ }
859
+
860
+ registerType(name, _d) {
861
+ if (this.#locked) throw new Error('Cannot modify frozen registry')
862
+ if (typeof name === 'object') ((_d = name), (name = _d.fullName || _d.name || _d.ctor?.name))
863
+ if (typeof name === 'string' && name[0] === '.') name = name.slice(1)
864
+ if (typeof name !== 'string' || name.length < 2 || RESERVED.has(name)) {
865
+ throw invalidType(`name '${name}' is not valid`)
866
+ }
867
+
868
+ if (this.objectTypes.has(name)) throw invalidType(`type '${name}' already registered`)
869
+
870
+ const type = this.#parseTypeString(name, false)
871
+ if (type.kind !== 'message') throw invalidType(`type '${name}' is not valid`)
872
+
873
+ const decl = {
874
+ name,
875
+ typeType: new Type(name),
876
+ type,
877
+ ctor: typeof _d === 'function' ? _d : _d?.ctor,
878
+ convert: typeof _d === 'function' ? undefined : _d?.convert,
879
+ fields:
880
+ typeof _d?.schema === 'object'
881
+ ? this.#normalizeFields(name, this.#registerSchemaAsType(name, _d.schema))
882
+ : this.#normalizeFields(name, typeof _d === 'function' ? undefined : _d?.fields)
883
+ }
884
+
885
+ if (typeof decl.ctor !== 'function') {
886
+ if (!decl.fields) throw invalidType(`type '${name}' requires a constructor or fields`)
887
+ Object.assign(decl, this.#createDefaultConvert(name, decl.fields))
888
+ }
889
+
890
+ this.objectTypes.set(name, Object.freeze(decl))
891
+ this.objectTypesByConstructor.set(decl.ctor, decl)
892
+ this.registerFunctionOverload(`type(${name}): type`, () => decl.typeType, {async: false})
893
+ return decl
894
+ }
895
+
896
+ /** @returns {TypeDeclaration} */
897
+ #parseTypeString(typeStr, requireKnownTypes = true) {
898
+ let match = this.#typeDeclarations.get(typeStr)
899
+ if (match) return match
900
+
901
+ if (typeof typeStr !== 'string' || !typeStr.length) {
902
+ throw new Error(`Invalid type: must be a string`)
903
+ }
904
+
905
+ match = typeStr.match(/^[A-Z]$/)
906
+ if (match) return this.#createDeclaration(_createPlaceholderType, typeStr, typeStr)
907
+
908
+ match = typeStr.match(/^(dyn|list|map|optional)<(.+)>$/)
909
+ if (!match) {
910
+ if (requireKnownTypes) {
911
+ const err = new Error(`Unknown type: ${typeStr}`)
912
+ err.unknownType = typeStr
913
+ throw err
914
+ }
915
+ return this.#createDeclaration(_createMessageType, typeStr, typeStr)
916
+ }
917
+
918
+ const kind = match[1]
919
+ const inner = match[2].trim()
920
+ switch (kind) {
921
+ case 'dyn': {
922
+ const type = this.#parseTypeString(inner, requireKnownTypes).wrappedType
923
+ this.#typeDeclarations.set(type.name, type)
924
+ return type
925
+ }
926
+ case 'list': {
927
+ const vType = this.#parseTypeString(inner, requireKnownTypes)
928
+ return this.#createDeclaration(_createListType, `list<${vType}>`, vType)
929
+ }
930
+ case 'map': {
931
+ const parts = splitByComma(inner)
932
+ if (parts.length !== 2) throw new Error(`Invalid map type: ${typeStr}`)
933
+ const kType = this.#parseTypeString(parts[0], requireKnownTypes)
934
+ const vType = this.#parseTypeString(parts[1], requireKnownTypes)
935
+ return this.#createDeclaration(_createMapType, `map<${kType}, ${vType}>`, kType, vType)
936
+ }
937
+ case 'optional': {
938
+ const vType = this.#parseTypeString(inner, requireKnownTypes)
939
+ return this.#createDeclaration(_createOptionalType, `optional<${vType}>`, vType)
940
+ }
941
+ }
942
+ }
943
+
944
+ #createDeclaration(creator, key, ...args) {
945
+ return (
946
+ this.#typeDeclarations.get(key) || this.#typeDeclarations.set(key, creator(...args)).get(key)
947
+ )
948
+ }
949
+
950
+ findMacro(name, hasReceiver, argLen) {
951
+ return this.functionCandidates(hasReceiver, name, argLen).macro
952
+ }
953
+
954
+ findUnaryOverload(op, left) {
955
+ return this.operatorCandidates(op).findUnaryOverload(left)
956
+ }
957
+
958
+ findBinaryOverload(op, left, right) {
959
+ return this.operatorCandidates(op).findBinaryOverload(left, right)
960
+ }
961
+
962
+ matchTypeWithPlaceholders(declared, actual, bindings) {
963
+ if (!declared.hasPlaceholderType) return actual.matches(declared) ? actual : null
964
+
965
+ const treatAsDyn = actual.kind === 'dyn'
966
+ if (!this.#collectPlaceholderBindings(declared, actual, bindings, treatAsDyn)) return null
967
+ if (treatAsDyn) return actual
968
+ return actual.matches(declared.templated(this, bindings)) ? actual : null
969
+ }
970
+
971
+ #bindPlaceholder(name, candidateType, bindings) {
972
+ const existing = bindings.get(name)
973
+ if (!existing) return bindings.set(name, candidateType) && true
974
+ return existing.kind === 'dyn' || candidateType.kind === 'dyn'
975
+ ? true
976
+ : existing.matchesBoth(candidateType)
977
+ }
978
+
979
+ #collectPlaceholderBindings(declared, actual, bindings, fromDyn = false) {
980
+ if (!declared.hasPlaceholderType) return true
981
+ if (!actual) return false
982
+
983
+ const treatAsDyn = fromDyn || actual.kind === 'dyn'
984
+ actual = actual.unwrappedType
985
+
986
+ switch (declared.kind) {
987
+ case 'param': {
988
+ const candidateType = treatAsDyn ? dynType : actual
989
+ return this.#bindPlaceholder(declared.name, candidateType, bindings)
990
+ }
991
+ case 'list': {
992
+ if (actual.name === 'dyn') actual = declared
993
+ if (actual.kind !== 'list') return false
994
+ return this.#collectPlaceholderBindings(
995
+ declared.valueType,
996
+ actual.valueType,
997
+ bindings,
998
+ treatAsDyn
999
+ )
1000
+ }
1001
+ case 'map': {
1002
+ if (actual.name === 'dyn') actual = declared
1003
+ if (actual.kind !== 'map') return false
1004
+ return (
1005
+ this.#collectPlaceholderBindings(
1006
+ declared.keyType,
1007
+ actual.keyType,
1008
+ bindings,
1009
+ treatAsDyn
1010
+ ) &&
1011
+ this.#collectPlaceholderBindings(
1012
+ declared.valueType,
1013
+ actual.valueType,
1014
+ bindings,
1015
+ treatAsDyn
1016
+ )
1017
+ )
1018
+ }
1019
+ case 'optional': {
1020
+ if (actual.name === 'dyn') actual = declared
1021
+ if (actual.kind !== 'optional') return false
1022
+ return this.#collectPlaceholderBindings(
1023
+ declared.valueType,
1024
+ actual.valueType,
1025
+ bindings,
1026
+ treatAsDyn
1027
+ )
1028
+ }
1029
+ }
1030
+ return true
1031
+ }
1032
+
1033
+ #toCelFieldType(field) {
1034
+ if (typeof field === 'string') return {type: field}
1035
+ if (field.id) return protobufjsFieldToCelType(field)
1036
+ return field
1037
+ }
1038
+
1039
+ #toCelFieldDeclaration(typename, fields, k, requireKnownTypes = false) {
1040
+ try {
1041
+ const field = this.#toCelFieldType(fields[k])
1042
+ if (typeof field?.type !== 'string') throw new Error(`unsupported declaration`)
1043
+ return this.#parseTypeString(field.type, requireKnownTypes)
1044
+ } catch (e) {
1045
+ e.message =
1046
+ `Field '${k}' in type '${typename}' has unsupported declaration: ` +
1047
+ `${JSON.stringify(fields[k])}`
1048
+ throw e
1049
+ }
1050
+ }
1051
+
1052
+ #normalizeFields(typename, fields) {
1053
+ if (!fields) return
1054
+ const all = Object.create(null)
1055
+ for (const k of objKeys(fields)) all[k] = this.#toCelFieldDeclaration(typename, fields, k)
1056
+ return all
1057
+ }
1058
+
1059
+ #createDefaultConvert(name, fields) {
1060
+ const keys = objKeys(fields)
1061
+
1062
+ const conversions = Object.create(null)
1063
+ for (const k of keys) {
1064
+ const type = fields[k]
1065
+ const decl = type.kind === 'message' && this.objectTypes.get(type.name)
1066
+ if (decl === false) conversions[k] = false
1067
+ else conversions[k] = decl.convert ? decl : false
1068
+ }
1069
+
1070
+ const Ctor = {
1071
+ [name]: class extends Map {
1072
+ #raw
1073
+ constructor(v) {
1074
+ super()
1075
+ this.#raw = v
1076
+ }
1077
+
1078
+ [Symbol.iterator]() {
1079
+ if (this.size !== keys.length) for (const k of keys) this.get(k)
1080
+ return super[Symbol.iterator]()
1081
+ }
1082
+
1083
+ get(field) {
1084
+ let v = super.get(field)
1085
+ if (v !== undefined || this.has(field)) return v
1086
+
1087
+ const dec = conversions[field]
1088
+ if (dec === undefined) return
1089
+
1090
+ v = this.#raw instanceof Map ? this.#raw.get(field) : this.#raw?.[field]
1091
+ if (dec && v && typeof v === 'object') {
1092
+ switch (v.constructor) {
1093
+ case undefined:
1094
+ case Object:
1095
+ case Map:
1096
+ v = dec.convert(v)
1097
+ }
1098
+ }
1099
+ return (super.set(field, v), v)
1100
+ }
1101
+ }
1102
+ }[name]
1103
+
1104
+ return {
1105
+ ctor: Ctor,
1106
+ convert(v) {
1107
+ if (!v) return
1108
+ if (v.constructor === Ctor) return v
1109
+ return new Ctor(v)
1110
+ }
1111
+ }
1112
+ }
1113
+
1114
+ clone(opts) {
1115
+ this.#locked = true
1116
+ return new Registry({
1117
+ parent: this,
1118
+ unlistedVariablesAreDyn: opts.unlistedVariablesAreDyn,
1119
+ enableOptionalTypes: opts.enableOptionalTypes
1120
+ })
1121
+ }
1122
+
1123
+ getDefinitions() {
1124
+ const variables = []
1125
+ const functions = []
1126
+ for (const [, varDecl] of this.variables) {
1127
+ if (!varDecl) continue
1128
+ variables.push({
1129
+ name: varDecl.name,
1130
+ description: varDecl.description || null,
1131
+ type: varDecl.type.name
1132
+ })
1133
+ }
1134
+
1135
+ for (const decl of this.#getFunctions()) {
1136
+ functions.push({
1137
+ signature: decl.signature,
1138
+ name: decl.name,
1139
+ description: decl.description,
1140
+ receiverType: decl.receiverType ? decl.receiverType.name : null,
1141
+ returnType: decl.returnType.name,
1142
+ params: decl.params.map((p) => ({
1143
+ name: p.name,
1144
+ type: p.type.name,
1145
+ description: p.description
1146
+ }))
1147
+ })
1148
+ }
1149
+
1150
+ return {variables, functions}
1151
+ }
1152
+
1153
+ #parseSignature(signature) {
1154
+ if (typeof signature !== 'string') throw new Error('Invalid signature: must be a string')
1155
+ const match = signature.match(/^(?:([a-zA-Z0-9.<>]+)\.)?(\w+)\((.*?)\):\s*(.+)$/)
1156
+ if (!match) throw new Error(`Invalid signature: ${signature}`)
1157
+ return {
1158
+ receiverType: match[1] || null,
1159
+ name: match[2],
1160
+ argTypes: splitByComma(match[3]),
1161
+ returnType: match[4].trim()
1162
+ }
1163
+ }
1164
+
1165
+ /**
1166
+ * @param {FunctionDeclaration} a
1167
+ * @param {FunctionDeclaration} b
1168
+ */
1169
+ #functionSignatureOverlaps(a, b) {
1170
+ if (a.name !== b.name) return false
1171
+ if (a.argTypes.length !== b.argTypes.length) return false
1172
+ if ((a.receiverType || b.receiverType) && (!a.receiverType || !b.receiverType)) return false
1173
+
1174
+ const isDifferentReceiver =
1175
+ a.receiverType !== b.receiverType && a.receiverType !== dynType && b.receiverType !== dynType
1176
+
1177
+ return (
1178
+ !isDifferentReceiver &&
1179
+ (b.macro ||
1180
+ a.macro ||
1181
+ b.argTypes.every((t, i) => {
1182
+ const o = a.argTypes[i]
1183
+ return t === o || t === dynType || o === dynType
1184
+ }))
1185
+ )
1186
+ }
1187
+
1188
+ /** @param {FunctionDeclaration} newDec */
1189
+ #checkOverlappingSignatures(newDec) {
1190
+ for (const decl of this.#functionCandidates(newDec.partitionKey)) {
1191
+ if (!this.#functionSignatureOverlaps(decl, newDec)) continue
1192
+ throw new Error(
1193
+ `Function signature '${newDec.signature}' overlaps with existing overload '${decl.signature}'.`
1194
+ )
1195
+ }
1196
+ }
1197
+
1198
+ #normalizeParam(i, aType, param) {
1199
+ if (!param) return {type: this.getFunctionType(aType), name: `arg${i}`, description: null}
1200
+
1201
+ const type = param.type || aType
1202
+ if (!type) throw new Error(`params[${i}].type is required`)
1203
+ if (aType && type !== aType) throw new Error(`params[${i}].type not equal to signature type`)
1204
+ return {
1205
+ name: param.name || `arg${i}`,
1206
+ type: this.getFunctionType(type),
1207
+ description: param.description ?? null
1208
+ }
1209
+ }
1210
+
1211
+ registerFunctionOverload(s, handler, opts) {
1212
+ if (this.#locked) throw new Error('Cannot modify frozen registry')
1213
+ if (typeof s === 'object') opts = s
1214
+ else if (typeof handler === 'object') opts = handler
1215
+ else if (!opts) opts = {}
1216
+
1217
+ const sig = typeof s === 'string' ? s : (opts.signature ?? undefined)
1218
+ const parsed = sig !== undefined ? this.#parseSignature(sig) : undefined
1219
+ const name = parsed?.name || opts.name
1220
+ const receiverType = parsed?.receiverType || opts.receiverType
1221
+ const argTypes = parsed?.argTypes
1222
+ const returnType = parsed?.returnType || opts.returnType
1223
+ const params = opts.params
1224
+ handler = typeof handler === 'function' ? handler : opts.handler
1225
+
1226
+ let dec
1227
+ try {
1228
+ if (!name) throw new Error(`signature or name are required`)
1229
+ if (!returnType) throw new Error(`must have a returnType`)
1230
+
1231
+ if (params) {
1232
+ if (argTypes && params.length !== argTypes.length) {
1233
+ throw new Error(`mismatched length in params and args in signature`)
1234
+ }
1235
+ } else if (!argTypes) throw new Error(`signature or params are required`)
1236
+
1237
+ dec = new FunctionDeclaration({
1238
+ name,
1239
+ async: opts?.async,
1240
+ receiverType: receiverType ? this.getType(receiverType) : null,
1241
+ returnType: this.getType(returnType),
1242
+ handler,
1243
+ description: opts.description,
1244
+ params: (argTypes || params).map((_, i) =>
1245
+ this.#normalizeParam(i, argTypes?.[i], params?.[i])
1246
+ )
1247
+ })
1248
+ } catch (e) {
1249
+ if (typeof sig === 'string') e.message = `Invalid function declaration '${sig}': ${e.message}`
1250
+ else if (name) e.message = `Invalid function declaration '${name}': ${e.message}`
1251
+ else e.message = `Invalid function declaration: ${e.message}`
1252
+ throw e
1253
+ }
1254
+
1255
+ this.#checkOverlappingSignatures(dec)
1256
+ this.#pushFunction(dec)
1257
+ }
1258
+
1259
+ registerOperatorOverload(string, handler, opts) {
1260
+ // Parse with optional return type: "Vector + Vector: Vector" or "Vector + Vector"
1261
+ const unaryParts = string.match(/^([-!])([\w.<>]+)(?::\s*([\w.<>]+))?$/)
1262
+ if (unaryParts) {
1263
+ const [, op, operandType, returnType] = unaryParts
1264
+ return this.unaryOverload(op, operandType, handler, returnType, opts?.async)
1265
+ }
1266
+
1267
+ const parts = string.match(
1268
+ /^([\w.<>]+) ([-+*%/]|==|!=|<|<=|>|>=|in) ([\w.<>]+)(?::\s*([\w.<>]+))?$/
1269
+ )
1270
+ if (!parts) throw new Error(`Operator overload invalid: ${string}`)
1271
+ const [, leftType, op, rightType, returnType] = parts
1272
+ return this.binaryOverload(leftType, op, rightType, handler, returnType)
1273
+ }
1274
+
1275
+ unaryOverload(op, typeStr, handler, returnTypeStr, async) {
1276
+ if (this.#locked) throw new Error('Cannot modify frozen registry')
1277
+ const leftType = this.assertType(typeStr, 'type', `${op}${typeStr}`)
1278
+ const returnType = this.assertType(
1279
+ returnTypeStr || typeStr,
1280
+ 'return type',
1281
+ `${op}${typeStr}: ${returnTypeStr || typeStr}`
1282
+ )
1283
+
1284
+ const d = new OperatorDeclaration({op: `${op}_`, leftType, returnType, handler, async})
1285
+ this.#pushOperator(this.#assertOverload(d))
1286
+ }
1287
+
1288
+ #hasOverload(d) {
1289
+ for (const o of this.operatorCandidates(d.operator)) if (d.equals(o)) return true
1290
+ return false
1291
+ }
1292
+
1293
+ #assertOverload(decl) {
1294
+ if (!this.#hasOverload(decl)) return decl
1295
+ throw new Error(`Operator overload already registered: ${decl.signature}`)
1296
+ }
1297
+
1298
+ binaryOverload(leftTypeStr, op, rightTypeStr, handler, returnTypeStr, async) {
1299
+ if (this.#locked) throw new Error('Cannot modify frozen registry')
1300
+ returnTypeStr ??= isRelational(op) ? 'bool' : leftTypeStr
1301
+
1302
+ const sig = `${leftTypeStr} ${op} ${rightTypeStr}: ${returnTypeStr}`
1303
+ let leftType = this.assertType(leftTypeStr, 'left type', sig)
1304
+ let rightType = this.assertType(rightTypeStr, 'right type', sig)
1305
+ const returnType = this.assertType(returnTypeStr, 'return type', sig)
1306
+
1307
+ // Register both types as wrapped with dyn<> if one of them is wrapped
1308
+ if (leftType.kind === 'dyn' && leftType.valueType) rightType = rightType.wrappedType
1309
+ else if (rightType.kind === 'dyn' && rightType.valueType) leftType = leftType.wrappedType
1310
+
1311
+ if (isRelational(op) && returnType.type !== 'bool') {
1312
+ throw new Error(`Comparison operator '${op}' must return 'bool', got '${returnType.type}'`)
1313
+ }
1314
+
1315
+ const dec = new OperatorDeclaration({op, leftType, rightType, returnType, handler, async})
1316
+ if (dec.hasPlaceholderType && !(rightType.hasPlaceholderType && leftType.hasPlaceholderType)) {
1317
+ throw new Error(
1318
+ `Operator overload with placeholders must use them in both left and right types: ${sig}`
1319
+ )
1320
+ }
1321
+
1322
+ this.#assertOverload(dec)
1323
+ if (op === '==') {
1324
+ const declarations = [
1325
+ new OperatorDeclaration({
1326
+ op: '!=',
1327
+ leftType,
1328
+ rightType,
1329
+ handler(a, b, ast, ev) {
1330
+ return !handler(a, b, ast, ev)
1331
+ },
1332
+ returnType,
1333
+ async
1334
+ })
1335
+ ]
1336
+
1337
+ if (leftType !== rightType) {
1338
+ declarations.push(
1339
+ new OperatorDeclaration({
1340
+ op: '==',
1341
+ leftType: rightType,
1342
+ rightType: leftType,
1343
+ handler(a, b, ast, ev) {
1344
+ return handler(b, a, ast, ev)
1345
+ },
1346
+ returnType,
1347
+ async
1348
+ }),
1349
+ new OperatorDeclaration({
1350
+ op: '!=',
1351
+ leftType: rightType,
1352
+ rightType: leftType,
1353
+ handler(a, b, ast, ev) {
1354
+ return !handler(b, a, ast, ev)
1355
+ },
1356
+ returnType,
1357
+ async
1358
+ })
1359
+ )
1360
+ }
1361
+
1362
+ for (const decl of declarations) this.#assertOverload(decl)
1363
+ for (const decl of declarations) this.#pushOperator(decl)
1364
+ }
1365
+
1366
+ this.#pushOperator(dec)
1367
+ }
1368
+ }
1369
+
1370
+ function isRelational(op) {
1371
+ return (
1372
+ op === '<' ||
1373
+ op === '<=' ||
1374
+ op === '>' ||
1375
+ op === '>=' ||
1376
+ op === '==' ||
1377
+ op === '!=' ||
1378
+ op === 'in'
1379
+ )
1380
+ }
1381
+
1382
+ export function createRegistry(opts) {
1383
+ return new Registry(opts)
1384
+ }
1385
+
1386
+ export class RootContext {
1387
+ #vars
1388
+ #contextObj
1389
+ #contextMap
1390
+ #convertCache
1391
+ constructor(registry, context) {
1392
+ this.#vars = registry.variables
1393
+ if (context === undefined || context === null) return
1394
+ if (typeof context !== 'object') throw new EvaluationError('Context must be an object')
1395
+ if (context instanceof Map) this.#contextMap = context
1396
+ else this.#contextObj = context
1397
+ }
1398
+
1399
+ getType(name) {
1400
+ return this.getVariable(name)?.type
1401
+ }
1402
+
1403
+ getValue(key) {
1404
+ return (
1405
+ this.#convertCache?.get(key) ||
1406
+ (this.#contextObj ? this.#contextObj[key] : this.#contextMap?.get(key))
1407
+ )
1408
+ }
1409
+
1410
+ getVariable(name) {
1411
+ return (
1412
+ this.#vars.get(name) ??
1413
+ (this.#vars.dyn && !RESERVED.has(name) ? new VariableDeclaration(name, dynType) : undefined)
1414
+ )
1415
+ }
1416
+
1417
+ getCheckedValue(ev, ast) {
1418
+ const v = this.getValue(ast.args)
1419
+ if (v === undefined) throw new ev.Error(`Unknown variable: ${ast.args}`, ast)
1420
+
1421
+ if (ast.checkedType === dynType) {
1422
+ // prettier-ignore
1423
+ switch (typeof v) {
1424
+ case 'string': case 'bigint': case 'number': case 'boolean': return v
1425
+ case 'object':
1426
+ switch (v ? v.constructor : v) {
1427
+ case null: return v
1428
+ case undefined: case Object: case Map: case Array: case Set: return v
1429
+ default: if (ev.objectTypesByConstructor.get(v.constructor)) return v
1430
+ }
1431
+ }
1432
+ }
1433
+
1434
+ const type = ast.checkedType
1435
+ const valueType = ev.debugType(v)
1436
+ if (type.matchesDebugType(valueType)) return v
1437
+
1438
+ // Convert plain objects to typed instances when a convert function is registered
1439
+ if (type.kind === 'message' && valueType.kind === 'map') {
1440
+ const c = ev.objectTypes.get(type.name)?.convert?.(v)
1441
+ if (c) return ((this.#convertCache ??= new Map()).set(ast.args, c), c)
1442
+ }
1443
+
1444
+ throw new ev.Error(`Variable '${ast.args}' is not of type '${type}', got '${valueType}'`, ast)
1445
+ }
1446
+
1447
+ forkWithVariable(iterVar, iterType) {
1448
+ return new OverlayContext(this, iterVar, iterType)
1449
+ }
1450
+ }
1451
+
1452
+ class OverlayContext {
1453
+ #parent
1454
+ accuType
1455
+ accuValue
1456
+ iterValue
1457
+ constructor(parent, iterVar, iterType) {
1458
+ this.#parent = parent
1459
+ this.iterVar = iterVar
1460
+ this.iterType = iterType
1461
+ }
1462
+
1463
+ forkWithVariable(iterVar, iterType) {
1464
+ return new OverlayContext(this, iterVar, iterType)
1465
+ }
1466
+
1467
+ reuse(parent) {
1468
+ if (!this.async) return ((this.#parent = parent), this)
1469
+ const ctx = new OverlayContext(parent, this.iterVar, this.iterType)
1470
+ ctx.accuType = this.accuType
1471
+ return ctx
1472
+ }
1473
+
1474
+ setIterValue(v, ev) {
1475
+ if (this.iterType === dynType) {
1476
+ // prettier-ignore
1477
+ switch (typeof v) {
1478
+ case 'string': case 'bigint': case 'number': case 'boolean':
1479
+ return ((this.iterValue = v), this)
1480
+ case 'object':
1481
+ switch (v ? v.constructor : v) {
1482
+ case null: case undefined: case Object: case Map: case Array: case Set:
1483
+ return ((this.iterValue = v), this)
1484
+ default:
1485
+ if (ev.objectTypesByConstructor.get(v.constructor))
1486
+ return ((this.iterValue = v), this)
1487
+ }
1488
+ }
1489
+ }
1490
+
1491
+ const valueType = ev.debugType(v)
1492
+ if (this.iterType.matchesDebugType(valueType)) return ((this.iterValue = v), this)
1493
+
1494
+ // Convert plain objects to typed instances when a convert function is registered
1495
+ if (this.iterType.kind === 'message' && valueType.kind === 'map') {
1496
+ const c = ev.objectTypes.get(this.iterType.name)?.convert?.(v)
1497
+ if (c) return ((this.iterValue = c), this)
1498
+ }
1499
+
1500
+ throw new ev.Error(
1501
+ `Variable '${this.iterVar}' is not of type '${this.iterType}', got '${valueType}'`
1502
+ )
1503
+ }
1504
+
1505
+ setAccuType(type) {
1506
+ return ((this.accuType = type), this)
1507
+ }
1508
+
1509
+ setAccuValue(v) {
1510
+ return ((this.accuValue = v), this)
1511
+ }
1512
+
1513
+ getValue(key) {
1514
+ return this.iterVar === key ? this.iterValue : this.#parent.getValue(key)
1515
+ }
1516
+
1517
+ getCheckedValue(ev, ast) {
1518
+ if (this.iterVar === ast.args) return this.iterValue
1519
+ return this.#parent.getCheckedValue(ev, ast)
1520
+ }
1521
+
1522
+ getVariable(name) {
1523
+ if (this.iterVar === name) return new VariableDeclaration(name, this.iterType)
1524
+ return this.#parent.getVariable(name)
1525
+ }
1526
+
1527
+ setConverted(name, value) {
1528
+ return this.iterVar === name ? (this.iterValue = value) : this.#parent.setConverted(name, value)
1529
+ }
1530
+
1531
+ // getVariable makes this obsolete
1532
+ getType(key) {
1533
+ return this.iterVar === key ? this.iterType : this.#parent.getType(key)
1534
+ }
1535
+ }
1536
+
1537
+ /**
1538
+ * Extract CEL field declarations from a protobufjs message type.
1539
+ * Maps protobuf types to CEL types.
1540
+ * @param {protobuf.Type} messageType - The protobufjs message type
1541
+ * @returns {Object} Field declarations in CEL format {fieldName: 'celType'}
1542
+ */
1543
+ function protobufjsFieldToCelType(field) {
1544
+ let fieldType
1545
+ if (field.map) {
1546
+ const keyType = protobufjsTypeToCelType(field.keyType, field.resolvedKeyType)
1547
+ const valueType = protobufjsTypeToCelType(field.type, field.resolvedType)
1548
+ fieldType = `map<${keyType}, ${valueType}>`
1549
+ } else {
1550
+ fieldType = protobufjsTypeToCelType(field.type, field.resolvedType)
1551
+ }
1552
+ return {type: field.repeated ? `list<${fieldType}>` : fieldType}
1553
+ }
1554
+
1555
+ /**
1556
+ * Map protobuf type names to CEL type names.
1557
+ * @param {string} protoType - The protobuf type name
1558
+ * @param {protobuf.Type|null} resolvedType - The resolved type for message/enum fields
1559
+ * @returns {string} The CEL type name
1560
+ */
1561
+ function protobufjsTypeToCelType(protoType, resolvedType) {
1562
+ switch (protoType) {
1563
+ case 'string':
1564
+ return 'string'
1565
+ case 'bytes':
1566
+ return 'bytes'
1567
+ case 'bool':
1568
+ return 'bool'
1569
+ // protobufjs uses JavaScript numbers for all numeric types
1570
+ case 'double':
1571
+ case 'float':
1572
+ case 'int32':
1573
+ case 'int64':
1574
+ case 'sint32':
1575
+ case 'sint64':
1576
+ case 'sfixed32':
1577
+ case 'sfixed64':
1578
+ case 'uint32':
1579
+ case 'uint64':
1580
+ case 'fixed32':
1581
+ case 'fixed64':
1582
+ return 'double'
1583
+ default:
1584
+ switch (resolvedType?.constructor.name) {
1585
+ case 'Type':
1586
+ return resolvedType.fullName.slice(1)
1587
+ case 'Enum':
1588
+ return 'int'
1589
+ }
1590
+
1591
+ if (protoType?.includes('.')) return protoType
1592
+
1593
+ // Unknown type, treat as dyn
1594
+ return 'dyn'
1595
+ }
1596
+ }