@atscript/typescript 0.1.2 → 0.1.3
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.
- package/dist/cli.cjs +90 -51
- package/dist/index.cjs +90 -51
- package/dist/index.d.ts +8 -2
- package/dist/index.mjs +90 -51
- package/dist/utils.cjs +306 -41
- package/dist/utils.d.ts +273 -11
- package/dist/utils.mjs +301 -41
- package/package.json +2 -2
package/dist/utils.mjs
CHANGED
|
@@ -1,4 +1,18 @@
|
|
|
1
1
|
|
|
2
|
+
//#region packages/typescript/src/traverse.ts
|
|
3
|
+
function forAnnotatedType(def, handlers) {
|
|
4
|
+
switch (def.type.kind) {
|
|
5
|
+
case "": return handlers.final(def);
|
|
6
|
+
case "object": return handlers.object(def);
|
|
7
|
+
case "array": return handlers.array(def);
|
|
8
|
+
case "union": return handlers.union(def);
|
|
9
|
+
case "intersection": return handlers.intersection(def);
|
|
10
|
+
case "tuple": return handlers.tuple(def);
|
|
11
|
+
default: throw new Error(`Unknown type kind "${def.type.kind}"`);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
//#endregion
|
|
2
16
|
//#region packages/typescript/src/validator.ts
|
|
3
17
|
function _define_property(obj, key, value) {
|
|
4
18
|
if (key in obj) Object.defineProperty(obj, key, {
|
|
@@ -43,7 +57,17 @@ var Validator = class {
|
|
|
43
57
|
throw() {
|
|
44
58
|
throw new ValidatorError(this.errors);
|
|
45
59
|
}
|
|
46
|
-
|
|
60
|
+
/**
|
|
61
|
+
* Validates a value against the type definition.
|
|
62
|
+
*
|
|
63
|
+
* Acts as a TypeScript type guard — when it returns `true`, the value
|
|
64
|
+
* is narrowed to `DataType`.
|
|
65
|
+
*
|
|
66
|
+
* @param value - The value to validate.
|
|
67
|
+
* @param safe - If `true`, returns `false` on failure instead of throwing.
|
|
68
|
+
* @returns `true` if the value matches the type definition.
|
|
69
|
+
* @throws {ValidatorError} When validation fails and `safe` is not `true`.
|
|
70
|
+
*/ validate(value, safe) {
|
|
47
71
|
this.push("");
|
|
48
72
|
this.errors = [];
|
|
49
73
|
this.stackErrors = [];
|
|
@@ -70,15 +94,14 @@ var Validator = class {
|
|
|
70
94
|
return this.stackPath.slice(1).join(".");
|
|
71
95
|
}
|
|
72
96
|
validateAnnotatedType(def, value) {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}
|
|
97
|
+
return forAnnotatedType(def, {
|
|
98
|
+
final: (d) => this.validatePrimitive(d, value),
|
|
99
|
+
object: (d) => this.validateObject(d, value),
|
|
100
|
+
array: (d) => this.validateArray(d, value),
|
|
101
|
+
union: (d) => this.validateUnion(d, value),
|
|
102
|
+
intersection: (d) => this.validateIntersection(d, value),
|
|
103
|
+
tuple: (d) => this.validateTuple(d, value)
|
|
104
|
+
});
|
|
82
105
|
}
|
|
83
106
|
validateUnion(def, value) {
|
|
84
107
|
let i = 0;
|
|
@@ -310,7 +333,7 @@ else {
|
|
|
310
333
|
constructor(def, opts) {
|
|
311
334
|
_define_property(this, "def", void 0);
|
|
312
335
|
_define_property(this, "opts", void 0);
|
|
313
|
-
_define_property(this, "errors", void 0);
|
|
336
|
+
/** Validation errors collected during the last {@link validate} call. */ _define_property(this, "errors", void 0);
|
|
314
337
|
_define_property(this, "stackErrors", void 0);
|
|
315
338
|
_define_property(this, "stackPath", void 0);
|
|
316
339
|
this.def = def;
|
|
@@ -469,14 +492,12 @@ function isAnnotatedTypeOfPrimitive(t) {
|
|
|
469
492
|
//#region packages/typescript/src/json-schema.ts
|
|
470
493
|
function buildJsonSchema(type) {
|
|
471
494
|
const build = (def) => {
|
|
472
|
-
const t = def.type;
|
|
473
495
|
const meta = def.metadata;
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
const obj = t;
|
|
496
|
+
return forAnnotatedType(def, {
|
|
497
|
+
object(d) {
|
|
477
498
|
const properties = {};
|
|
478
499
|
const required = [];
|
|
479
|
-
for (const [key, val] of
|
|
500
|
+
for (const [key, val] of d.type.props.entries()) {
|
|
480
501
|
properties[key] = build(val);
|
|
481
502
|
if (!val.optional) required.push(key);
|
|
482
503
|
}
|
|
@@ -486,41 +507,36 @@ function buildJsonSchema(type) {
|
|
|
486
507
|
};
|
|
487
508
|
if (required.length) schema.required = required;
|
|
488
509
|
return schema;
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
const arr = t;
|
|
510
|
+
},
|
|
511
|
+
array(d) {
|
|
492
512
|
const schema = {
|
|
493
513
|
type: "array",
|
|
494
|
-
items: build(
|
|
514
|
+
items: build(d.type.of)
|
|
495
515
|
};
|
|
496
516
|
const minLength = meta.get("expect.minLength");
|
|
497
517
|
if (typeof minLength === "number") schema.minItems = minLength;
|
|
498
518
|
const maxLength = meta.get("expect.maxLength");
|
|
499
519
|
if (typeof maxLength === "number") schema.maxItems = maxLength;
|
|
500
520
|
return schema;
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
}
|
|
510
|
-
case "tuple": {
|
|
511
|
-
const grp = t;
|
|
521
|
+
},
|
|
522
|
+
union(d) {
|
|
523
|
+
return { anyOf: d.type.items.map(build) };
|
|
524
|
+
},
|
|
525
|
+
intersection(d) {
|
|
526
|
+
return { allOf: d.type.items.map(build) };
|
|
527
|
+
},
|
|
528
|
+
tuple(d) {
|
|
512
529
|
return {
|
|
513
530
|
type: "array",
|
|
514
|
-
items:
|
|
531
|
+
items: d.type.items.map(build),
|
|
515
532
|
additionalItems: false
|
|
516
533
|
};
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
const fin = t;
|
|
534
|
+
},
|
|
535
|
+
final(d) {
|
|
520
536
|
const schema = {};
|
|
521
|
-
if (
|
|
522
|
-
if (
|
|
523
|
-
schema.type =
|
|
537
|
+
if (d.type.value !== undefined) schema.const = d.type.value;
|
|
538
|
+
if (d.type.designType && d.type.designType !== "any") {
|
|
539
|
+
schema.type = d.type.designType === "undefined" ? "null" : d.type.designType;
|
|
524
540
|
if (schema.type === "number" && meta.get("expect.int")) schema.type = "integer";
|
|
525
541
|
}
|
|
526
542
|
if (schema.type === "string") {
|
|
@@ -540,11 +556,255 @@ else schema.allOf = (schema.allOf || []).concat(patterns.map((p) => ({ pattern:
|
|
|
540
556
|
}
|
|
541
557
|
return schema;
|
|
542
558
|
}
|
|
543
|
-
|
|
544
|
-
}
|
|
559
|
+
});
|
|
545
560
|
};
|
|
546
561
|
return build(type);
|
|
547
562
|
}
|
|
563
|
+
function fromJsonSchema(schema) {
|
|
564
|
+
const convert = (s) => {
|
|
565
|
+
if (!s || Object.keys(s).length === 0) return defineAnnotatedType().designType("any").$type;
|
|
566
|
+
if (s.$ref) throw new Error("$ref is not supported by fromJsonSchema. Dereference the schema first.");
|
|
567
|
+
if ("const" in s) {
|
|
568
|
+
const val = s.const;
|
|
569
|
+
const dt = val === null ? "null" : typeof val;
|
|
570
|
+
return defineAnnotatedType().designType(dt).value(val).$type;
|
|
571
|
+
}
|
|
572
|
+
if (s.enum) {
|
|
573
|
+
const handle = defineAnnotatedType("union");
|
|
574
|
+
for (const val of s.enum) {
|
|
575
|
+
const dt = val === null ? "null" : typeof val;
|
|
576
|
+
handle.item(defineAnnotatedType().designType(dt).value(val).$type);
|
|
577
|
+
}
|
|
578
|
+
return handle.$type;
|
|
579
|
+
}
|
|
580
|
+
if (s.anyOf) {
|
|
581
|
+
const handle = defineAnnotatedType("union");
|
|
582
|
+
for (const item of s.anyOf) handle.item(convert(item));
|
|
583
|
+
return handle.$type;
|
|
584
|
+
}
|
|
585
|
+
if (s.oneOf) {
|
|
586
|
+
const handle = defineAnnotatedType("union");
|
|
587
|
+
for (const item of s.oneOf) handle.item(convert(item));
|
|
588
|
+
return handle.$type;
|
|
589
|
+
}
|
|
590
|
+
if (s.allOf && !s.type) {
|
|
591
|
+
const handle = defineAnnotatedType("intersection");
|
|
592
|
+
for (const item of s.allOf) handle.item(convert(item));
|
|
593
|
+
return handle.$type;
|
|
594
|
+
}
|
|
595
|
+
if (Array.isArray(s.type)) {
|
|
596
|
+
const handle = defineAnnotatedType("union");
|
|
597
|
+
for (const t of s.type) handle.item(convert({
|
|
598
|
+
...s,
|
|
599
|
+
type: t
|
|
600
|
+
}));
|
|
601
|
+
return handle.$type;
|
|
602
|
+
}
|
|
603
|
+
if (s.type === "object") {
|
|
604
|
+
const handle = defineAnnotatedType("object");
|
|
605
|
+
const required = new Set(s.required || []);
|
|
606
|
+
if (s.properties) for (const [key, propSchema] of Object.entries(s.properties)) {
|
|
607
|
+
const propType = convert(propSchema);
|
|
608
|
+
if (!required.has(key)) propType.optional = true;
|
|
609
|
+
handle.prop(key, propType);
|
|
610
|
+
}
|
|
611
|
+
return handle.$type;
|
|
612
|
+
}
|
|
613
|
+
if (s.type === "array") {
|
|
614
|
+
if (Array.isArray(s.items)) {
|
|
615
|
+
const handle$1 = defineAnnotatedType("tuple");
|
|
616
|
+
for (const item of s.items) handle$1.item(convert(item));
|
|
617
|
+
return handle$1.$type;
|
|
618
|
+
}
|
|
619
|
+
const itemType = s.items ? convert(s.items) : defineAnnotatedType().designType("any").$type;
|
|
620
|
+
const handle = defineAnnotatedType("array").of(itemType);
|
|
621
|
+
if (typeof s.minItems === "number") handle.annotate("expect.minLength", s.minItems);
|
|
622
|
+
if (typeof s.maxItems === "number") handle.annotate("expect.maxLength", s.maxItems);
|
|
623
|
+
return handle.$type;
|
|
624
|
+
}
|
|
625
|
+
if (s.type === "string") {
|
|
626
|
+
const handle = defineAnnotatedType().designType("string").tags("string");
|
|
627
|
+
if (typeof s.minLength === "number") handle.annotate("expect.minLength", s.minLength);
|
|
628
|
+
if (typeof s.maxLength === "number") handle.annotate("expect.maxLength", s.maxLength);
|
|
629
|
+
if (s.pattern) handle.annotate("expect.pattern", { pattern: s.pattern }, true);
|
|
630
|
+
if (s.allOf) {
|
|
631
|
+
for (const item of s.allOf) if (item.pattern) handle.annotate("expect.pattern", { pattern: item.pattern }, true);
|
|
632
|
+
}
|
|
633
|
+
return handle.$type;
|
|
634
|
+
}
|
|
635
|
+
if (s.type === "integer") {
|
|
636
|
+
const handle = defineAnnotatedType().designType("number").tags("number");
|
|
637
|
+
handle.annotate("expect.int", true);
|
|
638
|
+
if (typeof s.minimum === "number") handle.annotate("expect.min", s.minimum);
|
|
639
|
+
if (typeof s.maximum === "number") handle.annotate("expect.max", s.maximum);
|
|
640
|
+
return handle.$type;
|
|
641
|
+
}
|
|
642
|
+
if (s.type === "number") {
|
|
643
|
+
const handle = defineAnnotatedType().designType("number").tags("number");
|
|
644
|
+
if (typeof s.minimum === "number") handle.annotate("expect.min", s.minimum);
|
|
645
|
+
if (typeof s.maximum === "number") handle.annotate("expect.max", s.maximum);
|
|
646
|
+
return handle.$type;
|
|
647
|
+
}
|
|
648
|
+
if (s.type === "boolean") return defineAnnotatedType().designType("boolean").tags("boolean").$type;
|
|
649
|
+
if (s.type === "null") return defineAnnotatedType().designType("null").tags("null").$type;
|
|
650
|
+
return defineAnnotatedType().designType("any").$type;
|
|
651
|
+
};
|
|
652
|
+
return convert(schema);
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
//#endregion
|
|
656
|
+
//#region packages/typescript/src/serialize.ts
|
|
657
|
+
const SERIALIZE_VERSION = 1;
|
|
658
|
+
function serializeAnnotatedType(type, options) {
|
|
659
|
+
const result = serializeNode(type, [], options);
|
|
660
|
+
result.$v = SERIALIZE_VERSION;
|
|
661
|
+
return result;
|
|
662
|
+
}
|
|
663
|
+
function serializeNode(def, path, options) {
|
|
664
|
+
const result = {
|
|
665
|
+
type: serializeTypeDef(def, path, options),
|
|
666
|
+
metadata: serializeMetadata(def.metadata, path, def.type.kind, options)
|
|
667
|
+
};
|
|
668
|
+
if (def.optional) result.optional = true;
|
|
669
|
+
return result;
|
|
670
|
+
}
|
|
671
|
+
function serializeTypeDef(def, path, options) {
|
|
672
|
+
return forAnnotatedType(def, {
|
|
673
|
+
final(d) {
|
|
674
|
+
const result = {
|
|
675
|
+
kind: "",
|
|
676
|
+
designType: d.type.designType,
|
|
677
|
+
tags: Array.from(d.type.tags)
|
|
678
|
+
};
|
|
679
|
+
if (d.type.value !== undefined) result.value = d.type.value;
|
|
680
|
+
return result;
|
|
681
|
+
},
|
|
682
|
+
object(d) {
|
|
683
|
+
const props = {};
|
|
684
|
+
for (const [key, val] of d.type.props.entries()) props[key] = serializeNode(val, [...path, key], options);
|
|
685
|
+
const propsPatterns = d.type.propsPatterns.map((pp) => ({
|
|
686
|
+
pattern: {
|
|
687
|
+
source: pp.pattern.source,
|
|
688
|
+
flags: pp.pattern.flags
|
|
689
|
+
},
|
|
690
|
+
def: serializeNode(pp.def, path, options)
|
|
691
|
+
}));
|
|
692
|
+
return {
|
|
693
|
+
kind: "object",
|
|
694
|
+
props,
|
|
695
|
+
propsPatterns,
|
|
696
|
+
tags: Array.from(d.type.tags)
|
|
697
|
+
};
|
|
698
|
+
},
|
|
699
|
+
array(d) {
|
|
700
|
+
return {
|
|
701
|
+
kind: "array",
|
|
702
|
+
of: serializeNode(d.type.of, path, options),
|
|
703
|
+
tags: Array.from(d.type.tags)
|
|
704
|
+
};
|
|
705
|
+
},
|
|
706
|
+
union(d) {
|
|
707
|
+
return {
|
|
708
|
+
kind: "union",
|
|
709
|
+
items: d.type.items.map((item) => serializeNode(item, path, options)),
|
|
710
|
+
tags: Array.from(d.type.tags)
|
|
711
|
+
};
|
|
712
|
+
},
|
|
713
|
+
intersection(d) {
|
|
714
|
+
return {
|
|
715
|
+
kind: "intersection",
|
|
716
|
+
items: d.type.items.map((item) => serializeNode(item, path, options)),
|
|
717
|
+
tags: Array.from(d.type.tags)
|
|
718
|
+
};
|
|
719
|
+
},
|
|
720
|
+
tuple(d) {
|
|
721
|
+
return {
|
|
722
|
+
kind: "tuple",
|
|
723
|
+
items: d.type.items.map((item) => serializeNode(item, path, options)),
|
|
724
|
+
tags: Array.from(d.type.tags)
|
|
725
|
+
};
|
|
726
|
+
}
|
|
727
|
+
});
|
|
728
|
+
}
|
|
729
|
+
function serializeMetadata(metadata, path, kind, options) {
|
|
730
|
+
const result = {};
|
|
731
|
+
const ignoreSet = options?.ignoreAnnotations ? new Set(options.ignoreAnnotations) : undefined;
|
|
732
|
+
for (const [key, value] of metadata.entries()) {
|
|
733
|
+
if (ignoreSet?.has(key)) continue;
|
|
734
|
+
if (options?.processAnnotation) {
|
|
735
|
+
const processed = options.processAnnotation({
|
|
736
|
+
key,
|
|
737
|
+
value,
|
|
738
|
+
path,
|
|
739
|
+
kind
|
|
740
|
+
});
|
|
741
|
+
if (processed === undefined || processed === null) continue;
|
|
742
|
+
result[processed.key] = processed.value;
|
|
743
|
+
continue;
|
|
744
|
+
}
|
|
745
|
+
result[key] = value;
|
|
746
|
+
}
|
|
747
|
+
return result;
|
|
748
|
+
}
|
|
749
|
+
function deserializeAnnotatedType(data) {
|
|
750
|
+
if (data.$v !== SERIALIZE_VERSION) throw new Error(`Unsupported serialized type version: ${data.$v} (expected ${SERIALIZE_VERSION})`);
|
|
751
|
+
return deserializeNode(data);
|
|
752
|
+
}
|
|
753
|
+
function deserializeNode(data) {
|
|
754
|
+
const metadata = new Map(Object.entries(data.metadata));
|
|
755
|
+
const type = deserializeTypeDef(data.type);
|
|
756
|
+
const result = {
|
|
757
|
+
__is_atscript_annotated_type: true,
|
|
758
|
+
type,
|
|
759
|
+
metadata,
|
|
760
|
+
validator(opts) {
|
|
761
|
+
return new Validator(this, opts);
|
|
762
|
+
}
|
|
763
|
+
};
|
|
764
|
+
if (data.optional) result.optional = true;
|
|
765
|
+
return result;
|
|
766
|
+
}
|
|
767
|
+
function deserializeTypeDef(t) {
|
|
768
|
+
const tags = new Set(t.tags);
|
|
769
|
+
switch (t.kind) {
|
|
770
|
+
case "": {
|
|
771
|
+
const result = {
|
|
772
|
+
kind: "",
|
|
773
|
+
designType: t.designType,
|
|
774
|
+
tags
|
|
775
|
+
};
|
|
776
|
+
if (t.value !== undefined) result.value = t.value;
|
|
777
|
+
return result;
|
|
778
|
+
}
|
|
779
|
+
case "object": {
|
|
780
|
+
const props = new Map();
|
|
781
|
+
for (const [key, val] of Object.entries(t.props)) props.set(key, deserializeNode(val));
|
|
782
|
+
const propsPatterns = t.propsPatterns.map((pp) => ({
|
|
783
|
+
pattern: new RegExp(pp.pattern.source, pp.pattern.flags),
|
|
784
|
+
def: deserializeNode(pp.def)
|
|
785
|
+
}));
|
|
786
|
+
return {
|
|
787
|
+
kind: "object",
|
|
788
|
+
props,
|
|
789
|
+
propsPatterns,
|
|
790
|
+
tags
|
|
791
|
+
};
|
|
792
|
+
}
|
|
793
|
+
case "array": return {
|
|
794
|
+
kind: "array",
|
|
795
|
+
of: deserializeNode(t.of),
|
|
796
|
+
tags
|
|
797
|
+
};
|
|
798
|
+
case "union":
|
|
799
|
+
case "intersection":
|
|
800
|
+
case "tuple": return {
|
|
801
|
+
kind: t.kind,
|
|
802
|
+
items: t.items.map((item) => deserializeNode(item)),
|
|
803
|
+
tags
|
|
804
|
+
};
|
|
805
|
+
default: throw new Error(`Unknown serialized type kind "${t.kind}"`);
|
|
806
|
+
}
|
|
807
|
+
}
|
|
548
808
|
|
|
549
809
|
//#endregion
|
|
550
|
-
export { Validator, ValidatorError, annotate, buildJsonSchema, defineAnnotatedType, isAnnotatedType, isAnnotatedTypeOfPrimitive };
|
|
810
|
+
export { SERIALIZE_VERSION, Validator, ValidatorError, annotate, buildJsonSchema, defineAnnotatedType, deserializeAnnotatedType, forAnnotatedType, fromJsonSchema, isAnnotatedType, isAnnotatedTypeOfPrimitive, serializeAnnotatedType };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atscript/typescript",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Atscript: typescript-gen support.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.mjs",
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
"homepage": "https://github.com/moostjs/atscript/tree/main/packages/typescript#readme",
|
|
71
71
|
"license": "ISC",
|
|
72
72
|
"peerDependencies": {
|
|
73
|
-
"@atscript/core": "^0.1.
|
|
73
|
+
"@atscript/core": "^0.1.3"
|
|
74
74
|
},
|
|
75
75
|
"dependencies": {
|
|
76
76
|
"@moostjs/event-cli": "^0.5.32",
|