@elaraai/east 0.0.1-beta.0

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 (251) hide show
  1. package/LICENSE.md +682 -0
  2. package/README.md +276 -0
  3. package/dist/src/analyze.d.ts +95 -0
  4. package/dist/src/analyze.d.ts.map +1 -0
  5. package/dist/src/analyze.js +1110 -0
  6. package/dist/src/analyze.js.map +1 -0
  7. package/dist/src/ast.d.ts +263 -0
  8. package/dist/src/ast.d.ts.map +1 -0
  9. package/dist/src/ast.js +151 -0
  10. package/dist/src/ast.js.map +1 -0
  11. package/dist/src/ast_to_ir.d.ts +24 -0
  12. package/dist/src/ast_to_ir.d.ts.map +1 -0
  13. package/dist/src/ast_to_ir.js +834 -0
  14. package/dist/src/ast_to_ir.js.map +1 -0
  15. package/dist/src/builtins.d.ts +18 -0
  16. package/dist/src/builtins.d.ts.map +1 -0
  17. package/dist/src/builtins.js +1105 -0
  18. package/dist/src/builtins.js.map +1 -0
  19. package/dist/src/comparison.d.ts +28 -0
  20. package/dist/src/comparison.d.ts.map +1 -0
  21. package/dist/src/comparison.js +1017 -0
  22. package/dist/src/comparison.js.map +1 -0
  23. package/dist/src/compile.d.ts +22 -0
  24. package/dist/src/compile.d.ts.map +1 -0
  25. package/dist/src/compile.js +3260 -0
  26. package/dist/src/compile.js.map +1 -0
  27. package/dist/src/containers/ref.d.ts +106 -0
  28. package/dist/src/containers/ref.d.ts.map +1 -0
  29. package/dist/src/containers/ref.js +100 -0
  30. package/dist/src/containers/ref.js.map +1 -0
  31. package/dist/src/containers/sortedmap.d.ts +165 -0
  32. package/dist/src/containers/sortedmap.d.ts.map +1 -0
  33. package/dist/src/containers/sortedmap.js +237 -0
  34. package/dist/src/containers/sortedmap.js.map +1 -0
  35. package/dist/src/containers/sortedset.d.ts +185 -0
  36. package/dist/src/containers/sortedset.d.ts.map +1 -0
  37. package/dist/src/containers/sortedset.js +312 -0
  38. package/dist/src/containers/sortedset.js.map +1 -0
  39. package/dist/src/containers/variant.d.ts +131 -0
  40. package/dist/src/containers/variant.d.ts.map +1 -0
  41. package/dist/src/containers/variant.js +68 -0
  42. package/dist/src/containers/variant.js.map +1 -0
  43. package/dist/src/datetime_format/parse.d.ts +50 -0
  44. package/dist/src/datetime_format/parse.d.ts.map +1 -0
  45. package/dist/src/datetime_format/parse.js +908 -0
  46. package/dist/src/datetime_format/parse.js.map +1 -0
  47. package/dist/src/datetime_format/print.d.ts +35 -0
  48. package/dist/src/datetime_format/print.d.ts.map +1 -0
  49. package/dist/src/datetime_format/print.js +157 -0
  50. package/dist/src/datetime_format/print.js.map +1 -0
  51. package/dist/src/datetime_format/tokenize.d.ts +76 -0
  52. package/dist/src/datetime_format/tokenize.d.ts.map +1 -0
  53. package/dist/src/datetime_format/tokenize.js +271 -0
  54. package/dist/src/datetime_format/tokenize.js.map +1 -0
  55. package/dist/src/datetime_format/types.d.ts +99 -0
  56. package/dist/src/datetime_format/types.d.ts.map +1 -0
  57. package/dist/src/datetime_format/types.js +103 -0
  58. package/dist/src/datetime_format/types.js.map +1 -0
  59. package/dist/src/datetime_format/validate.d.ts +51 -0
  60. package/dist/src/datetime_format/validate.d.ts.map +1 -0
  61. package/dist/src/datetime_format/validate.js +208 -0
  62. package/dist/src/datetime_format/validate.js.map +1 -0
  63. package/dist/src/default.d.ts +21 -0
  64. package/dist/src/default.d.ts.map +1 -0
  65. package/dist/src/default.js +82 -0
  66. package/dist/src/default.js.map +1 -0
  67. package/dist/src/eastir.d.ts +33 -0
  68. package/dist/src/eastir.d.ts.map +1 -0
  69. package/dist/src/eastir.js +92 -0
  70. package/dist/src/eastir.js.map +1 -0
  71. package/dist/src/error.d.ts +13 -0
  72. package/dist/src/error.d.ts.map +1 -0
  73. package/dist/src/error.js +8 -0
  74. package/dist/src/error.js.map +1 -0
  75. package/dist/src/expr/array.d.ts +1711 -0
  76. package/dist/src/expr/array.d.ts.map +1 -0
  77. package/dist/src/expr/array.js +1805 -0
  78. package/dist/src/expr/array.js.map +1 -0
  79. package/dist/src/expr/ast.d.ts +17 -0
  80. package/dist/src/expr/ast.d.ts.map +1 -0
  81. package/dist/src/expr/ast.js +302 -0
  82. package/dist/src/expr/ast.js.map +1 -0
  83. package/dist/src/expr/blob.d.ts +141 -0
  84. package/dist/src/expr/blob.d.ts.map +1 -0
  85. package/dist/src/expr/blob.js +198 -0
  86. package/dist/src/expr/blob.js.map +1 -0
  87. package/dist/src/expr/block.d.ts +201 -0
  88. package/dist/src/expr/block.d.ts.map +1 -0
  89. package/dist/src/expr/block.js +1505 -0
  90. package/dist/src/expr/block.js.map +1 -0
  91. package/dist/src/expr/boolean.d.ts +207 -0
  92. package/dist/src/expr/boolean.d.ts.map +1 -0
  93. package/dist/src/expr/boolean.js +261 -0
  94. package/dist/src/expr/boolean.js.map +1 -0
  95. package/dist/src/expr/datetime.d.ts +544 -0
  96. package/dist/src/expr/datetime.d.ts.map +1 -0
  97. package/dist/src/expr/datetime.js +980 -0
  98. package/dist/src/expr/datetime.js.map +1 -0
  99. package/dist/src/expr/dict.d.ts +1242 -0
  100. package/dist/src/expr/dict.d.ts.map +1 -0
  101. package/dist/src/expr/dict.js +1492 -0
  102. package/dist/src/expr/dict.js.map +1 -0
  103. package/dist/src/expr/expr.d.ts +95 -0
  104. package/dist/src/expr/expr.d.ts.map +1 -0
  105. package/dist/src/expr/expr.js +171 -0
  106. package/dist/src/expr/expr.js.map +1 -0
  107. package/dist/src/expr/float.d.ts +357 -0
  108. package/dist/src/expr/float.d.ts.map +1 -0
  109. package/dist/src/expr/float.js +637 -0
  110. package/dist/src/expr/float.js.map +1 -0
  111. package/dist/src/expr/function.d.ts +46 -0
  112. package/dist/src/expr/function.d.ts.map +1 -0
  113. package/dist/src/expr/function.js +58 -0
  114. package/dist/src/expr/function.js.map +1 -0
  115. package/dist/src/expr/index.d.ts +450 -0
  116. package/dist/src/expr/index.d.ts.map +1 -0
  117. package/dist/src/expr/index.js +423 -0
  118. package/dist/src/expr/index.js.map +1 -0
  119. package/dist/src/expr/integer.d.ts +256 -0
  120. package/dist/src/expr/integer.d.ts.map +1 -0
  121. package/dist/src/expr/integer.js +311 -0
  122. package/dist/src/expr/integer.js.map +1 -0
  123. package/dist/src/expr/libs/array.d.ts +106 -0
  124. package/dist/src/expr/libs/array.d.ts.map +1 -0
  125. package/dist/src/expr/libs/array.js +140 -0
  126. package/dist/src/expr/libs/array.js.map +1 -0
  127. package/dist/src/expr/libs/blob.d.ts +42 -0
  128. package/dist/src/expr/libs/blob.d.ts.map +1 -0
  129. package/dist/src/expr/libs/blob.js +70 -0
  130. package/dist/src/expr/libs/blob.js.map +1 -0
  131. package/dist/src/expr/libs/datetime.d.ts +479 -0
  132. package/dist/src/expr/libs/datetime.d.ts.map +1 -0
  133. package/dist/src/expr/libs/datetime.js +624 -0
  134. package/dist/src/expr/libs/datetime.js.map +1 -0
  135. package/dist/src/expr/libs/dict.d.ts +66 -0
  136. package/dist/src/expr/libs/dict.d.ts.map +1 -0
  137. package/dist/src/expr/libs/dict.js +77 -0
  138. package/dist/src/expr/libs/dict.js.map +1 -0
  139. package/dist/src/expr/libs/float.d.ts +299 -0
  140. package/dist/src/expr/libs/float.d.ts.map +1 -0
  141. package/dist/src/expr/libs/float.js +564 -0
  142. package/dist/src/expr/libs/float.js.map +1 -0
  143. package/dist/src/expr/libs/integer.d.ts +228 -0
  144. package/dist/src/expr/libs/integer.d.ts.map +1 -0
  145. package/dist/src/expr/libs/integer.js +398 -0
  146. package/dist/src/expr/libs/integer.js.map +1 -0
  147. package/dist/src/expr/libs/set.d.ts +59 -0
  148. package/dist/src/expr/libs/set.d.ts.map +1 -0
  149. package/dist/src/expr/libs/set.js +69 -0
  150. package/dist/src/expr/libs/set.js.map +1 -0
  151. package/dist/src/expr/libs/string.d.ts +71 -0
  152. package/dist/src/expr/libs/string.d.ts.map +1 -0
  153. package/dist/src/expr/libs/string.js +75 -0
  154. package/dist/src/expr/libs/string.js.map +1 -0
  155. package/dist/src/expr/never.d.ts +15 -0
  156. package/dist/src/expr/never.d.ts.map +1 -0
  157. package/dist/src/expr/never.js +12 -0
  158. package/dist/src/expr/never.js.map +1 -0
  159. package/dist/src/expr/null.d.ts +15 -0
  160. package/dist/src/expr/null.d.ts.map +1 -0
  161. package/dist/src/expr/null.js +12 -0
  162. package/dist/src/expr/null.js.map +1 -0
  163. package/dist/src/expr/ref.d.ts +103 -0
  164. package/dist/src/expr/ref.d.ts.map +1 -0
  165. package/dist/src/expr/ref.js +131 -0
  166. package/dist/src/expr/ref.js.map +1 -0
  167. package/dist/src/expr/regex_validation.d.ts +25 -0
  168. package/dist/src/expr/regex_validation.d.ts.map +1 -0
  169. package/dist/src/expr/regex_validation.js +130 -0
  170. package/dist/src/expr/regex_validation.js.map +1 -0
  171. package/dist/src/expr/set.d.ts +1071 -0
  172. package/dist/src/expr/set.d.ts.map +1 -0
  173. package/dist/src/expr/set.js +1137 -0
  174. package/dist/src/expr/set.js.map +1 -0
  175. package/dist/src/expr/string.d.ts +414 -0
  176. package/dist/src/expr/string.d.ts.map +1 -0
  177. package/dist/src/expr/string.js +683 -0
  178. package/dist/src/expr/string.js.map +1 -0
  179. package/dist/src/expr/struct.d.ts +48 -0
  180. package/dist/src/expr/struct.d.ts.map +1 -0
  181. package/dist/src/expr/struct.js +65 -0
  182. package/dist/src/expr/struct.js.map +1 -0
  183. package/dist/src/expr/types.d.ts +68 -0
  184. package/dist/src/expr/types.d.ts.map +1 -0
  185. package/dist/src/expr/types.js +6 -0
  186. package/dist/src/expr/types.js.map +1 -0
  187. package/dist/src/expr/variant.d.ts +137 -0
  188. package/dist/src/expr/variant.d.ts.map +1 -0
  189. package/dist/src/expr/variant.js +105 -0
  190. package/dist/src/expr/variant.js.map +1 -0
  191. package/dist/src/fuzz.d.ts +80 -0
  192. package/dist/src/fuzz.d.ts.map +1 -0
  193. package/dist/src/fuzz.js +300 -0
  194. package/dist/src/fuzz.js.map +1 -0
  195. package/dist/src/index.d.ts +21 -0
  196. package/dist/src/index.d.ts.map +1 -0
  197. package/dist/src/index.js +21 -0
  198. package/dist/src/index.js.map +1 -0
  199. package/dist/src/internal.d.ts +36 -0
  200. package/dist/src/internal.d.ts.map +1 -0
  201. package/dist/src/internal.js +11 -0
  202. package/dist/src/internal.js.map +1 -0
  203. package/dist/src/ir.d.ts +1571 -0
  204. package/dist/src/ir.d.ts.map +1 -0
  205. package/dist/src/ir.js +56 -0
  206. package/dist/src/ir.js.map +1 -0
  207. package/dist/src/location.d.ts +48 -0
  208. package/dist/src/location.d.ts.map +1 -0
  209. package/dist/src/location.js +62 -0
  210. package/dist/src/location.js.map +1 -0
  211. package/dist/src/platform.d.ts +21 -0
  212. package/dist/src/platform.d.ts.map +1 -0
  213. package/dist/src/platform.js +8 -0
  214. package/dist/src/platform.js.map +1 -0
  215. package/dist/src/serialization/beast.d.ts +39 -0
  216. package/dist/src/serialization/beast.d.ts.map +1 -0
  217. package/dist/src/serialization/beast.js +555 -0
  218. package/dist/src/serialization/beast.js.map +1 -0
  219. package/dist/src/serialization/beast2-stream.d.ts +38 -0
  220. package/dist/src/serialization/beast2-stream.d.ts.map +1 -0
  221. package/dist/src/serialization/beast2-stream.js +665 -0
  222. package/dist/src/serialization/beast2-stream.js.map +1 -0
  223. package/dist/src/serialization/beast2.d.ts +41 -0
  224. package/dist/src/serialization/beast2.d.ts.map +1 -0
  225. package/dist/src/serialization/beast2.js +489 -0
  226. package/dist/src/serialization/beast2.js.map +1 -0
  227. package/dist/src/serialization/binary-utils.d.ts +151 -0
  228. package/dist/src/serialization/binary-utils.d.ts.map +1 -0
  229. package/dist/src/serialization/binary-utils.js +929 -0
  230. package/dist/src/serialization/binary-utils.js.map +1 -0
  231. package/dist/src/serialization/east.d.ts +84 -0
  232. package/dist/src/serialization/east.d.ts.map +1 -0
  233. package/dist/src/serialization/east.js +1802 -0
  234. package/dist/src/serialization/east.js.map +1 -0
  235. package/dist/src/serialization/index.d.ts +11 -0
  236. package/dist/src/serialization/index.d.ts.map +1 -0
  237. package/dist/src/serialization/index.js +12 -0
  238. package/dist/src/serialization/index.js.map +1 -0
  239. package/dist/src/serialization/json.d.ts +36 -0
  240. package/dist/src/serialization/json.d.ts.map +1 -0
  241. package/dist/src/serialization/json.js +849 -0
  242. package/dist/src/serialization/json.js.map +1 -0
  243. package/dist/src/type_of_type.d.ts +115 -0
  244. package/dist/src/type_of_type.d.ts.map +1 -0
  245. package/dist/src/type_of_type.js +362 -0
  246. package/dist/src/type_of_type.js.map +1 -0
  247. package/dist/src/types.d.ts +648 -0
  248. package/dist/src/types.d.ts.map +1 -0
  249. package/dist/src/types.js +1631 -0
  250. package/dist/src/types.js.map +1 -0
  251. package/package.json +87 -0
@@ -0,0 +1,849 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
4
+ */
5
+ import { compareFor } from "../comparison.js";
6
+ import { SortedMap } from "../containers/sortedmap.js";
7
+ import { SortedSet } from "../containers/sortedset.js";
8
+ import { EastTypeValueType, toEastTypeValue } from "../type_of_type.js";
9
+ import { isVariant, variant } from "../containers/variant.js";
10
+ import { printFor } from "./east.js";
11
+ import { ref } from "../containers/ref.js";
12
+ const printTypeValue = printFor(EastTypeValueType);
13
+ /**
14
+ * Encodes a JSON Pointer component according to RFC 6901.
15
+ *
16
+ * @param component - The path component to encode
17
+ * @returns The encoded component with ~ and / escaped
18
+ *
19
+ * @remarks
20
+ * Per RFC 6901, '~' is encoded as '~0' and '/' is encoded as '~1'.
21
+ * The order matters: we must escape '~' first to avoid double-escaping.
22
+ */
23
+ function _encodeJSONPointerComponent(component) {
24
+ return component.replace(/~/g, '~0').replace(/\//g, '~1');
25
+ }
26
+ class JSONDecodeError extends Error {
27
+ path;
28
+ constructor(message, path = '') {
29
+ super(message);
30
+ this.path = path;
31
+ this.name = "JSONDecodeError";
32
+ }
33
+ }
34
+ /**
35
+ * Find the length of the common prefix between two path arrays.
36
+ */
37
+ function _commonPrefixLength(a, b) {
38
+ let i = 0;
39
+ while (i < a.length && i < b.length && a[i] === b[i]) {
40
+ i++;
41
+ }
42
+ return i;
43
+ }
44
+ /**
45
+ * Compute a relative JSON Pointer reference from currentPath to targetPath.
46
+ * Returns a string like "2#foo/bar" (up 2 levels, then follow foo/bar)
47
+ * or "1#" (up 1 level, no remaining path).
48
+ */
49
+ function encodeRelativeRef(currentPath, targetPath) {
50
+ const commonLen = _commonPrefixLength(currentPath, targetPath);
51
+ const upLevels = currentPath.length - commonLen;
52
+ const remaining = targetPath.slice(commonLen);
53
+ if (remaining.length === 0) {
54
+ return `${upLevels}#`;
55
+ }
56
+ // Escape each component according to RFC 6901
57
+ const escapedRemaining = remaining.map(_encodeJSONPointerComponent).join('/');
58
+ return `${upLevels}#${escapedRemaining}`;
59
+ }
60
+ /**
61
+ * Decode a relative JSON Pointer reference and return the target path array.
62
+ * Input like "2#foo/bar" returns the target path array.
63
+ * Input like "1#" returns the target path array.
64
+ */
65
+ function _decodeRelativeRef(refStr, currentPath) {
66
+ const hashIdx = refStr.indexOf('#');
67
+ if (hashIdx === -1) {
68
+ throw new Error(`Invalid relative JSON Pointer reference: ${refStr}`);
69
+ }
70
+ const upLevelStr = refStr.substring(0, hashIdx);
71
+ const remainingStr = refStr.substring(hashIdx + 1);
72
+ let upLevels;
73
+ try {
74
+ upLevels = parseInt(upLevelStr);
75
+ }
76
+ catch {
77
+ throw new Error(`Invalid relative JSON Pointer reference: ${refStr}`);
78
+ }
79
+ if (upLevels < 0 || upLevels > currentPath.length) {
80
+ throw new Error(`Invalid relative JSON Pointer reference: going up ${upLevels} levels from depth ${currentPath.length}`);
81
+ }
82
+ // Build target path
83
+ const targetPath = currentPath.slice(0, currentPath.length - upLevels);
84
+ // Add remaining components if any
85
+ if (remainingStr.length > 0) {
86
+ const components = remainingStr.split('/');
87
+ for (const component of components) {
88
+ // Decode RFC 6901 escaping
89
+ const unescaped = component.replace(/~1/g, '/').replace(/~0/g, '~');
90
+ targetPath.push(unescaped);
91
+ }
92
+ }
93
+ return targetPath;
94
+ }
95
+ /**
96
+ * Decode a RFC 6901 JSON Pointer component.
97
+ */
98
+ function _decodeJSONPointerComponent(component) {
99
+ return component.replace(/~1/g, '/').replace(/~0/g, '~');
100
+ }
101
+ export function encodeJSONFor(type) {
102
+ // Convert EastType to EastTypeValue if necessary
103
+ if (!isVariant(type)) {
104
+ type = toEastTypeValue(type);
105
+ }
106
+ const textEncoder = new TextEncoder();
107
+ const toJSON = toJSONFor(type);
108
+ return (x) => textEncoder.encode(JSON.stringify(toJSON(x)));
109
+ }
110
+ export function decodeJSONFor(type, frozen = false) {
111
+ // Convert EastType to EastTypeValue if necessary
112
+ if (!isVariant(type)) {
113
+ type = toEastTypeValue(type);
114
+ }
115
+ const textDecoder = new TextDecoder();
116
+ const fromJSON = createJSONDecoder(type, frozen);
117
+ return (x) => {
118
+ const jsonString = textDecoder.decode(x);
119
+ let parsed;
120
+ let _parseError = null;
121
+ let line = 1;
122
+ let column = 1;
123
+ try {
124
+ parsed = JSON.parse(jsonString);
125
+ }
126
+ catch (e) {
127
+ // Extract line and column from JSON.parse error if available
128
+ if (e instanceof SyntaxError) {
129
+ const match = e.message.match(/position (\d+)/);
130
+ if (match) {
131
+ const position = parseInt(match[1]);
132
+ for (let i = 0; i < position && i < jsonString.length; i++) {
133
+ if (jsonString[i] === '\n') {
134
+ line++;
135
+ column = 1;
136
+ }
137
+ else {
138
+ column++;
139
+ }
140
+ }
141
+ }
142
+ throw new Error(`Error occurred because ${e.message} (line ${line}, col ${column}) while parsing value of type "${printTypeValue(type)}"`);
143
+ }
144
+ throw e;
145
+ }
146
+ try {
147
+ return fromJSON(parsed);
148
+ }
149
+ catch (e) {
150
+ if (e instanceof JSONDecodeError) {
151
+ const pathStr = e.path ? ` at ${e.path}` : '';
152
+ throw new Error(`Error occurred because ${e.message}${pathStr} (line 1, col 1) while parsing value of type "${printTypeValue(type)}"`);
153
+ }
154
+ throw e;
155
+ }
156
+ };
157
+ }
158
+ export function toJSONFor(type, typeCtx = []) {
159
+ // Convert EastType to EastTypeValue if necessary
160
+ if (!isVariant(type)) {
161
+ type = toEastTypeValue(type);
162
+ }
163
+ if (type.type === "Never") {
164
+ return ((_, _ctx) => { throw new Error("Cannot encode Never type to JSON"); });
165
+ }
166
+ else if (type.type === "Null") {
167
+ return (_, _ctx) => null;
168
+ }
169
+ else if (type.type === "Boolean") {
170
+ return (value, _ctx) => value;
171
+ }
172
+ else if (type.type === "Integer") {
173
+ return (value, _ctx) => value.toString();
174
+ }
175
+ else if (type.type === "Float") {
176
+ return (value, _ctx) => {
177
+ // Handle negative zero specially since JSON.parse("-0.0") returns 0
178
+ if (Object.is(value, -0)) {
179
+ return "-0.0";
180
+ }
181
+ return isFinite(value) ? value : value.toString();
182
+ };
183
+ }
184
+ else if (type.type === "String") {
185
+ return (value, _ctx) => value;
186
+ }
187
+ else if (type.type === "DateTime") {
188
+ // Encode as RFC 3339 date-time string (see RFC 3339 Section 5.6)
189
+ // Always use UTC timezone (+00:00) for consistency
190
+ return (date, _ctx) => {
191
+ const year = date.getUTCFullYear();
192
+ const month = (date.getUTCMonth() + 1).toString().padStart(2, '0');
193
+ const day = date.getUTCDate().toString().padStart(2, '0');
194
+ const hour = date.getUTCHours().toString().padStart(2, '0');
195
+ const minute = date.getUTCMinutes().toString().padStart(2, '0');
196
+ const second = date.getUTCSeconds().toString().padStart(2, '0');
197
+ const ms = date.getUTCMilliseconds().toString().padStart(3, '0');
198
+ return `${year}-${month}-${day}T${hour}:${minute}:${second}.${ms}+00:00`;
199
+ };
200
+ }
201
+ else if (type.type === "Blob") {
202
+ return (value, _ctx) => `0x${[...value].map(b => b.toString(16).padStart(2, "0")).join("")}`;
203
+ }
204
+ else if (type.type === "Ref") {
205
+ let valueToJson;
206
+ const ret = (value, ctx = { refs: new Map(), currentPath: [] }) => {
207
+ // Check if this ref was already seen
208
+ if (ctx.refs.has(value)) {
209
+ // Return a relative reference
210
+ const targetPath = ctx.refs.get(value);
211
+ const refStr = encodeRelativeRef(ctx.currentPath, targetPath);
212
+ return { "$ref": refStr };
213
+ }
214
+ // First encounter - register the current path array
215
+ ctx.refs.set(value, [...ctx.currentPath]);
216
+ // Serialize the referenced value as array of one element
217
+ ctx.currentPath.push("0");
218
+ const result = [valueToJson(value.value, ctx)];
219
+ ctx.currentPath.pop();
220
+ return result;
221
+ };
222
+ typeCtx.push(ret);
223
+ valueToJson = toJSONFor(type.value, typeCtx);
224
+ typeCtx.pop();
225
+ return ret;
226
+ }
227
+ else if (type.type === "Array") {
228
+ let valueToJson;
229
+ const ret = (value, ctx = { refs: new Map(), currentPath: [] }) => {
230
+ // Check if this array was already seen
231
+ if (ctx.refs.has(value)) {
232
+ // Return a relative reference
233
+ const targetPath = ctx.refs.get(value);
234
+ const refStr = encodeRelativeRef(ctx.currentPath, targetPath);
235
+ return { "$ref": refStr };
236
+ }
237
+ // First encounter - register the current path array
238
+ ctx.refs.set(value, [...ctx.currentPath]);
239
+ // Serialize array elements
240
+ const result = [];
241
+ for (let i = 0; i < value.length; i++) {
242
+ ctx.currentPath.push(i.toString());
243
+ result.push(valueToJson(value[i], ctx));
244
+ ctx.currentPath.pop();
245
+ }
246
+ return result;
247
+ };
248
+ typeCtx.push(ret);
249
+ valueToJson = toJSONFor(type.value, typeCtx);
250
+ typeCtx.pop();
251
+ return ret;
252
+ }
253
+ else if (type.type === "Set") {
254
+ const keyToJson = toJSONFor(type.value, typeCtx);
255
+ return (value, ctx) => {
256
+ // Check if we're tracking references (inside a RecursiveType)
257
+ if (ctx) {
258
+ // Check if this set was already seen
259
+ if (ctx.refs.has(value)) {
260
+ // Return a relative reference
261
+ const targetPath = ctx.refs.get(value);
262
+ const refStr = encodeRelativeRef(ctx.currentPath, targetPath);
263
+ return { "$ref": refStr };
264
+ }
265
+ // First encounter - register the current path array
266
+ ctx.refs.set(value, [...ctx.currentPath]);
267
+ }
268
+ // Serialize set elements
269
+ const arr = [];
270
+ let i = 0;
271
+ for (const v of value) {
272
+ if (ctx)
273
+ ctx.currentPath.push(i.toString());
274
+ arr.push(keyToJson(v, ctx));
275
+ if (ctx)
276
+ ctx.currentPath.pop();
277
+ i++;
278
+ }
279
+ return arr;
280
+ };
281
+ }
282
+ else if (type.type === "Dict") {
283
+ const keyToJson = toJSONFor(type.value.key, typeCtx);
284
+ let valueToJson;
285
+ const ret = (value, ctx = { refs: new Map(), currentPath: [] }) => {
286
+ // Check if this dict was already seen
287
+ if (ctx.refs.has(value)) {
288
+ // Return a relative reference
289
+ const targetPath = ctx.refs.get(value);
290
+ const refStr = encodeRelativeRef(ctx.currentPath, targetPath);
291
+ return { "$ref": refStr };
292
+ }
293
+ // First encounter - register the current path array
294
+ ctx.refs.set(value, [...ctx.currentPath]);
295
+ // Serialize dict entries
296
+ const arr = [];
297
+ let i = 0;
298
+ for (const [k, v] of value) {
299
+ const entry = {};
300
+ // Encode key
301
+ ctx.currentPath.push(i.toString(), "key");
302
+ entry.key = keyToJson(k, ctx);
303
+ ctx.currentPath.pop();
304
+ ctx.currentPath.pop();
305
+ // Encode value
306
+ ctx.currentPath.push(i.toString(), "value");
307
+ entry.value = valueToJson(v, ctx);
308
+ ctx.currentPath.pop();
309
+ ctx.currentPath.pop();
310
+ arr.push(entry);
311
+ i++;
312
+ }
313
+ return arr;
314
+ };
315
+ typeCtx.push(ret);
316
+ valueToJson = toJSONFor(type.value.value, typeCtx);
317
+ typeCtx.pop();
318
+ return ret;
319
+ }
320
+ else if (type.type === "Struct") {
321
+ const fieldToJson = {};
322
+ const ret = (value, ctx = { refs: new Map(), currentPath: [] }) => {
323
+ const obj = {};
324
+ for (const k in fieldToJson) {
325
+ ctx.currentPath.push(k);
326
+ obj[k] = fieldToJson[k](value[k], ctx);
327
+ ctx.currentPath.pop();
328
+ }
329
+ return obj;
330
+ };
331
+ typeCtx.push(ret);
332
+ for (const { name, type: t } of type.value) {
333
+ fieldToJson[name] = toJSONFor(t, typeCtx);
334
+ }
335
+ typeCtx.pop();
336
+ return ret;
337
+ }
338
+ else if (type.type === "Variant") {
339
+ const caseToJson = {};
340
+ const ret = (value, ctx = { refs: new Map(), currentPath: [] }) => {
341
+ const type = value.type;
342
+ ctx.currentPath.push(type);
343
+ const encodedValue = caseToJson[type](value.value, ctx);
344
+ ctx.currentPath.pop();
345
+ return { type, value: encodedValue };
346
+ };
347
+ typeCtx.push(ret);
348
+ for (const { name, type: t } of type.value) {
349
+ caseToJson[name] = toJSONFor(t, typeCtx);
350
+ }
351
+ typeCtx.pop();
352
+ return ret;
353
+ }
354
+ else if (type.type === "Recursive") {
355
+ const ret = typeCtx[typeCtx.length - Number(type.value)];
356
+ if (ret === undefined) {
357
+ throw new Error(`Internal error: Recursive type context not found`);
358
+ }
359
+ return ret;
360
+ }
361
+ else if (type.type === "Function") {
362
+ throw new Error(`Cannot encode function type to JSON`);
363
+ }
364
+ else {
365
+ throw new Error(`Unhandled type ${type.type} for toJson`);
366
+ }
367
+ }
368
+ export function fromJSONFor(type, frozen = false) {
369
+ // Convert EastType to EastTypeValue if necessary
370
+ if (!isVariant(type)) {
371
+ type = toEastTypeValue(type);
372
+ }
373
+ const decoder = createJSONDecoder(type, frozen);
374
+ const typeName = printTypeValue(type);
375
+ return (value) => {
376
+ try {
377
+ return decoder(value);
378
+ }
379
+ catch (e) {
380
+ if (e instanceof JSONDecodeError) {
381
+ const pathStr = e.path ? ` at ${e.path}` : '';
382
+ throw new Error(`Error occurred because ${e.message}${pathStr} (line 1, col 1) while parsing value of type "${typeName}"`);
383
+ }
384
+ throw e;
385
+ }
386
+ };
387
+ }
388
+ /**
389
+ * Creates a JSON decoder function for a given East type.
390
+ *
391
+ * @param type - The East type to create a decoder for
392
+ * @param frozen - Whether to freeze decoded objects
393
+ * @param recursiveContext - Optional context for handling recursive types (internal use)
394
+ * @returns A function that converts JSON values to East values
395
+ *
396
+ * @remarks
397
+ * The returned function accepts an optional context parameter for resolving references.
398
+ * When called without a context (the normal case), it operates independently.
399
+ * When called with a context (inside a RecursiveType), it resolves `$ref` references.
400
+ */
401
+ function createJSONDecoder(type, frozen = false, typeCtx = []) {
402
+ if (type.type === "Never") {
403
+ return ((_, _ctx) => { throw new Error("Cannot decode Never type from JSON"); });
404
+ }
405
+ else if (type.type === "Null") {
406
+ return (value, _ctx) => {
407
+ if (value !== null) {
408
+ throw new JSONDecodeError(`expected null, got ${JSON.stringify(value)}`);
409
+ }
410
+ return null;
411
+ };
412
+ }
413
+ else if (type.type === "Boolean") {
414
+ return (value, _ctx) => {
415
+ if (typeof value !== "boolean") {
416
+ throw new JSONDecodeError(`expected boolean, got ${JSON.stringify(value)}`);
417
+ }
418
+ return value;
419
+ };
420
+ }
421
+ else if (type.type === "Integer") {
422
+ return (value, _ctx) => {
423
+ if (typeof value === "string" && value.length > 0) {
424
+ let bigint;
425
+ try {
426
+ bigint = BigInt(value);
427
+ }
428
+ catch {
429
+ throw new JSONDecodeError(`expected string representing integer, got ${JSON.stringify(value)}`);
430
+ }
431
+ // Check for 64-bit signed integer range: -2^63 to 2^63-1
432
+ if (bigint < -9223372036854775808n || bigint > 9223372036854775807n) {
433
+ throw new JSONDecodeError(`integer out of range (must be 64-bit signed), got ${JSON.stringify(value)}`);
434
+ }
435
+ return bigint;
436
+ }
437
+ else {
438
+ throw new JSONDecodeError(`expected string representing integer, got ${JSON.stringify(value)}`);
439
+ }
440
+ };
441
+ }
442
+ else if (type.type === "Float") {
443
+ return (value, _ctx) => {
444
+ if (typeof value === "number") {
445
+ return value;
446
+ }
447
+ else if (value === "-0.0") {
448
+ return -0.0;
449
+ }
450
+ else if (value === "NaN") {
451
+ return NaN;
452
+ }
453
+ else if (value === "Infinity") {
454
+ return Infinity;
455
+ }
456
+ else if (value === "-Infinity") {
457
+ return -Infinity;
458
+ }
459
+ else {
460
+ throw new JSONDecodeError(`expected number or string representing special float value, got ${JSON.stringify(value)}`);
461
+ }
462
+ };
463
+ }
464
+ else if (type.type === "String") {
465
+ return (value, _ctx) => {
466
+ if (typeof value !== "string") {
467
+ throw new JSONDecodeError(`expected string, got ${JSON.stringify(value)}`);
468
+ }
469
+ return value;
470
+ };
471
+ }
472
+ else if (type.type === "DateTime") {
473
+ return (value, _ctx) => {
474
+ if (typeof value !== "string") {
475
+ throw new JSONDecodeError(`expected string for DateTime, got ${JSON.stringify(value)}`);
476
+ }
477
+ // Require RFC 3339 date-time format with timezone (see RFC 3339 Section 5.6)
478
+ // Per RFC 3339 Section 4.3, "unqualified local time" is unacceptable for interchange
479
+ // Timezone must be either 'Z' (UTC) or numeric offset (e.g., '+05:00' or '-08:00')
480
+ // Format: YYYY-MM-DDTHH:mm:ss.sss(Z|±HH:mm)
481
+ const iso8601WithTimezone = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}(Z|[+-]\d{2}:\d{2})$/;
482
+ if (!iso8601WithTimezone.test(value)) {
483
+ throw new JSONDecodeError(`expected ISO 8601 date string with timezone (e.g. "2022-06-29T13:43:00.123Z" or "2022-06-29T13:43:00.123+05:00"), got ${JSON.stringify(value)}`);
484
+ }
485
+ const date = new Date(value);
486
+ if (isNaN(date.getTime())) {
487
+ throw new JSONDecodeError(`invalid date string, got ${JSON.stringify(value)}`);
488
+ }
489
+ if (frozen) {
490
+ Object.freeze(date);
491
+ }
492
+ return date;
493
+ };
494
+ }
495
+ else if (type.type === "Blob") {
496
+ return (value, _ctx) => {
497
+ if (typeof value !== "string" || !value.startsWith("0x")) {
498
+ throw new JSONDecodeError(`expected hex string starting with 0x, got ${JSON.stringify(value)}`);
499
+ }
500
+ const hex = value.slice(2);
501
+ if (hex.length % 2 !== 0 || !/^[0-9a-fA-F]*$/.test(hex)) {
502
+ throw new JSONDecodeError(`invalid hex string, got ${JSON.stringify(value)}`);
503
+ }
504
+ const bytes = new Uint8Array(hex.length / 2);
505
+ for (let i = 0; i < bytes.length; i++) {
506
+ bytes[i] = parseInt(hex.substring(i * 2, i * 2 + 2), 16);
507
+ }
508
+ if (frozen) {
509
+ Object.freeze(bytes);
510
+ }
511
+ return bytes;
512
+ };
513
+ }
514
+ else if (type.type === "Ref") {
515
+ let valueFromJson;
516
+ const ret = (json, ctx = { refs: new Map(), currentPath: [] }) => {
517
+ // Check for reference first (must appear before refs)
518
+ if (json && typeof json === 'object' && "$ref" in json && Object.keys(json).length === 1) {
519
+ const refStr = json["$ref"];
520
+ if (typeof refStr === 'string') {
521
+ try {
522
+ const targetPath = _decodeRelativeRef(refStr, ctx.currentPath);
523
+ const pathKey = "/" + targetPath.map(_encodeJSONPointerComponent).join("/");
524
+ if (!ctx.refs.has(pathKey)) {
525
+ throw new JSONDecodeError(`undefined reference ${refStr}`);
526
+ }
527
+ return ctx.refs.get(pathKey);
528
+ }
529
+ catch (e) {
530
+ if (e instanceof JSONDecodeError) {
531
+ throw e;
532
+ }
533
+ throw new JSONDecodeError(`invalid reference ${refStr}`);
534
+ }
535
+ }
536
+ }
537
+ if (!Array.isArray(json) || json.length !== 1) {
538
+ throw new JSONDecodeError(`expected array with 1 entry, got ${JSON.stringify(json)}`);
539
+ }
540
+ // Create array and pre-register (for circular references)
541
+ const self = ref(undefined);
542
+ const pathKey = "/" + ctx.currentPath.map(_encodeJSONPointerComponent).join("/");
543
+ ctx.refs.set(pathKey, self);
544
+ // Populate reference
545
+ self.value = valueFromJson(json[0], ctx);
546
+ if (frozen) {
547
+ Object.freeze(self);
548
+ }
549
+ return self;
550
+ };
551
+ typeCtx.push(ret);
552
+ valueFromJson = createJSONDecoder(type.value, frozen, typeCtx);
553
+ typeCtx.pop();
554
+ return ret;
555
+ }
556
+ else if (type.type === "Array") {
557
+ let valueFromJson;
558
+ const ret = (json, ctx = { refs: new Map(), currentPath: [] }) => {
559
+ // Check for reference first (must appear before refs)
560
+ if (json && typeof json === 'object' && "$ref" in json && Object.keys(json).length === 1) {
561
+ const refStr = json["$ref"];
562
+ if (typeof refStr === 'string') {
563
+ try {
564
+ const targetPath = _decodeRelativeRef(refStr, ctx.currentPath);
565
+ const pathKey = "/" + targetPath.map(_encodeJSONPointerComponent).join("/");
566
+ if (!ctx.refs.has(pathKey)) {
567
+ throw new JSONDecodeError(`undefined reference ${refStr}`);
568
+ }
569
+ return ctx.refs.get(pathKey);
570
+ }
571
+ catch (e) {
572
+ if (e instanceof JSONDecodeError) {
573
+ throw e;
574
+ }
575
+ throw new JSONDecodeError(`invalid reference ${refStr}`);
576
+ }
577
+ }
578
+ }
579
+ if (!Array.isArray(json)) {
580
+ throw new JSONDecodeError(`expected array, got ${JSON.stringify(json)}`);
581
+ }
582
+ // Create array and pre-register (for circular references)
583
+ const array = [];
584
+ const pathKey = "/" + ctx.currentPath.map(_encodeJSONPointerComponent).join("/");
585
+ ctx.refs.set(pathKey, array);
586
+ // Populate array
587
+ for (let i = 0; i < json.length; i++) {
588
+ ctx.currentPath.push(i.toString());
589
+ try {
590
+ array.push(valueFromJson(json[i], ctx));
591
+ }
592
+ catch (e) {
593
+ if (e instanceof JSONDecodeError) {
594
+ const newPath = `[${i}]` + (e.path ? e.path : '');
595
+ throw new JSONDecodeError(e.message, newPath);
596
+ }
597
+ throw e;
598
+ }
599
+ ctx.currentPath.pop();
600
+ }
601
+ if (frozen) {
602
+ Object.freeze(array);
603
+ }
604
+ return array;
605
+ };
606
+ typeCtx.push(ret);
607
+ valueFromJson = createJSONDecoder(type.value, frozen, typeCtx);
608
+ typeCtx.pop();
609
+ return ret;
610
+ }
611
+ else if (type.type === "Set") {
612
+ const keyFromJson = createJSONDecoder(type.value, frozen, typeCtx);
613
+ const compare = compareFor(type.value);
614
+ return (json, ctx) => {
615
+ // Check for reference first
616
+ if (ctx && json && typeof json === 'object' && "$ref" in json && Object.keys(json).length === 1) {
617
+ const refStr = json["$ref"];
618
+ if (typeof refStr === 'string') {
619
+ try {
620
+ const targetPath = _decodeRelativeRef(refStr, ctx.currentPath);
621
+ const pathKey = "/" + targetPath.map(_encodeJSONPointerComponent).join("/");
622
+ if (!ctx.refs.has(pathKey)) {
623
+ throw new JSONDecodeError(`undefined reference ${refStr}`);
624
+ }
625
+ return ctx.refs.get(pathKey);
626
+ }
627
+ catch (e) {
628
+ if (e instanceof JSONDecodeError) {
629
+ throw e;
630
+ }
631
+ throw new JSONDecodeError(`invalid reference ${refStr}`);
632
+ }
633
+ }
634
+ }
635
+ if (!Array.isArray(json)) {
636
+ throw new JSONDecodeError(`expected array for Set, got ${JSON.stringify(json)}`);
637
+ }
638
+ // Create set and pre-register
639
+ const set = new SortedSet([], compare);
640
+ if (ctx) {
641
+ const pathKey = "/" + ctx.currentPath.map(_encodeJSONPointerComponent).join("/");
642
+ ctx.refs.set(pathKey, set);
643
+ }
644
+ // Populate set
645
+ for (let i = 0; i < json.length; i++) {
646
+ if (ctx)
647
+ ctx.currentPath.push(i.toString());
648
+ try {
649
+ set.add(keyFromJson(json[i], ctx));
650
+ }
651
+ catch (e) {
652
+ if (e instanceof JSONDecodeError) {
653
+ const newPath = `[${i}]` + (e.path ? e.path : '');
654
+ throw new JSONDecodeError(e.message, newPath);
655
+ }
656
+ throw e;
657
+ }
658
+ if (ctx)
659
+ ctx.currentPath.pop();
660
+ }
661
+ if (frozen) {
662
+ Object.freeze(set);
663
+ }
664
+ return set;
665
+ };
666
+ }
667
+ else if (type.type === "Dict") {
668
+ const keyFromJson = createJSONDecoder(type.value.key, frozen, typeCtx);
669
+ let valueFromJson;
670
+ const compare = compareFor(type.value.key);
671
+ const ret = (json, ctx = { refs: new Map(), currentPath: [] }) => {
672
+ // Check for reference first
673
+ if (json && typeof json === 'object' && "$ref" in json && Object.keys(json).length === 1) {
674
+ const refStr = json["$ref"];
675
+ if (typeof refStr === 'string') {
676
+ try {
677
+ const targetPath = _decodeRelativeRef(refStr, ctx.currentPath);
678
+ const pathKey = "/" + targetPath.map(_encodeJSONPointerComponent).join("/");
679
+ if (!ctx.refs.has(pathKey)) {
680
+ throw new JSONDecodeError(`undefined reference ${refStr}`);
681
+ }
682
+ return ctx.refs.get(pathKey);
683
+ }
684
+ catch (e) {
685
+ if (e instanceof JSONDecodeError) {
686
+ throw e;
687
+ }
688
+ throw new JSONDecodeError(`invalid reference ${refStr}`);
689
+ }
690
+ }
691
+ }
692
+ if (!Array.isArray(json)) {
693
+ throw new JSONDecodeError(`expected array for Dict, got ${JSON.stringify(json)}`);
694
+ }
695
+ // Create dict and pre-register (for circular references)
696
+ const dict = new SortedMap([], compare);
697
+ const pathKey = "/" + ctx.currentPath.map(_encodeJSONPointerComponent).join("/");
698
+ ctx.refs.set(pathKey, dict);
699
+ // Populate dict
700
+ for (let i = 0; i < json.length; i++) {
701
+ const item = json[i];
702
+ if (typeof item !== "object" || item === null || !("key" in item) || !("value" in item)) {
703
+ throw new JSONDecodeError(`expected object with key and value for Dict entry, got ${JSON.stringify(item)}`, `[${i}]`);
704
+ }
705
+ // Check for extra fields in dict entry
706
+ for (const k in item) {
707
+ if (k !== "key" && k !== "value") {
708
+ throw new JSONDecodeError(`unexpected field "${k}" in Dict entry, got ${JSON.stringify(item)}`, `[${i}]`);
709
+ }
710
+ }
711
+ let dictKey;
712
+ ctx.currentPath.push(i.toString(), "key");
713
+ try {
714
+ dictKey = keyFromJson(item.key, ctx);
715
+ }
716
+ catch (e) {
717
+ if (e instanceof JSONDecodeError) {
718
+ const newPath = `[${i}].key` + (e.path ? e.path : '');
719
+ throw new JSONDecodeError(e.message, newPath);
720
+ }
721
+ throw e;
722
+ }
723
+ ctx.currentPath.pop();
724
+ ctx.currentPath.push("value");
725
+ try {
726
+ const dictValue = valueFromJson(item.value, ctx);
727
+ dict.set(dictKey, dictValue);
728
+ }
729
+ catch (e) {
730
+ if (e instanceof JSONDecodeError) {
731
+ const newPath = `[${i}].value` + (e.path ? e.path : '');
732
+ throw new JSONDecodeError(e.message, newPath);
733
+ }
734
+ throw e;
735
+ }
736
+ ctx.currentPath.pop();
737
+ ctx.currentPath.pop();
738
+ }
739
+ if (frozen) {
740
+ Object.freeze(dict);
741
+ }
742
+ return dict;
743
+ };
744
+ typeCtx.push(ret);
745
+ valueFromJson = createJSONDecoder(type.value.value, frozen, typeCtx);
746
+ typeCtx.pop();
747
+ return ret;
748
+ }
749
+ else if (type.type === "Struct") {
750
+ const fieldFromJson = {};
751
+ const ret = (json, ctx = { refs: new Map(), currentPath: [] }) => {
752
+ if (typeof json !== "object" || json === null) {
753
+ throw new JSONDecodeError(`expected object for Struct, got ${JSON.stringify(json)}`);
754
+ }
755
+ // Check for extra fields
756
+ for (const k in json) {
757
+ if (!(k in fieldFromJson)) {
758
+ throw new JSONDecodeError(`unexpected field "${k}" in Struct, got ${JSON.stringify(json)}`);
759
+ }
760
+ }
761
+ // Create struct
762
+ const obj = {};
763
+ // Populate fields
764
+ for (const k in fieldFromJson) {
765
+ if (!(k in json)) {
766
+ throw new JSONDecodeError(`missing field "${k}" in Struct, got ${JSON.stringify(json)}`);
767
+ }
768
+ ctx.currentPath.push(k);
769
+ try {
770
+ obj[k] = fieldFromJson[k](json[k], ctx);
771
+ }
772
+ catch (e) {
773
+ if (e instanceof JSONDecodeError) {
774
+ const newPath = `.${k}` + (e.path ? e.path : '');
775
+ throw new JSONDecodeError(e.message, newPath);
776
+ }
777
+ throw e;
778
+ }
779
+ ctx.currentPath.pop();
780
+ }
781
+ if (frozen) {
782
+ Object.freeze(obj); // is this overkill?
783
+ }
784
+ return obj;
785
+ };
786
+ typeCtx.push(ret);
787
+ for (const { name, type: t } of type.value) {
788
+ fieldFromJson[name] = createJSONDecoder(t, frozen, typeCtx);
789
+ }
790
+ typeCtx.pop();
791
+ return ret;
792
+ }
793
+ else if (type.type === "Variant") {
794
+ const caseFromJson = {};
795
+ const ret = (json, ctx = { refs: new Map(), currentPath: [] }) => {
796
+ if (typeof json !== "object" || json === null || !("type" in json) || !("value" in json)) {
797
+ throw new JSONDecodeError(`expected object with type and value for Variant, got ${JSON.stringify(json)}`);
798
+ }
799
+ const typeStr = json.type;
800
+ if (!(typeStr in caseFromJson)) {
801
+ throw new JSONDecodeError(`unknown variant type "${typeStr}", got ${JSON.stringify(json)}`);
802
+ }
803
+ const caseFn = caseFromJson[typeStr];
804
+ // Create variant with undefined placeholder
805
+ const v = variant(typeStr, undefined);
806
+ // Decode the value
807
+ ctx.currentPath.push(typeStr);
808
+ try {
809
+ const variantValue = caseFn(json.value, ctx);
810
+ // Mutate the variant's value field
811
+ v.value = variantValue;
812
+ if (frozen) {
813
+ Object.freeze(v);
814
+ }
815
+ return v;
816
+ }
817
+ catch (e) {
818
+ if (e instanceof JSONDecodeError) {
819
+ const newPath = `.${typeStr}` + (e.path ? e.path : '');
820
+ throw new JSONDecodeError(e.message, newPath);
821
+ }
822
+ throw e;
823
+ }
824
+ finally {
825
+ ctx.currentPath.pop();
826
+ }
827
+ };
828
+ typeCtx.push(ret);
829
+ for (const { name, type: t } of type.value) {
830
+ caseFromJson[name] = createJSONDecoder(t, frozen, typeCtx);
831
+ }
832
+ typeCtx.pop();
833
+ return ret;
834
+ }
835
+ else if (type.type === "Recursive") {
836
+ const ret = typeCtx[typeCtx.length - Number(type.value)];
837
+ if (ret === undefined) {
838
+ throw new Error(`Internal error: Recursive type context not found`);
839
+ }
840
+ return ret;
841
+ }
842
+ else if (type.type === "Function") {
843
+ throw new Error(`Cannot decode function type from JSON`);
844
+ }
845
+ else {
846
+ throw new Error(`Unhandled type ${type.type} for fromJson`);
847
+ }
848
+ }
849
+ //# sourceMappingURL=json.js.map