@fncts/schema 0.0.4 → 0.0.6

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 (151) hide show
  1. package/AST.d.ts +528 -0
  2. package/ASTAnnotation.d.ts +82 -0
  3. package/ASTAnnotationMap.d.ts +14 -0
  4. package/Gen.d.ts +15 -0
  5. package/InvalidInterpretationError.d.ts +5 -0
  6. package/ParseError.d.ts +107 -0
  7. package/ParseResult.d.ts +24 -0
  8. package/Parser/api.d.ts +42 -0
  9. package/Parser/definition.d.ts +22 -0
  10. package/Parser/interpreter.d.ts +6 -0
  11. package/Parser.d.ts +2 -0
  12. package/Schema/api/conc.d.ts +18 -0
  13. package/Schema/api/hashMap.d.ts +21 -0
  14. package/Schema/api/immutableArray.d.ts +23 -0
  15. package/Schema/api/list.d.ts +23 -0
  16. package/Schema/api/maybe.d.ts +21 -0
  17. package/Schema/api.d.ts +243 -0
  18. package/Schema/definition.d.ts +29 -0
  19. package/Schema/derivations.d.ts +70 -0
  20. package/Schema.d.ts +2 -144
  21. package/_cjs/AST.cjs +1171 -0
  22. package/_cjs/AST.cjs.map +1 -0
  23. package/_cjs/ASTAnnotation.cjs +111 -0
  24. package/_cjs/ASTAnnotation.cjs.map +1 -0
  25. package/_cjs/ASTAnnotationMap.cjs +35 -0
  26. package/_cjs/ASTAnnotationMap.cjs.map +1 -0
  27. package/_cjs/Gen.cjs +185 -0
  28. package/_cjs/Gen.cjs.map +1 -0
  29. package/_cjs/InvalidInterpretationError.cjs +18 -0
  30. package/_cjs/InvalidInterpretationError.cjs.map +1 -0
  31. package/_cjs/ParseError.cjs +222 -0
  32. package/_cjs/ParseError.cjs.map +1 -0
  33. package/_cjs/{Decoder.cjs → ParseResult.cjs} +24 -22
  34. package/_cjs/ParseResult.cjs.map +1 -0
  35. package/_cjs/Parser/api.cjs +80 -0
  36. package/_cjs/Parser/api.cjs.map +1 -0
  37. package/_cjs/{Guard.cjs → Parser/definition.cjs} +17 -22
  38. package/_cjs/Parser/definition.cjs.map +1 -0
  39. package/_cjs/Parser/interpreter.cjs +409 -0
  40. package/_cjs/Parser/interpreter.cjs.map +1 -0
  41. package/_cjs/Parser.cjs +28 -0
  42. package/_cjs/Parser.cjs.map +1 -0
  43. package/_cjs/Schema/api/conc.cjs +84 -0
  44. package/_cjs/Schema/api/conc.cjs.map +1 -0
  45. package/_cjs/Schema/api/hashMap.cjs +161 -0
  46. package/_cjs/Schema/api/hashMap.cjs.map +1 -0
  47. package/_cjs/Schema/api/immutableArray.cjs +90 -0
  48. package/_cjs/Schema/api/immutableArray.cjs.map +1 -0
  49. package/_cjs/Schema/api/list.cjs +98 -0
  50. package/_cjs/Schema/api/list.cjs.map +1 -0
  51. package/_cjs/Schema/api/maybe.cjs +75 -0
  52. package/_cjs/Schema/api/maybe.cjs.map +1 -0
  53. package/_cjs/Schema/api.cjs +424 -0
  54. package/_cjs/Schema/api.cjs.map +1 -0
  55. package/_cjs/Schema/definition.cjs +26 -0
  56. package/_cjs/Schema/definition.cjs.map +1 -0
  57. package/_cjs/Schema/derivations.cjs +108 -0
  58. package/_cjs/Schema/derivations.cjs.map +1 -0
  59. package/_cjs/Schema.cjs +20 -237
  60. package/_cjs/Schema.cjs.map +1 -1
  61. package/_cjs/utils.cjs +52 -0
  62. package/_cjs/utils.cjs.map +1 -0
  63. package/_mjs/AST.mjs +1060 -0
  64. package/_mjs/AST.mjs.map +1 -0
  65. package/_mjs/ASTAnnotation.mjs +80 -0
  66. package/_mjs/ASTAnnotation.mjs.map +1 -0
  67. package/_mjs/ASTAnnotationMap.mjs +27 -0
  68. package/_mjs/ASTAnnotationMap.mjs.map +1 -0
  69. package/_mjs/Gen.mjs +176 -0
  70. package/_mjs/Gen.mjs.map +1 -0
  71. package/_mjs/InvalidInterpretationError.mjs +10 -0
  72. package/_mjs/InvalidInterpretationError.mjs.map +1 -0
  73. package/_mjs/ParseError.mjs +200 -0
  74. package/_mjs/ParseError.mjs.map +1 -0
  75. package/_mjs/ParseResult.mjs +21 -0
  76. package/_mjs/ParseResult.mjs.map +1 -0
  77. package/_mjs/Parser/api.mjs +67 -0
  78. package/_mjs/Parser/api.mjs.map +1 -0
  79. package/_mjs/Parser/definition.mjs +15 -0
  80. package/_mjs/Parser/definition.mjs.map +1 -0
  81. package/_mjs/Parser/interpreter.mjs +401 -0
  82. package/_mjs/Parser/interpreter.mjs.map +1 -0
  83. package/_mjs/Parser.mjs +4 -0
  84. package/_mjs/Parser.mjs.map +1 -0
  85. package/_mjs/Schema/api/conc.mjs +72 -0
  86. package/_mjs/Schema/api/conc.mjs.map +1 -0
  87. package/_mjs/Schema/api/hashMap.mjs +150 -0
  88. package/_mjs/Schema/api/hashMap.mjs.map +1 -0
  89. package/_mjs/Schema/api/immutableArray.mjs +79 -0
  90. package/_mjs/Schema/api/immutableArray.mjs.map +1 -0
  91. package/_mjs/Schema/api/list.mjs +87 -0
  92. package/_mjs/Schema/api/list.mjs.map +1 -0
  93. package/_mjs/Schema/api/maybe.mjs +64 -0
  94. package/_mjs/Schema/api/maybe.mjs.map +1 -0
  95. package/_mjs/Schema/api.mjs +367 -0
  96. package/_mjs/Schema/api.mjs.map +1 -0
  97. package/_mjs/Schema/definition.mjs +16 -0
  98. package/_mjs/Schema/definition.mjs.map +1 -0
  99. package/_mjs/Schema/derivations.mjs +94 -0
  100. package/_mjs/Schema/derivations.mjs.map +1 -0
  101. package/_mjs/Schema.mjs +3 -212
  102. package/_mjs/Schema.mjs.map +1 -1
  103. package/_mjs/utils.mjs +41 -0
  104. package/_mjs/utils.mjs.map +1 -0
  105. package/_src/AST.ts +1353 -0
  106. package/_src/ASTAnnotation.ts +98 -0
  107. package/_src/ASTAnnotationMap.ts +38 -0
  108. package/_src/Gen.ts +171 -0
  109. package/_src/InvalidInterpretationError.ts +6 -0
  110. package/_src/ParseError.ts +237 -0
  111. package/_src/ParseResult.ts +26 -0
  112. package/_src/Parser/api.ts +71 -0
  113. package/_src/Parser/definition.ts +24 -0
  114. package/_src/Parser/interpreter.ts +442 -0
  115. package/_src/Parser.ts +4 -0
  116. package/_src/Schema/api/conc.ts +78 -0
  117. package/_src/Schema/api/hashMap.ts +184 -0
  118. package/_src/Schema/api/immutableArray.ts +88 -0
  119. package/_src/Schema/api/list.ts +96 -0
  120. package/_src/Schema/api/maybe.ts +68 -0
  121. package/_src/Schema/api.ts +530 -0
  122. package/_src/Schema/definition.ts +32 -0
  123. package/_src/Schema/derivations.ts +185 -0
  124. package/_src/Schema.ts +4 -254
  125. package/_src/global.ts +53 -0
  126. package/_src/utils.ts +48 -0
  127. package/global.d.ts +52 -0
  128. package/package.json +2 -2
  129. package/utils.d.ts +8 -0
  130. package/Decoder.d.ts +0 -3
  131. package/Encoder.d.ts +0 -4
  132. package/Guard.d.ts +0 -3
  133. package/Schemable.d.ts +0 -39
  134. package/_cjs/Decoder.cjs.map +0 -1
  135. package/_cjs/Encoder.cjs +0 -45
  136. package/_cjs/Encoder.cjs.map +0 -1
  137. package/_cjs/Guard.cjs.map +0 -1
  138. package/_cjs/Schemable.cjs +0 -6
  139. package/_cjs/Schemable.cjs.map +0 -1
  140. package/_mjs/Decoder.mjs +0 -20
  141. package/_mjs/Decoder.mjs.map +0 -1
  142. package/_mjs/Encoder.mjs +0 -36
  143. package/_mjs/Encoder.mjs.map +0 -1
  144. package/_mjs/Guard.mjs +0 -20
  145. package/_mjs/Guard.mjs.map +0 -1
  146. package/_mjs/Schemable.mjs +0 -2
  147. package/_mjs/Schemable.mjs.map +0 -1
  148. package/_src/Decoder.ts +0 -20
  149. package/_src/Encoder.ts +0 -38
  150. package/_src/Guard.ts +0 -20
  151. package/_src/Schemable.ts +0 -46
package/_src/AST.ts ADDED
@@ -0,0 +1,1353 @@
1
+ import type { MutableVector } from "@fncts/base/collection/immutable/Vector";
2
+ import type { Validation as ValidationType } from "@fncts/base/data/Branded";
3
+
4
+ import { show } from "@fncts/base/data/Showable";
5
+ import { memoize } from "@fncts/schema/utils";
6
+
7
+ import { ASTAnnotation } from "./ASTAnnotation.js";
8
+ import { ASTAnnotationMap } from "./ASTAnnotationMap.js";
9
+
10
+ export const ASTTypeId = Symbol.for("fncts.schema.AST");
11
+ export type ASTTypeId = typeof ASTTypeId;
12
+
13
+ export abstract class Annotated {
14
+ readonly annotations: ASTAnnotationMap = ASTAnnotationMap.empty;
15
+ }
16
+
17
+ /**
18
+ * @tsplus type fncts.schema.AST
19
+ * @tsplus companion fncts.schema.ASTOps
20
+ */
21
+ export abstract class AST extends Annotated {
22
+ readonly [ASTTypeId]: ASTTypeId = ASTTypeId;
23
+
24
+ abstract clone(newProperties: Partial<this>): AST;
25
+ }
26
+
27
+ export declare namespace AST {
28
+ export interface Compiler<A> {
29
+ (ast: AST): A;
30
+ }
31
+
32
+ export type Match<A> = {
33
+ [K in Concrete["_tag"]]: (ast: Extract<Concrete, { _tag: K }>, compile: Compiler<A>) => A;
34
+ };
35
+ }
36
+
37
+ export const enum ASTTag {
38
+ Declaration,
39
+ Literal,
40
+ UniqueSymbol,
41
+ UndefinedKeyword,
42
+ VoidKeyword,
43
+ NeverKeyword,
44
+ UnknownKeyword,
45
+ AnyKeyword,
46
+ StringKeyword,
47
+ NumberKeyword,
48
+ BooleanKeyword,
49
+ BigIntKeyword,
50
+ SymbolKeyword,
51
+ ObjectKeyword,
52
+ Enum,
53
+ TemplateLiteral,
54
+ Tuple,
55
+ TypeLiteral,
56
+ Union,
57
+ Lazy,
58
+ Refinement,
59
+ Transform,
60
+ Validation,
61
+ }
62
+
63
+ export type Concrete =
64
+ | Declaration
65
+ | Literal
66
+ | UniqueSymbol
67
+ | UndefinedKeyword
68
+ | VoidKeyword
69
+ | NeverKeyword
70
+ | UnknownKeyword
71
+ | AnyKeyword
72
+ | StringKeyword
73
+ | NumberKeyword
74
+ | BooleanKeyword
75
+ | BigIntKeyword
76
+ | SymbolKeyword
77
+ | ObjectKeyword
78
+ | Enum
79
+ | TemplateLiteral
80
+ | Tuple
81
+ | TypeLiteral
82
+ | Union
83
+ | Lazy
84
+ | Refinement
85
+ | Transform
86
+ | Validation;
87
+
88
+ /**
89
+ * @tsplus static fncts.schema.ASTOps concrete
90
+ * @tsplus macro remove
91
+ */
92
+ export function concrete(_: AST): asserts _ is Concrete {
93
+ //
94
+ }
95
+
96
+ export function getAnnotations<V>(key: ASTAnnotation<V>) {
97
+ return (self: Annotated): Maybe<V> => {
98
+ return self.annotations.get(key);
99
+ };
100
+ }
101
+
102
+ /*
103
+ * Declaration
104
+ */
105
+
106
+ export class Declaration extends AST {
107
+ readonly _tag = ASTTag.Declaration;
108
+ constructor(
109
+ readonly typeParameters: Vector<AST>,
110
+ readonly type: AST,
111
+ readonly decode: (
112
+ ...typeParameters: ReadonlyArray<AST>
113
+ ) => (input: any, options?: ParseOptions) => ParseResult<any>,
114
+ readonly annotations: ASTAnnotationMap = ASTAnnotationMap.empty,
115
+ ) {
116
+ super();
117
+ }
118
+
119
+ clone(newProperties: Partial<this>): AST {
120
+ return new Declaration(
121
+ newProperties.typeParameters ?? this.typeParameters,
122
+ newProperties.type ?? this.type,
123
+ newProperties.decode ?? this.decode,
124
+ newProperties.annotations ?? this.annotations,
125
+ );
126
+ }
127
+ }
128
+
129
+ /**
130
+ * @tsplus static fncts.schema.ASTOps createDeclaration
131
+ */
132
+ export function createDeclaration(
133
+ typeParameters: Vector<AST>,
134
+ type: AST,
135
+ decode: (...typeParameters: ReadonlyArray<AST>) => (input: any, options?: ParseOptions) => ParseResult<any>,
136
+ annotations: ASTAnnotationMap = ASTAnnotationMap.empty,
137
+ ): Declaration {
138
+ return new Declaration(typeParameters, type, decode, annotations);
139
+ }
140
+
141
+ /**
142
+ * @tsplus fluent fncts.schema.AST isDeclaration
143
+ */
144
+ export function isDeclaration(self: AST): self is Declaration {
145
+ concrete(self);
146
+ return self._tag === ASTTag.Declaration;
147
+ }
148
+
149
+ /*
150
+ * Literal
151
+ */
152
+
153
+ export type LiteralValue = string | number | boolean | null | bigint;
154
+
155
+ export class Literal extends AST {
156
+ readonly _tag = ASTTag.Literal;
157
+ constructor(readonly literal: LiteralValue, readonly annotations: ASTAnnotationMap = ASTAnnotationMap.empty) {
158
+ super();
159
+ }
160
+
161
+ clone(newProperties: Partial<this>): AST {
162
+ return new Literal(newProperties.literal ?? this.literal, newProperties.annotations ?? this.annotations);
163
+ }
164
+ }
165
+
166
+ /**
167
+ * @tsplus static fncts.schema.ASTOps createLiteral
168
+ */
169
+ export function createLiteral(literal: LiteralValue, annotations: ASTAnnotationMap = ASTAnnotationMap.empty): Literal {
170
+ return new Literal(literal, annotations);
171
+ }
172
+
173
+ /**
174
+ * @tsplus fluent fncts.schema.AST isLiteral
175
+ */
176
+ export function isLiteral(self: AST): self is Literal {
177
+ concrete(self);
178
+ return self._tag === ASTTag.Literal;
179
+ }
180
+
181
+ /*
182
+ * UniqueSymbol
183
+ */
184
+
185
+ export class UniqueSymbol extends AST {
186
+ readonly _tag = ASTTag.UniqueSymbol;
187
+ constructor(readonly symbol: symbol, readonly annotations: ASTAnnotationMap = ASTAnnotationMap.empty) {
188
+ super();
189
+ }
190
+
191
+ clone(newProperties: Partial<this>): AST {
192
+ return new UniqueSymbol(newProperties.symbol ?? this.symbol, newProperties.annotations ?? this.annotations);
193
+ }
194
+ }
195
+
196
+ /**
197
+ * @tsplus static fncts.schema.ASTOps createUniqueSymbol
198
+ */
199
+ export function createUniqueSymbol(
200
+ symbol: symbol,
201
+ annotations: ASTAnnotationMap = ASTAnnotationMap.empty,
202
+ ): UniqueSymbol {
203
+ return new UniqueSymbol(symbol, annotations);
204
+ }
205
+
206
+ /**
207
+ * @tsplus fluent fncts.schema.AST isUniqueSymbol
208
+ */
209
+ export function isUniqueSymbol(self: AST): self is UniqueSymbol {
210
+ concrete(self);
211
+ return self._tag === ASTTag.UniqueSymbol;
212
+ }
213
+
214
+ /*
215
+ * UndefinedKeyword
216
+ */
217
+
218
+ export class UndefinedKeyword extends AST {
219
+ readonly _tag = ASTTag.UndefinedKeyword;
220
+ constructor(readonly annotations: ASTAnnotationMap = ASTAnnotationMap.empty) {
221
+ super();
222
+ }
223
+
224
+ clone(newProperties: Partial<this>): AST {
225
+ return new UndefinedKeyword(newProperties.annotations ?? this.annotations);
226
+ }
227
+ }
228
+
229
+ /**
230
+ * @tsplus static fncts.schema.ASTOps undefinedKeyword
231
+ */
232
+ export const undefinedKeyword: UndefinedKeyword = new UndefinedKeyword(
233
+ ASTAnnotationMap.empty.annotate(ASTAnnotation.Title, "undefined"),
234
+ );
235
+
236
+ /*
237
+ * VoidKeyword
238
+ */
239
+
240
+ export class VoidKeyword extends AST {
241
+ readonly _tag = ASTTag.VoidKeyword;
242
+ constructor(readonly annotations: ASTAnnotationMap = ASTAnnotationMap.empty) {
243
+ super();
244
+ }
245
+
246
+ clone(newProperties: Partial<this>): AST {
247
+ return new VoidKeyword(newProperties.annotations ?? this.annotations);
248
+ }
249
+ }
250
+
251
+ /**
252
+ * @tsplus static fncts.schema.ASTOps voidKeyword
253
+ */
254
+ export const voidKeyword: VoidKeyword = new VoidKeyword(ASTAnnotationMap.empty.annotate(ASTAnnotation.Title, "void"));
255
+
256
+ /*
257
+ * NeverKeyword
258
+ */
259
+
260
+ export class NeverKeyword extends AST {
261
+ readonly _tag = ASTTag.NeverKeyword;
262
+ constructor(readonly annotations: ASTAnnotationMap = ASTAnnotationMap.empty) {
263
+ super();
264
+ }
265
+
266
+ clone(newProperties: Partial<this>): AST {
267
+ return new NeverKeyword(newProperties.annotations ?? this.annotations);
268
+ }
269
+ }
270
+
271
+ /**
272
+ * @tsplus static fncts.schema.ASTOps neverKeyword
273
+ */
274
+ export const neverKeyword: NeverKeyword = new NeverKeyword(
275
+ ASTAnnotationMap.empty.annotate(ASTAnnotation.Title, "never"),
276
+ );
277
+
278
+ /*
279
+ * UnknownKeyword
280
+ */
281
+
282
+ export class UnknownKeyword extends AST {
283
+ readonly _tag = ASTTag.UnknownKeyword;
284
+ constructor(readonly annotations: ASTAnnotationMap = ASTAnnotationMap.empty) {
285
+ super();
286
+ }
287
+
288
+ clone(newProperties: Partial<this>): AST {
289
+ return new UnknownKeyword(newProperties.annotations ?? this.annotations);
290
+ }
291
+ }
292
+
293
+ /**
294
+ * @tsplus static fncts.schema.ASTOps unknownKeyword
295
+ */
296
+ export const unknownKeyword: UnknownKeyword = new UnknownKeyword(
297
+ ASTAnnotationMap.empty.annotate(ASTAnnotation.Title, "unknown"),
298
+ );
299
+
300
+ /*
301
+ * AnyKeyword
302
+ */
303
+
304
+ export class AnyKeyword extends AST {
305
+ readonly _tag = ASTTag.AnyKeyword;
306
+ constructor(readonly annotations: ASTAnnotationMap = ASTAnnotationMap.empty) {
307
+ super();
308
+ }
309
+
310
+ clone(newProperties: Partial<this>): AST {
311
+ return new AnyKeyword(newProperties.annotations ?? this.annotations);
312
+ }
313
+ }
314
+
315
+ /**
316
+ * @tsplus static fncts.schema.ASTOps anyKeyword
317
+ */
318
+ export const anyKeyword: AnyKeyword = new AnyKeyword(ASTAnnotationMap.empty.annotate(ASTAnnotation.Title, "any"));
319
+
320
+ /*
321
+ * StringKeyword
322
+ */
323
+
324
+ export class StringKeyword extends AST {
325
+ readonly _tag = ASTTag.StringKeyword;
326
+ constructor(readonly annotations: ASTAnnotationMap = ASTAnnotationMap.empty) {
327
+ super();
328
+ }
329
+
330
+ clone(newProperties: Partial<this>): AST {
331
+ return new StringKeyword(newProperties.annotations ?? this.annotations);
332
+ }
333
+ }
334
+
335
+ /**
336
+ * @tsplus static fncts.schema.ASTOps stringKeyword
337
+ */
338
+ export const stringKeyword: StringKeyword = new StringKeyword(
339
+ ASTAnnotationMap.empty.annotate(ASTAnnotation.Title, "string"),
340
+ );
341
+
342
+ /**
343
+ * @tsplus fluent fncts.schema.AST isStringKeyword
344
+ */
345
+ export function isStringKeyword(self: AST): self is StringKeyword {
346
+ concrete(self);
347
+ return self._tag === ASTTag.StringKeyword;
348
+ }
349
+
350
+ /*
351
+ * NumberKeyword
352
+ */
353
+
354
+ export class NumberKeyword extends AST {
355
+ readonly _tag = ASTTag.NumberKeyword;
356
+ constructor(readonly annotations: ASTAnnotationMap = ASTAnnotationMap.empty) {
357
+ super();
358
+ }
359
+
360
+ clone(newProperties: Partial<this>): AST {
361
+ return new NumberKeyword(newProperties.annotations ?? this.annotations);
362
+ }
363
+ }
364
+
365
+ /**
366
+ * @tsplus static fncts.schema.ASTOps numberKeyword
367
+ */
368
+ export const numberKeyword: NumberKeyword = new NumberKeyword(
369
+ ASTAnnotationMap.empty.annotate(ASTAnnotation.Title, "number"),
370
+ );
371
+
372
+ /**
373
+ * @tsplus fluent fncts.schema.AST isNumberKeyword
374
+ */
375
+ export function isNumberKeyword(self: AST): self is NumberKeyword {
376
+ concrete(self);
377
+ return self._tag === ASTTag.NumberKeyword;
378
+ }
379
+
380
+ /*
381
+ * BooleanKeyword
382
+ */
383
+
384
+ export class BooleanKeyword extends AST {
385
+ readonly _tag = ASTTag.BooleanKeyword;
386
+ constructor(readonly annotations: ASTAnnotationMap = ASTAnnotationMap.empty) {
387
+ super();
388
+ }
389
+
390
+ clone(newProperties: Partial<this>): AST {
391
+ return new BooleanKeyword(newProperties.annotations ?? this.annotations);
392
+ }
393
+ }
394
+
395
+ /**
396
+ * @tsplus static fncts.schema.ASTOps booleanKeyword
397
+ */
398
+ export const booleanKeyword: BooleanKeyword = new BooleanKeyword(
399
+ ASTAnnotationMap.empty.annotate(ASTAnnotation.Title, "boolean"),
400
+ );
401
+
402
+ /**
403
+ * @tsplus fluent fncts.schema.AST isBooleanKeyword
404
+ */
405
+ export function isBooleanKeyword(self: AST): self is BooleanKeyword {
406
+ concrete(self);
407
+ return self._tag === ASTTag.BooleanKeyword;
408
+ }
409
+
410
+ /*
411
+ * BigIntKeyword
412
+ */
413
+
414
+ export class BigIntKeyword extends AST {
415
+ readonly _tag = ASTTag.BigIntKeyword;
416
+ constructor(readonly annotations: ASTAnnotationMap = ASTAnnotationMap.empty) {
417
+ super();
418
+ }
419
+
420
+ clone(newProperties: Partial<this>): AST {
421
+ return new BigIntKeyword(newProperties.annotations ?? this.annotations);
422
+ }
423
+ }
424
+
425
+ /**
426
+ * @tsplus static fncts.schema.ASTOps bigIntKeyword
427
+ */
428
+ export const bigIntKeyword: BigIntKeyword = new BigIntKeyword(
429
+ ASTAnnotationMap.empty.annotate(ASTAnnotation.Title, "bigint"),
430
+ );
431
+
432
+ /**
433
+ * @tsplus fluent fncts.schema.AST isBigIntKeyword
434
+ */
435
+ export function isBigIntKeyword(self: AST): self is BigIntKeyword {
436
+ concrete(self);
437
+ return self._tag === ASTTag.BigIntKeyword;
438
+ }
439
+
440
+ /*
441
+ * SymbolKeyword
442
+ */
443
+
444
+ export class SymbolKeyword extends AST {
445
+ readonly _tag = ASTTag.SymbolKeyword;
446
+ constructor(readonly annotations: ASTAnnotationMap = ASTAnnotationMap.empty) {
447
+ super();
448
+ }
449
+
450
+ clone(newProperties: Partial<this>): AST {
451
+ return new SymbolKeyword(newProperties.annotations ?? this.annotations);
452
+ }
453
+ }
454
+
455
+ /**
456
+ * @tsplus static fncts.schema.ASTOps symbolKeyword
457
+ */
458
+ export const symbolKeyword: SymbolKeyword = new SymbolKeyword(
459
+ ASTAnnotationMap.empty.annotate(ASTAnnotation.Title, "symbol"),
460
+ );
461
+
462
+ /**
463
+ * @tsplus fluent fncts.schema.AST isSymbolKeyword
464
+ */
465
+ export function isSymbolKeyword(self: AST): self is SymbolKeyword {
466
+ concrete(self);
467
+ return self._tag === ASTTag.SymbolKeyword;
468
+ }
469
+
470
+ /*
471
+ * ObjectKeyword
472
+ */
473
+
474
+ export class ObjectKeyword extends AST {
475
+ readonly _tag = ASTTag.ObjectKeyword;
476
+ constructor(readonly annotations: ASTAnnotationMap = ASTAnnotationMap.empty) {
477
+ super();
478
+ }
479
+
480
+ clone(newProperties: Partial<this>): AST {
481
+ return new ObjectKeyword(newProperties.annotations ?? this.annotations);
482
+ }
483
+ }
484
+
485
+ /**
486
+ * @tsplus static fncts.schema.ASTOps objectKeyword
487
+ */
488
+ export const objectKeyword: ObjectKeyword = new ObjectKeyword(
489
+ ASTAnnotationMap.empty.annotate(ASTAnnotation.Title, "object"),
490
+ );
491
+
492
+ /*
493
+ * Enum
494
+ */
495
+
496
+ export class Enum extends AST {
497
+ readonly _tag = ASTTag.Enum;
498
+ constructor(
499
+ readonly enums: Vector<readonly [string, string | number]>,
500
+ readonly annotations: ASTAnnotationMap = ASTAnnotationMap.empty,
501
+ ) {
502
+ super();
503
+ }
504
+
505
+ clone(newProperties: Partial<this>): AST {
506
+ return new Enum(newProperties.enums ?? this.enums, newProperties.annotations ?? this.annotations);
507
+ }
508
+ }
509
+
510
+ /**
511
+ * @tsplus static fncts.schema.ASTOps createEnum
512
+ */
513
+ export function createEnum(
514
+ enums: Vector<readonly [string, string | number]>,
515
+ annotations: ASTAnnotationMap = ASTAnnotationMap.empty,
516
+ ): Enum {
517
+ return new Enum(enums, annotations);
518
+ }
519
+
520
+ export class TemplateLiteralSpan {
521
+ constructor(readonly type: StringKeyword | NumberKeyword, readonly literal: string) {}
522
+ }
523
+
524
+ /*
525
+ * TemplateLiteral
526
+ */
527
+
528
+ export class TemplateLiteral extends AST {
529
+ readonly _tag = ASTTag.TemplateLiteral;
530
+ constructor(
531
+ readonly head: string,
532
+ readonly spans: Vector<TemplateLiteralSpan>,
533
+ readonly annotations: ASTAnnotationMap = ASTAnnotationMap.empty,
534
+ ) {
535
+ super();
536
+ }
537
+
538
+ clone(newProperties: Partial<this>): AST {
539
+ return createTemplateLiteral(
540
+ newProperties.head ?? this.head,
541
+ newProperties.spans ?? this.spans,
542
+ newProperties.annotations ?? this.annotations,
543
+ );
544
+ }
545
+ }
546
+
547
+ /**
548
+ * @tsplus static fncts.schema.ASTOps createTemplateLiteral
549
+ */
550
+ export function createTemplateLiteral(
551
+ head: string,
552
+ spans: Vector<TemplateLiteralSpan>,
553
+ annotations: ASTAnnotationMap = ASTAnnotationMap.empty,
554
+ ): TemplateLiteral | Literal {
555
+ if (spans.isNonEmpty()) {
556
+ return new TemplateLiteral(head, spans, annotations);
557
+ } else {
558
+ return createLiteral(head, annotations);
559
+ }
560
+ }
561
+
562
+ /*
563
+ * Element
564
+ */
565
+
566
+ export class Element {
567
+ constructor(readonly type: AST, readonly isOptional: boolean) {}
568
+ }
569
+
570
+ /**
571
+ * @tsplus static fncts.schema.ASTOps createElement
572
+ */
573
+ export function createElement(type: AST, isOptional: boolean): Element {
574
+ return new Element(type, isOptional);
575
+ }
576
+
577
+ /*
578
+ * Tuple
579
+ */
580
+
581
+ export class Tuple extends AST {
582
+ readonly _tag = ASTTag.Tuple;
583
+ constructor(
584
+ readonly elements: Vector<Element>,
585
+ readonly rest: Maybe<Vector<AST>>,
586
+ readonly isReadonly: boolean,
587
+ readonly annotations: ASTAnnotationMap = ASTAnnotationMap.empty,
588
+ ) {
589
+ super();
590
+ }
591
+
592
+ clone(newProperties: Partial<this>): AST {
593
+ return new Tuple(
594
+ newProperties.elements ?? this.elements,
595
+ newProperties.rest ?? this.rest,
596
+ newProperties.isReadonly ?? this.isReadonly,
597
+ newProperties.annotations ?? this.annotations,
598
+ );
599
+ }
600
+ }
601
+
602
+ /**
603
+ * @tsplus static fncts.schema.ASTOps createTuple
604
+ */
605
+ export function createTuple(
606
+ elements: Vector<Element>,
607
+ rest: Maybe<Vector<AST>>,
608
+ isReadonly: boolean,
609
+ annotations: ASTAnnotationMap = ASTAnnotationMap.empty,
610
+ ): Tuple {
611
+ return new Tuple(elements, rest, isReadonly, annotations);
612
+ }
613
+
614
+ /*
615
+ * PropertySignature
616
+ */
617
+
618
+ export class PropertySignature extends AST {
619
+ constructor(
620
+ readonly name: PropertyKey,
621
+ readonly type: AST,
622
+ readonly isOptional: boolean,
623
+ readonly isReadonly: boolean,
624
+ readonly annotations: ASTAnnotationMap = ASTAnnotationMap.empty,
625
+ ) {
626
+ super();
627
+ }
628
+
629
+ clone(newProperties: Partial<this>): AST {
630
+ return new PropertySignature(
631
+ newProperties.name ?? this.name,
632
+ newProperties.type ?? this.type,
633
+ newProperties.isOptional ?? this.isOptional,
634
+ newProperties.isReadonly ?? this.isReadonly,
635
+ newProperties.annotations ?? this.annotations,
636
+ );
637
+ }
638
+ }
639
+
640
+ /**
641
+ * @tsplus static fncts.schema.ASTOps createPropertySignature
642
+ */
643
+ export function createPropertySignature(
644
+ name: PropertyKey,
645
+ type: AST,
646
+ isOptional: boolean,
647
+ isReadonly: boolean,
648
+ annotations: ASTAnnotationMap = ASTAnnotationMap.empty,
649
+ ): PropertySignature {
650
+ return new PropertySignature(name, type, isOptional, isReadonly, annotations);
651
+ }
652
+
653
+ /*
654
+ * IndexSignature
655
+ */
656
+
657
+ export class IndexSignature {
658
+ constructor(
659
+ readonly parameter: StringKeyword | SymbolKeyword | TemplateLiteral | Refinement,
660
+ readonly type: AST,
661
+ readonly isReadonly: boolean,
662
+ ) {}
663
+ }
664
+
665
+ /**
666
+ * @tsplus static fncts.schema.ASTOps createIndexSignature
667
+ */
668
+ export function createIndexSignature(
669
+ parameter: StringKeyword | SymbolKeyword | TemplateLiteral | Refinement,
670
+ type: AST,
671
+ isReadonly: boolean,
672
+ ): IndexSignature {
673
+ return new IndexSignature(parameter, type, isReadonly);
674
+ }
675
+
676
+ /*
677
+ * TypeLiteral
678
+ */
679
+
680
+ export class TypeLiteral extends AST {
681
+ readonly _tag = ASTTag.TypeLiteral;
682
+ readonly propertySignatures: Vector<PropertySignature>;
683
+ readonly indexSignatures: Vector<IndexSignature>;
684
+ constructor(
685
+ propertySignatures: Vector<PropertySignature>,
686
+ indexSignatures: Vector<IndexSignature>,
687
+ readonly annotations: ASTAnnotationMap = ASTAnnotationMap.empty,
688
+ ) {
689
+ super();
690
+ this.propertySignatures = sortByAscendingCardinality(propertySignatures);
691
+ this.indexSignatures = sortByAscendingCardinality(indexSignatures);
692
+ }
693
+
694
+ clone(newProperties: Partial<this>): AST {
695
+ return new TypeLiteral(
696
+ newProperties.propertySignatures ?? this.propertySignatures,
697
+ newProperties.indexSignatures ?? this.indexSignatures,
698
+ newProperties.annotations ?? this.annotations,
699
+ );
700
+ }
701
+ }
702
+
703
+ /**
704
+ * @tsplus static fncts.schema.ASTOps isTypeLiteral
705
+ * @tsplus fluent fncts.schema.AST isTypeLiteral
706
+ */
707
+ export function isTypeLiteral(self: AST): self is TypeLiteral {
708
+ concrete(self);
709
+ return self._tag === ASTTag.TypeLiteral;
710
+ }
711
+
712
+ /**
713
+ * @tsplus static fncts.schema.ASTOps createTypeLiteral
714
+ */
715
+ export function createTypeLiteral(
716
+ propertySignatures: Vector<PropertySignature>,
717
+ indexSignatures: Vector<IndexSignature>,
718
+ annotations?: ASTAnnotationMap,
719
+ ): TypeLiteral {
720
+ return new TypeLiteral(propertySignatures, indexSignatures, annotations);
721
+ }
722
+
723
+ /*
724
+ * Union
725
+ */
726
+
727
+ export class Union extends AST {
728
+ readonly _tag = ASTTag.Union;
729
+ constructor(readonly types: Vector<AST>, readonly annotations: ASTAnnotationMap = ASTAnnotationMap.empty) {
730
+ super();
731
+ }
732
+
733
+ clone(newProperties: Partial<this>): AST {
734
+ return createUnion(newProperties.types ?? this.types, newProperties.annotations ?? this.annotations);
735
+ }
736
+ }
737
+
738
+ /**
739
+ * @tsplus fluent fncts.schema.AST isUnion
740
+ */
741
+ export function isUnion(self: AST): self is Union {
742
+ concrete(self);
743
+ return self._tag === ASTTag.Union;
744
+ }
745
+
746
+ /**
747
+ * @tsplus static fncts.schema.ASTOps createUnion
748
+ */
749
+ export function createUnion(candidates: Vector<AST>, annotations: ASTAnnotationMap = ASTAnnotationMap.empty) {
750
+ const types = unify(candidates);
751
+ switch (types.length) {
752
+ case 0:
753
+ return neverKeyword;
754
+ case 1:
755
+ return types.unsafeGet(0)!;
756
+ default:
757
+ return new Union(sortByDescendingWeight(types), annotations);
758
+ }
759
+ }
760
+
761
+ /*
762
+ * Lazy
763
+ */
764
+
765
+ export class Lazy extends AST {
766
+ readonly _tag = ASTTag.Lazy;
767
+ constructor(readonly getAST: () => AST, readonly annotations: ASTAnnotationMap = ASTAnnotationMap.empty) {
768
+ super();
769
+ }
770
+
771
+ clone(newProperties: Partial<this>): AST {
772
+ return new Lazy(newProperties.getAST ?? this.getAST, newProperties.annotations ?? this.annotations);
773
+ }
774
+ }
775
+
776
+ /**
777
+ * @tsplus static fncts.schema.ASTOps createLazy
778
+ */
779
+ export function createLazy(getAST: () => AST, annotations?: ASTAnnotationMap) {
780
+ return new Lazy(getAST, annotations);
781
+ }
782
+
783
+ /**
784
+ * @tsplus fluent fncts.schema.AST isLazy
785
+ */
786
+ export function isLazy(self: AST): self is Lazy {
787
+ AST.concrete(self);
788
+ return self._tag === ASTTag.Lazy;
789
+ }
790
+
791
+ /*
792
+ * Refinement
793
+ */
794
+
795
+ export class Refinement extends AST {
796
+ readonly _tag = ASTTag.Refinement;
797
+ constructor(
798
+ readonly from: AST,
799
+ readonly decode: (input: any, options?: ParseOptions) => ParseResult<any>,
800
+ readonly isReversed: boolean,
801
+ readonly annotations: ASTAnnotationMap = ASTAnnotationMap.empty,
802
+ ) {
803
+ super();
804
+ }
805
+
806
+ clone(newProperties: Partial<this>): AST {
807
+ return new Refinement(
808
+ newProperties.from ?? this.from,
809
+ newProperties.decode ?? this.decode,
810
+ newProperties.isReversed ?? this.isReversed,
811
+ newProperties.annotations ?? this.annotations,
812
+ );
813
+ }
814
+ }
815
+
816
+ /**
817
+ * @tsplus static fncts.schema.ASTOps createRefinement
818
+ */
819
+ export function createRefinement(
820
+ from: AST,
821
+ decode: (input: any, options?: ParseOptions) => ParseResult<any>,
822
+ isReversed: boolean,
823
+ annotations?: ASTAnnotationMap,
824
+ ): Refinement {
825
+ return new Refinement(from, decode, isReversed, annotations);
826
+ }
827
+
828
+ export function isRefinement(self: AST): self is Refinement {
829
+ concrete(self);
830
+ return self._tag === ASTTag.Refinement;
831
+ }
832
+
833
+ export interface ParseOptions {
834
+ readonly isUnexpectedAllowed?: boolean;
835
+ readonly allErrors?: boolean;
836
+ }
837
+
838
+ /*
839
+ * Transform
840
+ */
841
+
842
+ export class Transform extends AST {
843
+ readonly _tag = ASTTag.Transform;
844
+ constructor(
845
+ readonly from: AST,
846
+ readonly to: AST,
847
+ readonly decode: (input: any, options?: ParseOptions) => ParseResult<any>,
848
+ readonly encode: (input: any, options?: ParseOptions) => ParseResult<any>,
849
+ readonly isReversed: boolean,
850
+ readonly annotations: ASTAnnotationMap = ASTAnnotationMap.empty,
851
+ ) {
852
+ super();
853
+ }
854
+
855
+ clone(newProperties: Partial<this>): AST {
856
+ return new Transform(
857
+ newProperties.from ?? this.from,
858
+ newProperties.to ?? this.to,
859
+ newProperties.decode ?? this.decode,
860
+ newProperties.encode ?? this.encode,
861
+ newProperties.isReversed ?? this.isReversed,
862
+ newProperties.annotations ?? this.annotations,
863
+ );
864
+ }
865
+ }
866
+
867
+ /**
868
+ * @tsplus static fncts.schema.ASTOps createTransform
869
+ */
870
+ export function createTransform(
871
+ from: AST,
872
+ to: AST,
873
+ decode: (input: any, options?: ParseOptions) => ParseResult<any>,
874
+ encode: (input: any, options?: ParseOptions) => ParseResult<any>,
875
+ isReversed: boolean,
876
+ annotations?: ASTAnnotationMap,
877
+ ): Transform {
878
+ return new Transform(from, getTo(to), decode, encode, isReversed, annotations);
879
+ }
880
+
881
+ /*
882
+ * Validation
883
+ */
884
+
885
+ export class Validation extends AST {
886
+ readonly _tag = ASTTag.Validation;
887
+ constructor(
888
+ readonly from: AST,
889
+ readonly validation: Vector<ValidationType<any, string>>,
890
+ readonly annotations: ASTAnnotationMap = ASTAnnotationMap.empty,
891
+ ) {
892
+ super();
893
+ }
894
+ clone(newProperties: Partial<this>): AST {
895
+ return new Validation(
896
+ newProperties.from ?? this.from,
897
+ newProperties.validation ?? this.validation,
898
+ newProperties.annotations ?? this.annotations,
899
+ );
900
+ }
901
+ }
902
+
903
+ /**
904
+ * @tsplus static fncts.schema.ASTOps createValidation
905
+ */
906
+ export function createValidation(
907
+ from: AST,
908
+ validation: Vector<ValidationType<any, string>>,
909
+ annotations?: ASTAnnotationMap,
910
+ ): Validation {
911
+ return new Validation(from, validation, annotations);
912
+ }
913
+
914
+ /**
915
+ * @tsplus tailRec
916
+ */
917
+ export function getCardinality(ast: AST): number {
918
+ concrete(ast);
919
+ switch (ast._tag) {
920
+ case ASTTag.Declaration:
921
+ return getCardinality(ast.type);
922
+ case ASTTag.NeverKeyword:
923
+ return 0;
924
+ case ASTTag.Literal:
925
+ case ASTTag.UndefinedKeyword:
926
+ case ASTTag.VoidKeyword:
927
+ case ASTTag.UniqueSymbol:
928
+ return 1;
929
+ case ASTTag.BooleanKeyword:
930
+ return 2;
931
+ case ASTTag.StringKeyword:
932
+ case ASTTag.NumberKeyword:
933
+ case ASTTag.BigIntKeyword:
934
+ case ASTTag.SymbolKeyword:
935
+ return 3;
936
+ case ASTTag.ObjectKeyword:
937
+ return 4;
938
+ case ASTTag.UnknownKeyword:
939
+ case ASTTag.AnyKeyword:
940
+ return 6;
941
+ case ASTTag.Refinement:
942
+ return getCardinality(ast.from);
943
+ case ASTTag.Transform:
944
+ return getCardinality(ast.to);
945
+ default:
946
+ return 5;
947
+ }
948
+ }
949
+
950
+ function sortByAscendingCardinality<A extends { readonly type: AST }>(types: Vector<A>): Vector<A> {
951
+ return types.sort(Number.Ord.contramap(({ type }) => getCardinality(type)));
952
+ }
953
+
954
+ export function getWeight(ast: AST): number {
955
+ concrete(ast);
956
+ switch (ast._tag) {
957
+ case ASTTag.Declaration:
958
+ return getWeight(ast.type);
959
+ case ASTTag.Tuple:
960
+ return ast.elements.length + (ast.rest.isJust() ? ast.rest.value.length : 0);
961
+ case ASTTag.TypeLiteral:
962
+ return ast.propertySignatures.length + ast.indexSignatures.length;
963
+ case ASTTag.Union:
964
+ return ast.types.foldLeft(0, (n, member) => n + getWeight(member));
965
+ case ASTTag.Lazy:
966
+ return 10;
967
+ case ASTTag.Refinement:
968
+ return getWeight(ast.from);
969
+ case ASTTag.Transform:
970
+ return getWeight(ast.to);
971
+ default:
972
+ return 0;
973
+ }
974
+ }
975
+
976
+ function sortByDescendingWeight(types: Vector<AST>): Vector<AST> {
977
+ return types.sort(Number.Ord.contramap(getWeight));
978
+ }
979
+
980
+ function unify(candidates: Vector<AST>): Vector<AST> {
981
+ let out = candidates.flatMap((ast) => {
982
+ concrete(ast);
983
+ switch (ast._tag) {
984
+ case ASTTag.NeverKeyword:
985
+ return Vector.empty<AST>();
986
+ case ASTTag.Union:
987
+ return ast.types;
988
+ default:
989
+ return Vector(ast);
990
+ }
991
+ });
992
+ if (out.some(isStringKeyword)) {
993
+ out = out.filter((m) => !(m.isLiteral() && typeof m.literal === "string"));
994
+ }
995
+ if (out.some(isNumberKeyword)) {
996
+ out = out.filter((m) => !(m.isLiteral() && typeof m.literal === "number"));
997
+ }
998
+ if (out.some(isSymbolKeyword)) {
999
+ out = out.filter((m) => !m.isUniqueSymbol());
1000
+ }
1001
+ return out;
1002
+ }
1003
+
1004
+ /**
1005
+ * @tsplus pipeable fncts.schema.AST combineAnnotations
1006
+ */
1007
+ export function combineAnnotations(annotations: ASTAnnotationMap) {
1008
+ return (self: AST): AST => {
1009
+ return self.clone({ annotations: self.annotations.combine(annotations) });
1010
+ };
1011
+ }
1012
+
1013
+ /**
1014
+ * @tsplus pipeable fncts.schema.AST setAnnotation
1015
+ */
1016
+ export function setAnnotation<A>(annotation: ASTAnnotation<A>, value: A) {
1017
+ return (self: AST): AST => {
1018
+ return self.clone({ annotations: self.annotations.annotate(annotation, value) });
1019
+ };
1020
+ }
1021
+
1022
+ /**
1023
+ * @tsplus pipeable fncts.schema.AST appendRestElement
1024
+ */
1025
+ export function appendRestElement(restElement: AST) {
1026
+ return (self: Tuple): Tuple => {
1027
+ if (self.rest.isJust()) {
1028
+ throw new Error("A rest element cannot follow another rest element. ts(1265)");
1029
+ }
1030
+ return createTuple(self.elements, Just(Vector(restElement)), self.isReadonly, self.annotations);
1031
+ };
1032
+ }
1033
+
1034
+ /**
1035
+ * @tsplus pipeable fncts.schema.AST appendElement
1036
+ */
1037
+ export function appendElement(element: Element) {
1038
+ return (self: Tuple): Tuple => {
1039
+ if (self.elements.some((e) => e.isOptional) && !element.isOptional) {
1040
+ throw new Error("A required element cannot follow an optional element. ts(1257)");
1041
+ }
1042
+ return self.rest.match(
1043
+ () => createTuple(self.elements.append(element), Nothing(), self.isReadonly, self.annotations),
1044
+ (rest) => {
1045
+ if (element.isOptional) {
1046
+ throw new Error("A required element cannot follow an optional element. ts(1257)");
1047
+ }
1048
+ return createTuple(self.elements, Just(rest.append(element.type)), self.isReadonly, self.annotations);
1049
+ },
1050
+ );
1051
+ };
1052
+ }
1053
+
1054
+ export function getParameter(x: IndexSignature["parameter"]): StringKeyword | SymbolKeyword | TemplateLiteral {
1055
+ return isRefinement(x) ? getParameter(x.from as any) : x;
1056
+ }
1057
+
1058
+ /**
1059
+ * @tsplus getter fncts.schema.AST getPropertySignatures
1060
+ */
1061
+ export function getPropertySignatures(self: AST): Vector<PropertySignature> {
1062
+ concrete(self);
1063
+ switch (self._tag) {
1064
+ case ASTTag.Declaration:
1065
+ return getPropertySignatures(self.type);
1066
+ case ASTTag.Tuple:
1067
+ return self.elements.mapWithIndex((i, element) =>
1068
+ createPropertySignature(i, element.type, element.isOptional, self.isReadonly),
1069
+ );
1070
+ case ASTTag.Union: {
1071
+ const propertySignatures = self.types.map(getPropertySignatures);
1072
+ return propertySignatures[0]!.filterMap(({ name }) => {
1073
+ if (propertySignatures.every((ps) => ps.some((p) => p.name === name))) {
1074
+ const members = propertySignatures.flatMap((ps) => ps.filter((p) => p.name === name));
1075
+ return Just(
1076
+ createPropertySignature(
1077
+ name,
1078
+ createUnion(members.map((p) => p.type)),
1079
+ members.some((p) => p.isOptional),
1080
+ members.some((p) => p.isReadonly),
1081
+ ),
1082
+ );
1083
+ }
1084
+ return Nothing();
1085
+ });
1086
+ }
1087
+ case ASTTag.Lazy:
1088
+ return getPropertySignatures(self.getAST());
1089
+ case ASTTag.Refinement:
1090
+ return getPropertySignatures(self.from);
1091
+ case ASTTag.Transform:
1092
+ return getPropertySignatures(self.to);
1093
+ default:
1094
+ return Vector.empty();
1095
+ }
1096
+ }
1097
+
1098
+ /**
1099
+ * @tsplus getter fncts.schema.AST keysof
1100
+ */
1101
+ export function keysOf(ast: AST): Vector<AST> {
1102
+ concrete(ast);
1103
+ switch (ast._tag) {
1104
+ case ASTTag.Declaration:
1105
+ return keysOf(ast.type);
1106
+ case ASTTag.NeverKeyword:
1107
+ case ASTTag.AnyKeyword:
1108
+ return Vector(stringKeyword, numberKeyword, symbolKeyword);
1109
+ case ASTTag.StringKeyword:
1110
+ return Vector(createLiteral("length"));
1111
+ case ASTTag.TypeLiteral:
1112
+ return ast.propertySignatures
1113
+ .map((p) => (typeof p.name === "symbol" ? createUniqueSymbol(p.name) : createLiteral(p.name)))
1114
+ .concat(ast.indexSignatures.map((is) => getParameter(is.parameter)));
1115
+ case ASTTag.Union:
1116
+ return getPropertySignatures(ast).map((p) =>
1117
+ typeof p.name === "symbol" ? createUniqueSymbol(p.name) : createLiteral(p.name),
1118
+ );
1119
+ case ASTTag.Lazy:
1120
+ return keysOf(ast.getAST());
1121
+ case ASTTag.Refinement:
1122
+ return keysOf(ast.from);
1123
+ case ASTTag.Transform:
1124
+ return keysOf(ast.to);
1125
+ default:
1126
+ return Vector.empty();
1127
+ }
1128
+ }
1129
+
1130
+ /**
1131
+ * @tsplus getter fncts.schema.AST keyof
1132
+ */
1133
+ export function keyof(self: AST): AST {
1134
+ return AST.createUnion(self.keysof);
1135
+ }
1136
+
1137
+ /**
1138
+ * @tsplus static fncts.schema.ASTOps createRecord
1139
+ */
1140
+ export function createRecord(key: AST, value: AST, isReadonly: boolean): TypeLiteral {
1141
+ const propertySignatures: MutableVector<PropertySignature> = Vector.emptyPushable();
1142
+ const indexSignatures: MutableVector<IndexSignature> = Vector.emptyPushable();
1143
+
1144
+ function go(key: AST): void {
1145
+ concrete(key);
1146
+ switch (key._tag) {
1147
+ case ASTTag.Declaration:
1148
+ go(key.type);
1149
+ break;
1150
+ case ASTTag.NeverKeyword:
1151
+ break;
1152
+ case ASTTag.StringKeyword:
1153
+ case ASTTag.SymbolKeyword:
1154
+ case ASTTag.TemplateLiteral:
1155
+ case ASTTag.Refinement:
1156
+ indexSignatures.push(createIndexSignature(key, value, isReadonly));
1157
+ break;
1158
+ case ASTTag.Literal:
1159
+ if (typeof key.literal === "string" || typeof key.literal === "number") {
1160
+ propertySignatures.push(createPropertySignature(key.literal, value, false, isReadonly));
1161
+ }
1162
+ break;
1163
+ case ASTTag.UniqueSymbol:
1164
+ propertySignatures.push(createPropertySignature(key.symbol, value, false, isReadonly));
1165
+ break;
1166
+ case ASTTag.Union:
1167
+ key.types.forEach(go);
1168
+ break;
1169
+ default:
1170
+ throw new Error(`createRecord: Unsupported key\n${show(key)}`);
1171
+ }
1172
+ }
1173
+ go(key);
1174
+ return createTypeLiteral(propertySignatures, indexSignatures);
1175
+ }
1176
+
1177
+ /**
1178
+ * @tsplus pipeable fncts.schema.AST pick
1179
+ */
1180
+ export function pick(keys: Vector<PropertyKey>) {
1181
+ return (self: AST): TypeLiteral => {
1182
+ return createTypeLiteral(
1183
+ self.getPropertySignatures.filter((ps) => keys.includes(ps.name)),
1184
+ Vector.empty(),
1185
+ );
1186
+ };
1187
+ }
1188
+
1189
+ /**
1190
+ * @tsplus pipeable fncts.schema.AST omit
1191
+ */
1192
+ export function omit(keys: Vector<PropertyKey>) {
1193
+ return (self: AST): TypeLiteral => {
1194
+ return createTypeLiteral(
1195
+ self.getPropertySignatures.filter((ps) => !keys.includes(ps.name)),
1196
+ Vector.empty(),
1197
+ );
1198
+ };
1199
+ }
1200
+
1201
+ /**
1202
+ * @tsplus getter fncts.schema.AST partial
1203
+ */
1204
+ export function partial(self: AST): AST {
1205
+ concrete(self);
1206
+ switch (self._tag) {
1207
+ case ASTTag.Declaration:
1208
+ return partial(self.type);
1209
+ case ASTTag.Tuple:
1210
+ return createTuple(
1211
+ self.elements.map((e) => createElement(e.type, true)),
1212
+ self.rest.map((rest) => Vector(createUnion(rest.append(undefinedKeyword)))),
1213
+ self.isReadonly,
1214
+ );
1215
+ case ASTTag.TypeLiteral:
1216
+ return createTypeLiteral(
1217
+ self.propertySignatures.map((f) => createPropertySignature(f.name, f.type, true, f.isReadonly, f.annotations)),
1218
+ self.indexSignatures,
1219
+ );
1220
+ case ASTTag.Union:
1221
+ return createUnion(self.types.map(partial));
1222
+ case ASTTag.Lazy:
1223
+ return createLazy(() => partial(self.getAST()));
1224
+ case ASTTag.Refinement:
1225
+ return partial(self.from);
1226
+ case ASTTag.Transform:
1227
+ return partial(self.to);
1228
+ default:
1229
+ return self;
1230
+ }
1231
+ }
1232
+
1233
+ /**
1234
+ * @tsplus static fncts.schema.AST createKey
1235
+ */
1236
+ export function createKey(key: PropertyKey): AST {
1237
+ return typeof key === "symbol" ? AST.createUniqueSymbol(key) : AST.createLiteral(key);
1238
+ }
1239
+
1240
+ /**
1241
+ * @tsplus getter fncts.schema.AST getFrom
1242
+ */
1243
+ export function getFrom(ast: AST): AST {
1244
+ AST.concrete(ast);
1245
+ switch (ast._tag) {
1246
+ case ASTTag.Declaration:
1247
+ return AST.createDeclaration(ast.typeParameters.map(getFrom), ast.type, ast.decode, ast.annotations);
1248
+ case ASTTag.Tuple:
1249
+ return AST.createTuple(
1250
+ ast.elements.map((element) => AST.createElement(getFrom(element.type), element.isOptional)),
1251
+ ast.rest.map((restElement) => restElement.map(getFrom)),
1252
+ ast.isReadonly,
1253
+ ast.annotations,
1254
+ );
1255
+ case ASTTag.TypeLiteral:
1256
+ return AST.createTypeLiteral(
1257
+ ast.propertySignatures.map((ps) =>
1258
+ AST.createPropertySignature(ps.name, getFrom(ps.type), ps.isOptional, ps.isReadonly, ps.annotations),
1259
+ ),
1260
+ ast.indexSignatures.map((is) => AST.createIndexSignature(is.parameter, getFrom(is.type), is.isReadonly)),
1261
+ ast.annotations,
1262
+ );
1263
+ case ASTTag.Union:
1264
+ return AST.createUnion(ast.types.map(getFrom), ast.annotations);
1265
+ case ASTTag.Lazy:
1266
+ return AST.createLazy(() => getFrom(ast.getAST()), ast.annotations);
1267
+ case ASTTag.Refinement:
1268
+ case ASTTag.Transform:
1269
+ return getFrom(ast.from);
1270
+ }
1271
+ return ast;
1272
+ }
1273
+
1274
+ /**
1275
+ * @tsplus getter fncts.schema.AST getTo
1276
+ */
1277
+ export function getTo(ast: AST): AST {
1278
+ AST.concrete(ast);
1279
+ switch (ast._tag) {
1280
+ case ASTTag.Declaration:
1281
+ return AST.createDeclaration(ast.typeParameters.map(getTo), ast.type, ast.decode, ast.annotations);
1282
+ case ASTTag.Tuple:
1283
+ return AST.createTuple(
1284
+ ast.elements.map((element) => AST.createElement(getTo(element.type), element.isOptional)),
1285
+ ast.rest.map((restElement) => restElement.map(getTo)),
1286
+ ast.isReadonly,
1287
+ ast.annotations,
1288
+ );
1289
+ case ASTTag.TypeLiteral:
1290
+ return AST.createTypeLiteral(
1291
+ ast.propertySignatures.map((ps) =>
1292
+ AST.createPropertySignature(ps.name, getTo(ps.type), ps.isOptional, ps.isReadonly, ps.annotations),
1293
+ ),
1294
+ ast.indexSignatures.map((is) => AST.createIndexSignature(is.parameter, getTo(is.type), is.isReadonly)),
1295
+ ast.annotations,
1296
+ );
1297
+ case ASTTag.Union:
1298
+ return AST.createUnion(ast.types.map(getTo), ast.annotations);
1299
+ case ASTTag.Lazy:
1300
+ return AST.createLazy(() => getTo(ast.getAST()), ast.annotations);
1301
+ case ASTTag.Refinement:
1302
+ return AST.createRefinement(getTo(ast.from), ast.decode, false, ast.annotations);
1303
+ case ASTTag.Transform:
1304
+ return getTo(ast.to);
1305
+ }
1306
+ return ast;
1307
+ }
1308
+
1309
+ /**
1310
+ * @tsplus getter fncts.schema.AST reverse
1311
+ */
1312
+ export function reverse(ast: AST): AST {
1313
+ AST.concrete(ast);
1314
+ switch (ast._tag) {
1315
+ case ASTTag.Declaration:
1316
+ return AST.createDeclaration(ast.typeParameters.map(reverse), ast.type, ast.decode, ast.annotations);
1317
+ case ASTTag.Tuple:
1318
+ return AST.createTuple(
1319
+ ast.elements.map((element) => AST.createElement(reverse(element.type), element.isOptional)),
1320
+ ast.rest.map((restElement) => restElement.map(reverse)),
1321
+ ast.isReadonly,
1322
+ ast.annotations,
1323
+ );
1324
+ case ASTTag.TypeLiteral:
1325
+ return AST.createTypeLiteral(
1326
+ ast.propertySignatures.map((ps) =>
1327
+ AST.createPropertySignature(ps.name, reverse(ps.type), ps.isOptional, ps.isReadonly, ps.annotations),
1328
+ ),
1329
+ ast.indexSignatures.map((is) => AST.createIndexSignature(is.parameter, reverse(is.type), is.isReadonly)),
1330
+ ast.annotations,
1331
+ );
1332
+ case ASTTag.Union:
1333
+ return AST.createUnion(ast.types.map(reverse), ast.annotations);
1334
+ case ASTTag.Lazy:
1335
+ return AST.createLazy(() => reverse(ast.getAST()), ast.annotations);
1336
+ case ASTTag.Refinement:
1337
+ return AST.createRefinement(ast.from, ast.decode, !ast.isReversed, ast.annotations);
1338
+ case ASTTag.Transform:
1339
+ return AST.createTransform(reverse(ast.from), ast.to, ast.decode, ast.encode, !ast.isReversed, ast.annotations);
1340
+ }
1341
+ return ast;
1342
+ }
1343
+
1344
+ /**
1345
+ * @tsplus static fncts.schema.AST getCompiler
1346
+ */
1347
+ export function getCompiler<A>(match: AST.Match<A>): AST.Compiler<A> {
1348
+ const compile: AST.Compiler<A> = memoize((ast: AST) => {
1349
+ AST.concrete(ast);
1350
+ return match[ast._tag](ast as any, compile);
1351
+ });
1352
+ return compile;
1353
+ }