@atscript/typescript 0.0.17 → 0.0.18
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 +47 -5
- package/dist/index.cjs +125 -23
- package/dist/index.d.ts +54 -21
- package/dist/index.mjs +124 -23
- package/package.json +7 -5
package/dist/cli.cjs
CHANGED
|
@@ -271,17 +271,41 @@ var TypeRenderer = class extends BaseRenderer {
|
|
|
271
271
|
}
|
|
272
272
|
renderStructure(struct, asClass) {
|
|
273
273
|
this.blockln("{}");
|
|
274
|
+
const patterns = [];
|
|
275
|
+
let hasProp = false;
|
|
274
276
|
for (const prop of Array.from(struct.props.values())) {
|
|
277
|
+
if (prop.token("identifier")?.pattern) {
|
|
278
|
+
patterns.push(prop);
|
|
279
|
+
continue;
|
|
280
|
+
}
|
|
281
|
+
hasProp = true;
|
|
275
282
|
const optional = !!prop.token("optional");
|
|
276
283
|
this.write(wrapProp(prop.id), optional ? "?" : "", ": ");
|
|
277
284
|
this.renderTypeDef(prop.getDefinition());
|
|
278
285
|
this.writeln();
|
|
279
286
|
}
|
|
287
|
+
if (patterns.length) {
|
|
288
|
+
this.write(`[key: string]: `);
|
|
289
|
+
if (hasProp) this.writeln("any");
|
|
290
|
+
else if (patterns.length === 1) {
|
|
291
|
+
this.renderTypeDef(patterns[0].getDefinition());
|
|
292
|
+
this.writeln();
|
|
293
|
+
} else {
|
|
294
|
+
this.indent();
|
|
295
|
+
for (const prop of patterns) {
|
|
296
|
+
this.writeln();
|
|
297
|
+
this.write("| ");
|
|
298
|
+
this.renderTypeDef(prop.getDefinition());
|
|
299
|
+
}
|
|
300
|
+
this.unindent();
|
|
301
|
+
this.writeln();
|
|
302
|
+
}
|
|
303
|
+
}
|
|
280
304
|
if (asClass) {
|
|
281
305
|
this.writeln("static __is_atscript_annotated_type: true");
|
|
282
306
|
this.writeln(`static type: TAtscriptTypeObject<keyof ${asClass}>`);
|
|
283
307
|
this.writeln(`static metadata: TMetadataMap<AtscriptMetadata>`);
|
|
284
|
-
this.writeln(`static validator: <TT extends TAtscriptAnnotatedTypeConstructor = ${asClass}>(opts?: TValidatorOptions) => Validator<TT>`);
|
|
308
|
+
this.writeln(`static validator: <TT extends TAtscriptAnnotatedTypeConstructor = ${asClass}>(opts?: Partial<TValidatorOptions>) => Validator<TT>`);
|
|
285
309
|
}
|
|
286
310
|
this.pop();
|
|
287
311
|
}
|
|
@@ -323,7 +347,7 @@ else if ((0, __atscript_core.isPrimitive)(realDef)) typeDef = "TAtscriptTypeFina
|
|
|
323
347
|
this.writeln(`const __is_atscript_annotated_type: true`);
|
|
324
348
|
this.writeln(`const type: ${typeDef}`);
|
|
325
349
|
this.writeln(`const metadata: TMetadataMap<AtscriptMetadata>`);
|
|
326
|
-
this.writeln(`
|
|
350
|
+
this.writeln(`const validator: <TT extends TAtscriptAnnotatedTypeConstructor = ${node.id}>(opts?: Partial<TValidatorOptions>) => Validator<TT>`);
|
|
327
351
|
this.popln();
|
|
328
352
|
}
|
|
329
353
|
renderJsDoc(node) {
|
|
@@ -508,6 +532,17 @@ var JsRenderer = class extends BaseRenderer {
|
|
|
508
532
|
this.unindent();
|
|
509
533
|
this.write(`)`);
|
|
510
534
|
}
|
|
535
|
+
for (const [key, propDef] of Object.entries(def.propsPatterns)) {
|
|
536
|
+
const optional = typeof propDef === "object" && propDef.optional;
|
|
537
|
+
this.writeln(`.propPattern(`);
|
|
538
|
+
this.indent();
|
|
539
|
+
this.writeln(`${key},`);
|
|
540
|
+
this.renderPrimitiveDef(propDef);
|
|
541
|
+
if (optional) this.writeln(".optional()");
|
|
542
|
+
this.writeln(".$type");
|
|
543
|
+
this.unindent();
|
|
544
|
+
this.write(`)`);
|
|
545
|
+
}
|
|
511
546
|
this.unindent();
|
|
512
547
|
return;
|
|
513
548
|
default: return this.writeln(`$(${d()}).designType("any")`);
|
|
@@ -516,10 +551,17 @@ var JsRenderer = class extends BaseRenderer {
|
|
|
516
551
|
defineObject(node) {
|
|
517
552
|
const props = Array.from(node.props.values());
|
|
518
553
|
for (const prop of props) {
|
|
554
|
+
const pattern = prop.token("identifier")?.pattern;
|
|
519
555
|
const optional = !!prop.token("optional");
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
556
|
+
if (pattern) {
|
|
557
|
+
this.writeln(`.propPattern(`);
|
|
558
|
+
this.indent();
|
|
559
|
+
this.writeln(`/${pattern.source}/${pattern.flags},`);
|
|
560
|
+
} else {
|
|
561
|
+
this.writeln(`.prop(`);
|
|
562
|
+
this.indent();
|
|
563
|
+
this.writeln(`"${escapeQuotes(prop.id)}",`);
|
|
564
|
+
}
|
|
523
565
|
this.annotateType(prop.getDefinition());
|
|
524
566
|
this.indent().defineMetadata(prop).unindent();
|
|
525
567
|
if (optional) this.writeln(" .optional()");
|
package/dist/index.cjs
CHANGED
|
@@ -269,17 +269,41 @@ var TypeRenderer = class extends BaseRenderer {
|
|
|
269
269
|
}
|
|
270
270
|
renderStructure(struct, asClass) {
|
|
271
271
|
this.blockln("{}");
|
|
272
|
+
const patterns = [];
|
|
273
|
+
let hasProp = false;
|
|
272
274
|
for (const prop of Array.from(struct.props.values())) {
|
|
275
|
+
if (prop.token("identifier")?.pattern) {
|
|
276
|
+
patterns.push(prop);
|
|
277
|
+
continue;
|
|
278
|
+
}
|
|
279
|
+
hasProp = true;
|
|
273
280
|
const optional = !!prop.token("optional");
|
|
274
281
|
this.write(wrapProp(prop.id), optional ? "?" : "", ": ");
|
|
275
282
|
this.renderTypeDef(prop.getDefinition());
|
|
276
283
|
this.writeln();
|
|
277
284
|
}
|
|
285
|
+
if (patterns.length) {
|
|
286
|
+
this.write(`[key: string]: `);
|
|
287
|
+
if (hasProp) this.writeln("any");
|
|
288
|
+
else if (patterns.length === 1) {
|
|
289
|
+
this.renderTypeDef(patterns[0].getDefinition());
|
|
290
|
+
this.writeln();
|
|
291
|
+
} else {
|
|
292
|
+
this.indent();
|
|
293
|
+
for (const prop of patterns) {
|
|
294
|
+
this.writeln();
|
|
295
|
+
this.write("| ");
|
|
296
|
+
this.renderTypeDef(prop.getDefinition());
|
|
297
|
+
}
|
|
298
|
+
this.unindent();
|
|
299
|
+
this.writeln();
|
|
300
|
+
}
|
|
301
|
+
}
|
|
278
302
|
if (asClass) {
|
|
279
303
|
this.writeln("static __is_atscript_annotated_type: true");
|
|
280
304
|
this.writeln(`static type: TAtscriptTypeObject<keyof ${asClass}>`);
|
|
281
305
|
this.writeln(`static metadata: TMetadataMap<AtscriptMetadata>`);
|
|
282
|
-
this.writeln(`static validator: <TT extends TAtscriptAnnotatedTypeConstructor = ${asClass}>(opts?: TValidatorOptions) => Validator<TT>`);
|
|
306
|
+
this.writeln(`static validator: <TT extends TAtscriptAnnotatedTypeConstructor = ${asClass}>(opts?: Partial<TValidatorOptions>) => Validator<TT>`);
|
|
283
307
|
}
|
|
284
308
|
this.pop();
|
|
285
309
|
}
|
|
@@ -321,7 +345,7 @@ else if ((0, __atscript_core.isPrimitive)(realDef)) typeDef = "TAtscriptTypeFina
|
|
|
321
345
|
this.writeln(`const __is_atscript_annotated_type: true`);
|
|
322
346
|
this.writeln(`const type: ${typeDef}`);
|
|
323
347
|
this.writeln(`const metadata: TMetadataMap<AtscriptMetadata>`);
|
|
324
|
-
this.writeln(`
|
|
348
|
+
this.writeln(`const validator: <TT extends TAtscriptAnnotatedTypeConstructor = ${node.id}>(opts?: Partial<TValidatorOptions>) => Validator<TT>`);
|
|
325
349
|
this.popln();
|
|
326
350
|
}
|
|
327
351
|
renderJsDoc(node) {
|
|
@@ -506,6 +530,17 @@ var JsRenderer = class extends BaseRenderer {
|
|
|
506
530
|
this.unindent();
|
|
507
531
|
this.write(`)`);
|
|
508
532
|
}
|
|
533
|
+
for (const [key, propDef] of Object.entries(def.propsPatterns)) {
|
|
534
|
+
const optional = typeof propDef === "object" && propDef.optional;
|
|
535
|
+
this.writeln(`.propPattern(`);
|
|
536
|
+
this.indent();
|
|
537
|
+
this.writeln(`${key},`);
|
|
538
|
+
this.renderPrimitiveDef(propDef);
|
|
539
|
+
if (optional) this.writeln(".optional()");
|
|
540
|
+
this.writeln(".$type");
|
|
541
|
+
this.unindent();
|
|
542
|
+
this.write(`)`);
|
|
543
|
+
}
|
|
509
544
|
this.unindent();
|
|
510
545
|
return;
|
|
511
546
|
default: return this.writeln(`$(${d()}).designType("any")`);
|
|
@@ -514,10 +549,17 @@ var JsRenderer = class extends BaseRenderer {
|
|
|
514
549
|
defineObject(node) {
|
|
515
550
|
const props = Array.from(node.props.values());
|
|
516
551
|
for (const prop of props) {
|
|
552
|
+
const pattern = prop.token("identifier")?.pattern;
|
|
517
553
|
const optional = !!prop.token("optional");
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
554
|
+
if (pattern) {
|
|
555
|
+
this.writeln(`.propPattern(`);
|
|
556
|
+
this.indent();
|
|
557
|
+
this.writeln(`/${pattern.source}/${pattern.flags},`);
|
|
558
|
+
} else {
|
|
559
|
+
this.writeln(`.prop(`);
|
|
560
|
+
this.indent();
|
|
561
|
+
this.writeln(`"${escapeQuotes(prop.id)}",`);
|
|
562
|
+
}
|
|
521
563
|
this.annotateType(prop.getDefinition());
|
|
522
564
|
this.indent().defineMetadata(prop).unindent();
|
|
523
565
|
if (optional) this.writeln(" .optional()");
|
|
@@ -653,7 +695,7 @@ var Validator = class {
|
|
|
653
695
|
error(message, path$2, details) {
|
|
654
696
|
const errors = this.stackErrors[this.stackErrors.length - 1] || this.errors;
|
|
655
697
|
const error = {
|
|
656
|
-
path: path$2 || this.
|
|
698
|
+
path: path$2 || this.path,
|
|
657
699
|
message
|
|
658
700
|
};
|
|
659
701
|
if (details?.length) error.details = details;
|
|
@@ -666,7 +708,7 @@ var Validator = class {
|
|
|
666
708
|
this.push("");
|
|
667
709
|
this.errors = [];
|
|
668
710
|
this.stackErrors = [];
|
|
669
|
-
const passed = this.
|
|
711
|
+
const passed = this.validateSafe(this.def, value);
|
|
670
712
|
this.pop(!passed);
|
|
671
713
|
if (!passed) {
|
|
672
714
|
if (safe) return false;
|
|
@@ -674,10 +716,21 @@ var Validator = class {
|
|
|
674
716
|
}
|
|
675
717
|
return true;
|
|
676
718
|
}
|
|
677
|
-
|
|
719
|
+
validateSafe(def, value) {
|
|
678
720
|
if (this.isLimitExceeded()) return false;
|
|
679
721
|
if (!isAnnotatedType(def)) throw new Error("Can not validate not-annotated type");
|
|
722
|
+
if (typeof this.opts.replace === "function") def = this.opts.replace(def, this.path);
|
|
680
723
|
if (def.optional && value === undefined) return true;
|
|
724
|
+
for (const plugin of this.opts.plugins) {
|
|
725
|
+
const result = plugin(this, def, value);
|
|
726
|
+
if (result === false || result === true) return result;
|
|
727
|
+
}
|
|
728
|
+
return this.validateAnnotatedType(def, value);
|
|
729
|
+
}
|
|
730
|
+
get path() {
|
|
731
|
+
return this.stackPath.slice(1).join(".");
|
|
732
|
+
}
|
|
733
|
+
validateAnnotatedType(def, value) {
|
|
681
734
|
switch (def.type.kind) {
|
|
682
735
|
case "object": return this.validateObject(def, value);
|
|
683
736
|
case "union": return this.validateUnion(def, value);
|
|
@@ -693,7 +746,7 @@ var Validator = class {
|
|
|
693
746
|
const popped = [];
|
|
694
747
|
for (const item of def.type.items) {
|
|
695
748
|
this.push(`[${item.type.kind || item.type.designType}(${i})]`);
|
|
696
|
-
if (this.
|
|
749
|
+
if (this.validateSafe(item, value)) {
|
|
697
750
|
this.pop(false);
|
|
698
751
|
return true;
|
|
699
752
|
}
|
|
@@ -707,7 +760,7 @@ var Validator = class {
|
|
|
707
760
|
return false;
|
|
708
761
|
}
|
|
709
762
|
validateIntersection(def, value) {
|
|
710
|
-
for (const item of def.type.items) if (!this.
|
|
763
|
+
for (const item of def.type.items) if (!this.validateSafe(item, value)) return false;
|
|
711
764
|
return true;
|
|
712
765
|
}
|
|
713
766
|
validateTuple(def, value) {
|
|
@@ -718,7 +771,7 @@ var Validator = class {
|
|
|
718
771
|
let i = 0;
|
|
719
772
|
for (const item of def.type.items) {
|
|
720
773
|
this.push(`[${i}]`);
|
|
721
|
-
if (!this.
|
|
774
|
+
if (!this.validateSafe(item, value[i])) {
|
|
722
775
|
this.pop(true);
|
|
723
776
|
return false;
|
|
724
777
|
}
|
|
@@ -746,7 +799,7 @@ var Validator = class {
|
|
|
746
799
|
let passed = true;
|
|
747
800
|
for (const item of value) {
|
|
748
801
|
this.push(`[${i}]`);
|
|
749
|
-
if (!this.
|
|
802
|
+
if (!this.validateSafe(def.type.of, item)) {
|
|
750
803
|
passed = false;
|
|
751
804
|
this.pop(true);
|
|
752
805
|
if (this.isLimitExceeded()) return false;
|
|
@@ -765,7 +818,7 @@ var Validator = class {
|
|
|
765
818
|
const typeKeys = new Set();
|
|
766
819
|
const skipList = new Set();
|
|
767
820
|
if (this.opts.skipList) {
|
|
768
|
-
const path$2 = this.stackPath.length > 1 ? this.
|
|
821
|
+
const path$2 = this.stackPath.length > 1 ? this.path + "." : "";
|
|
769
822
|
this.opts.skipList.forEach((item) => {
|
|
770
823
|
if (item.startsWith(path$2)) {
|
|
771
824
|
const key = item.slice(path$2.length);
|
|
@@ -775,7 +828,7 @@ var Validator = class {
|
|
|
775
828
|
});
|
|
776
829
|
}
|
|
777
830
|
let partialFunctionMatched = false;
|
|
778
|
-
if (typeof this.opts.partial === "function") partialFunctionMatched = this.opts.partial(def, this.
|
|
831
|
+
if (typeof this.opts.partial === "function") partialFunctionMatched = this.opts.partial(def, this.path);
|
|
779
832
|
for (const [key, item] of def.type.props.entries()) {
|
|
780
833
|
if (skipList.has(key)) continue;
|
|
781
834
|
typeKeys.add(key);
|
|
@@ -783,15 +836,35 @@ var Validator = class {
|
|
|
783
836
|
if (partialFunctionMatched || this.opts.partial === "deep" || this.opts.partial === true && this.stackPath.length <= 1) continue;
|
|
784
837
|
}
|
|
785
838
|
this.push(key);
|
|
786
|
-
if (this.
|
|
839
|
+
if (this.validateSafe(item, value[key])) this.pop(false);
|
|
787
840
|
else {
|
|
788
841
|
passed = false;
|
|
789
842
|
this.pop(true);
|
|
790
843
|
if (this.isLimitExceeded()) return false;
|
|
791
844
|
}
|
|
792
845
|
}
|
|
793
|
-
for (const key of valueKeys)
|
|
794
|
-
|
|
846
|
+
for (const key of valueKeys)
|
|
847
|
+
/** matched patterns for unknown keys */ if (!typeKeys.has(key)) {
|
|
848
|
+
const matched = [];
|
|
849
|
+
for (const { pattern, def: propDef } of def.type.propsPatterns) if (pattern.test(key)) matched.push({
|
|
850
|
+
pattern,
|
|
851
|
+
def: propDef
|
|
852
|
+
});
|
|
853
|
+
if (matched.length) {
|
|
854
|
+
let keyPassed = false;
|
|
855
|
+
for (const { def: def$1 } of matched) if (this.validateSafe(def$1, value[key])) {
|
|
856
|
+
this.pop(false);
|
|
857
|
+
keyPassed = true;
|
|
858
|
+
break;
|
|
859
|
+
}
|
|
860
|
+
if (!keyPassed) {
|
|
861
|
+
this.push(key);
|
|
862
|
+
this.validateSafe(matched[0].def, value[key]);
|
|
863
|
+
this.pop(true);
|
|
864
|
+
passed = false;
|
|
865
|
+
if (this.isLimitExceeded()) return false;
|
|
866
|
+
}
|
|
867
|
+
} else if (this.opts.unknwonProps !== "ignore") {
|
|
795
868
|
if (this.opts.unknwonProps === "error") {
|
|
796
869
|
this.push(key);
|
|
797
870
|
this.error(`Unexpected property`);
|
|
@@ -909,7 +982,8 @@ else {
|
|
|
909
982
|
partial: false,
|
|
910
983
|
unknwonProps: "error",
|
|
911
984
|
errorLimit: 10,
|
|
912
|
-
...opts
|
|
985
|
+
...opts,
|
|
986
|
+
plugins: opts?.plugins || []
|
|
913
987
|
};
|
|
914
988
|
}
|
|
915
989
|
};
|
|
@@ -933,7 +1007,10 @@ function defineAnnotatedType(_kind, base) {
|
|
|
933
1007
|
"intersection",
|
|
934
1008
|
"tuple"
|
|
935
1009
|
].includes(kind)) type.items = [];
|
|
936
|
-
if (kind === "object")
|
|
1010
|
+
if (kind === "object") {
|
|
1011
|
+
type.props = new Map();
|
|
1012
|
+
type.propsPatterns = [];
|
|
1013
|
+
}
|
|
937
1014
|
type.tags = new Set();
|
|
938
1015
|
const metadata = base?.metadata || new Map();
|
|
939
1016
|
if (base) Object.assign(base, {
|
|
@@ -981,8 +1058,19 @@ else base = {
|
|
|
981
1058
|
this.$def.props.set(name, value);
|
|
982
1059
|
return this;
|
|
983
1060
|
},
|
|
984
|
-
|
|
985
|
-
this.$
|
|
1061
|
+
propPattern(pattern, def) {
|
|
1062
|
+
this.$def.propsPatterns.push({
|
|
1063
|
+
pattern,
|
|
1064
|
+
def
|
|
1065
|
+
});
|
|
1066
|
+
return this;
|
|
1067
|
+
},
|
|
1068
|
+
optional(value = true) {
|
|
1069
|
+
this.$type.optional = value;
|
|
1070
|
+
return this;
|
|
1071
|
+
},
|
|
1072
|
+
copyMetadata(fromMetadata, ignore) {
|
|
1073
|
+
for (const [key, value] of fromMetadata.entries()) if (!ignore || !ignore.has(key)) this.$metadata.set(key, value);
|
|
986
1074
|
return this;
|
|
987
1075
|
},
|
|
988
1076
|
refTo(type$1, chain) {
|
|
@@ -992,7 +1080,7 @@ else base = {
|
|
|
992
1080
|
let keys = "";
|
|
993
1081
|
for (const c of chain || []) {
|
|
994
1082
|
keys += `["${c}"]`;
|
|
995
|
-
if (newBase.type.kind === "object") newBase = newBase.type.props.get(c);
|
|
1083
|
+
if (newBase.type.kind === "object" && newBase.type.props.has(c)) newBase = newBase.type.props.get(c);
|
|
996
1084
|
else throw new Error(`Can't find prop ${typeName}${keys}`);
|
|
997
1085
|
}
|
|
998
1086
|
if (!newBase && keys) throw new Error(`Can't find prop ${typeName}${keys}`);
|
|
@@ -1020,6 +1108,19 @@ else this.$metadata.set(key, value);
|
|
|
1020
1108
|
};
|
|
1021
1109
|
return handle;
|
|
1022
1110
|
}
|
|
1111
|
+
function isAnnotatedTypeOfPrimitive(t) {
|
|
1112
|
+
if (["array", "object"].includes(t.type.kind)) return false;
|
|
1113
|
+
if (!t.type.kind) return true;
|
|
1114
|
+
if ([
|
|
1115
|
+
"union",
|
|
1116
|
+
"tuple",
|
|
1117
|
+
"intersection"
|
|
1118
|
+
].includes(t.type.kind)) {
|
|
1119
|
+
for (const item of t.type.items) if (!isAnnotatedTypeOfPrimitive(item)) return false;
|
|
1120
|
+
return true;
|
|
1121
|
+
}
|
|
1122
|
+
return false;
|
|
1123
|
+
}
|
|
1023
1124
|
|
|
1024
1125
|
//#endregion
|
|
1025
1126
|
//#region packages/typescript/src/index.ts
|
|
@@ -1030,4 +1131,5 @@ exports.Validator = Validator
|
|
|
1030
1131
|
exports.ValidatorError = ValidatorError
|
|
1031
1132
|
exports.default = src_default
|
|
1032
1133
|
exports.defineAnnotatedType = defineAnnotatedType
|
|
1033
|
-
exports.isAnnotatedType = isAnnotatedType
|
|
1134
|
+
exports.isAnnotatedType = isAnnotatedType
|
|
1135
|
+
exports.isAnnotatedTypeOfPrimitive = isAnnotatedTypeOfPrimitive
|
package/dist/index.d.ts
CHANGED
|
@@ -7,16 +7,25 @@ interface TError {
|
|
|
7
7
|
message: string;
|
|
8
8
|
details?: TError[];
|
|
9
9
|
}
|
|
10
|
+
type TValidatorPlugin = (ctx: TValidatorPluginContext, def: TAtscriptAnnotatedType, value: any) => boolean | undefined;
|
|
10
11
|
interface TValidatorOptions {
|
|
11
12
|
partial: boolean | 'deep' | ((type: TAtscriptAnnotatedType<TAtscriptTypeObject>, path: string) => boolean);
|
|
13
|
+
replace?: (type: TAtscriptAnnotatedType, path: string) => TAtscriptAnnotatedType;
|
|
14
|
+
plugins: TValidatorPlugin[];
|
|
12
15
|
unknwonProps: 'strip' | 'ignore' | 'error';
|
|
13
16
|
errorLimit: number;
|
|
14
17
|
skipList?: Set<string>;
|
|
15
18
|
}
|
|
19
|
+
interface TValidatorPluginContext {
|
|
20
|
+
opts: Validator<any>['opts'];
|
|
21
|
+
validateAnnotatedType: Validator<any>['validateAnnotatedType'];
|
|
22
|
+
error: Validator<any>['error'];
|
|
23
|
+
path: Validator<any>['path'];
|
|
24
|
+
}
|
|
16
25
|
declare class Validator<T extends TAtscriptAnnotatedTypeConstructor> {
|
|
17
|
-
protected readonly def: T
|
|
26
|
+
protected readonly def: T | TAtscriptAnnotatedType<any>;
|
|
18
27
|
protected opts: TValidatorOptions;
|
|
19
|
-
constructor(def: T
|
|
28
|
+
constructor(def: T | TAtscriptAnnotatedType<any>, opts?: Partial<TValidatorOptions>);
|
|
20
29
|
errors: TError[];
|
|
21
30
|
protected stackErrors: TError[][];
|
|
22
31
|
protected stackPath: string[];
|
|
@@ -27,7 +36,9 @@ declare class Validator<T extends TAtscriptAnnotatedTypeConstructor> {
|
|
|
27
36
|
protected error(message: string, path?: string, details?: TError[]): void;
|
|
28
37
|
protected throw(): void;
|
|
29
38
|
validate<TT = T>(value: any, safe?: boolean): value is TT;
|
|
30
|
-
protected
|
|
39
|
+
protected validateSafe(def: TAtscriptAnnotatedType, value: any): boolean;
|
|
40
|
+
protected get path(): string;
|
|
41
|
+
protected validateAnnotatedType(def: TAtscriptAnnotatedType, value: any): boolean;
|
|
31
42
|
protected validateUnion(def: TAtscriptAnnotatedType<TAtscriptTypeComplex>, value: any): boolean;
|
|
32
43
|
protected validateIntersection(def: TAtscriptAnnotatedType<TAtscriptTypeComplex>, value: any): boolean;
|
|
33
44
|
protected validateTuple(def: TAtscriptAnnotatedType<TAtscriptTypeComplex>, value: any): boolean;
|
|
@@ -56,11 +67,21 @@ interface TAtscriptTypeArray {
|
|
|
56
67
|
interface TAtscriptTypeObject<K extends string = string> {
|
|
57
68
|
kind: 'object';
|
|
58
69
|
props: Map<K, TAtscriptAnnotatedType>;
|
|
70
|
+
propsPatterns: {
|
|
71
|
+
pattern: RegExp;
|
|
72
|
+
def: TAtscriptAnnotatedType;
|
|
73
|
+
}[];
|
|
59
74
|
tags: Set<AtscriptPrimitiveTags>;
|
|
60
75
|
}
|
|
61
76
|
interface TAtscriptTypeFinal {
|
|
62
77
|
kind: '';
|
|
78
|
+
/**
|
|
79
|
+
* design type
|
|
80
|
+
*/
|
|
63
81
|
designType: 'string' | 'number' | 'boolean' | 'undefined' | 'null' | 'object' | 'any' | 'never';
|
|
82
|
+
/**
|
|
83
|
+
* value for literals
|
|
84
|
+
*/
|
|
64
85
|
value?: string | number | boolean;
|
|
65
86
|
tags: Set<AtscriptPrimitiveTags>;
|
|
66
87
|
}
|
|
@@ -73,28 +94,40 @@ interface TAtscriptAnnotatedType<T = TAtscriptTypeDef> {
|
|
|
73
94
|
optional?: boolean;
|
|
74
95
|
}
|
|
75
96
|
type TAtscriptAnnotatedTypeConstructor = TAtscriptAnnotatedType & (new (...args: any[]) => any);
|
|
97
|
+
/**
|
|
98
|
+
* Type Guard to check if a type is atscript-annotated
|
|
99
|
+
*/
|
|
76
100
|
declare function isAnnotatedType(type: any): type is TAtscriptAnnotatedType;
|
|
77
101
|
type TKind = '' | 'array' | 'object' | 'union' | 'intersection' | 'tuple';
|
|
78
|
-
declare function defineAnnotatedType(_kind?: TKind, base?: any):
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
} & Omit<TAtscriptTypeComplex, "kind"> & Omit<TAtscriptTypeFinal, "kind"> & Omit<TAtscriptTypeArray, "kind"> & Omit<TAtscriptTypeObject<string>, "kind">;
|
|
83
|
-
$metadata: Map<string, unknown>;
|
|
84
|
-
_existingObject: TAtscriptAnnotatedType | undefined;
|
|
85
|
-
tags(...tags: string[]): any;
|
|
86
|
-
designType(value: TAtscriptTypeFinal["designType"]): any;
|
|
87
|
-
value(value: string | number | boolean): any;
|
|
88
|
-
of(value: TAtscriptAnnotatedType): any;
|
|
89
|
-
item(value: TAtscriptAnnotatedType): any;
|
|
90
|
-
prop(name: string, value: TAtscriptAnnotatedType): any;
|
|
91
|
-
optional(): any;
|
|
92
|
-
refTo(type: any, chain?: string[]): any;
|
|
93
|
-
annotate(key: string, value: any, asArray?: boolean): any;
|
|
94
|
-
};
|
|
102
|
+
declare function defineAnnotatedType(_kind?: TKind, base?: any): TAnnotatedTypeHandle;
|
|
103
|
+
/**
|
|
104
|
+
* Atscript Metadata Map with typed setters/getters
|
|
105
|
+
*/
|
|
95
106
|
interface TMetadataMap<O extends object> extends Map<keyof O, O[keyof O]> {
|
|
96
107
|
get<K extends keyof O>(key: K): O[K] | undefined;
|
|
97
108
|
set<K extends keyof O>(key: K, value: O[K]): this;
|
|
98
109
|
}
|
|
110
|
+
interface TAnnotatedTypeHandle {
|
|
111
|
+
$type: TAtscriptAnnotatedType;
|
|
112
|
+
$def: {
|
|
113
|
+
kind: TKind;
|
|
114
|
+
} & Omit<TAtscriptTypeComplex, 'kind'> & Omit<TAtscriptTypeFinal, 'kind'> & Omit<TAtscriptTypeArray, 'kind'> & Omit<TAtscriptTypeObject<string>, 'kind'>;
|
|
115
|
+
$metadata: TMetadataMap<AtscriptMetadata>;
|
|
116
|
+
_existingObject: TAtscriptAnnotatedType | undefined;
|
|
117
|
+
tags(...tags: string[]): TAnnotatedTypeHandle;
|
|
118
|
+
designType(value: TAtscriptTypeFinal['designType']): TAnnotatedTypeHandle;
|
|
119
|
+
value(value: string | number | boolean): TAnnotatedTypeHandle;
|
|
120
|
+
of(value: TAtscriptAnnotatedType): TAnnotatedTypeHandle;
|
|
121
|
+
item(value: TAtscriptAnnotatedType): TAnnotatedTypeHandle;
|
|
122
|
+
prop(name: string, value: TAtscriptAnnotatedType): TAnnotatedTypeHandle;
|
|
123
|
+
propPattern(pattern: RegExp, value: TAtscriptAnnotatedType): TAnnotatedTypeHandle;
|
|
124
|
+
optional(value?: boolean): TAnnotatedTypeHandle;
|
|
125
|
+
copyMetadata(fromMetadata: TMetadataMap<AtscriptMetadata>): TAnnotatedTypeHandle;
|
|
126
|
+
refTo(type: TAtscriptAnnotatedType & {
|
|
127
|
+
name?: string;
|
|
128
|
+
}, chain?: string[]): TAnnotatedTypeHandle;
|
|
129
|
+
annotate(key: keyof AtscriptMetadata, value: any, asArray?: boolean): TAnnotatedTypeHandle;
|
|
130
|
+
}
|
|
131
|
+
declare function isAnnotatedTypeOfPrimitive(t: TAtscriptAnnotatedType): boolean;
|
|
99
132
|
|
|
100
|
-
export { type TAtscriptAnnotatedType, type TAtscriptAnnotatedTypeConstructor, type TAtscriptTypeArray, type TAtscriptTypeComplex, type TAtscriptTypeDef, type TAtscriptTypeFinal, type TAtscriptTypeObject, type TMetadataMap, type TValidatorOptions, Validator, ValidatorError, tsPlugin as default, defineAnnotatedType, isAnnotatedType };
|
|
133
|
+
export { type TAnnotatedTypeHandle, type TAtscriptAnnotatedType, type TAtscriptAnnotatedTypeConstructor, type TAtscriptTypeArray, type TAtscriptTypeComplex, type TAtscriptTypeDef, type TAtscriptTypeFinal, type TAtscriptTypeObject, type TMetadataMap, type TValidatorOptions, type TValidatorPlugin, type TValidatorPluginContext, Validator, ValidatorError, tsPlugin as default, defineAnnotatedType, isAnnotatedType, isAnnotatedTypeOfPrimitive };
|
package/dist/index.mjs
CHANGED
|
@@ -244,17 +244,41 @@ var TypeRenderer = class extends BaseRenderer {
|
|
|
244
244
|
}
|
|
245
245
|
renderStructure(struct, asClass) {
|
|
246
246
|
this.blockln("{}");
|
|
247
|
+
const patterns = [];
|
|
248
|
+
let hasProp = false;
|
|
247
249
|
for (const prop of Array.from(struct.props.values())) {
|
|
250
|
+
if (prop.token("identifier")?.pattern) {
|
|
251
|
+
patterns.push(prop);
|
|
252
|
+
continue;
|
|
253
|
+
}
|
|
254
|
+
hasProp = true;
|
|
248
255
|
const optional = !!prop.token("optional");
|
|
249
256
|
this.write(wrapProp(prop.id), optional ? "?" : "", ": ");
|
|
250
257
|
this.renderTypeDef(prop.getDefinition());
|
|
251
258
|
this.writeln();
|
|
252
259
|
}
|
|
260
|
+
if (patterns.length) {
|
|
261
|
+
this.write(`[key: string]: `);
|
|
262
|
+
if (hasProp) this.writeln("any");
|
|
263
|
+
else if (patterns.length === 1) {
|
|
264
|
+
this.renderTypeDef(patterns[0].getDefinition());
|
|
265
|
+
this.writeln();
|
|
266
|
+
} else {
|
|
267
|
+
this.indent();
|
|
268
|
+
for (const prop of patterns) {
|
|
269
|
+
this.writeln();
|
|
270
|
+
this.write("| ");
|
|
271
|
+
this.renderTypeDef(prop.getDefinition());
|
|
272
|
+
}
|
|
273
|
+
this.unindent();
|
|
274
|
+
this.writeln();
|
|
275
|
+
}
|
|
276
|
+
}
|
|
253
277
|
if (asClass) {
|
|
254
278
|
this.writeln("static __is_atscript_annotated_type: true");
|
|
255
279
|
this.writeln(`static type: TAtscriptTypeObject<keyof ${asClass}>`);
|
|
256
280
|
this.writeln(`static metadata: TMetadataMap<AtscriptMetadata>`);
|
|
257
|
-
this.writeln(`static validator: <TT extends TAtscriptAnnotatedTypeConstructor = ${asClass}>(opts?: TValidatorOptions) => Validator<TT>`);
|
|
281
|
+
this.writeln(`static validator: <TT extends TAtscriptAnnotatedTypeConstructor = ${asClass}>(opts?: Partial<TValidatorOptions>) => Validator<TT>`);
|
|
258
282
|
}
|
|
259
283
|
this.pop();
|
|
260
284
|
}
|
|
@@ -296,7 +320,7 @@ else if (isPrimitive(realDef)) typeDef = "TAtscriptTypeFinal";
|
|
|
296
320
|
this.writeln(`const __is_atscript_annotated_type: true`);
|
|
297
321
|
this.writeln(`const type: ${typeDef}`);
|
|
298
322
|
this.writeln(`const metadata: TMetadataMap<AtscriptMetadata>`);
|
|
299
|
-
this.writeln(`
|
|
323
|
+
this.writeln(`const validator: <TT extends TAtscriptAnnotatedTypeConstructor = ${node.id}>(opts?: Partial<TValidatorOptions>) => Validator<TT>`);
|
|
300
324
|
this.popln();
|
|
301
325
|
}
|
|
302
326
|
renderJsDoc(node) {
|
|
@@ -481,6 +505,17 @@ var JsRenderer = class extends BaseRenderer {
|
|
|
481
505
|
this.unindent();
|
|
482
506
|
this.write(`)`);
|
|
483
507
|
}
|
|
508
|
+
for (const [key, propDef] of Object.entries(def.propsPatterns)) {
|
|
509
|
+
const optional = typeof propDef === "object" && propDef.optional;
|
|
510
|
+
this.writeln(`.propPattern(`);
|
|
511
|
+
this.indent();
|
|
512
|
+
this.writeln(`${key},`);
|
|
513
|
+
this.renderPrimitiveDef(propDef);
|
|
514
|
+
if (optional) this.writeln(".optional()");
|
|
515
|
+
this.writeln(".$type");
|
|
516
|
+
this.unindent();
|
|
517
|
+
this.write(`)`);
|
|
518
|
+
}
|
|
484
519
|
this.unindent();
|
|
485
520
|
return;
|
|
486
521
|
default: return this.writeln(`$(${d()}).designType("any")`);
|
|
@@ -489,10 +524,17 @@ var JsRenderer = class extends BaseRenderer {
|
|
|
489
524
|
defineObject(node) {
|
|
490
525
|
const props = Array.from(node.props.values());
|
|
491
526
|
for (const prop of props) {
|
|
527
|
+
const pattern = prop.token("identifier")?.pattern;
|
|
492
528
|
const optional = !!prop.token("optional");
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
529
|
+
if (pattern) {
|
|
530
|
+
this.writeln(`.propPattern(`);
|
|
531
|
+
this.indent();
|
|
532
|
+
this.writeln(`/${pattern.source}/${pattern.flags},`);
|
|
533
|
+
} else {
|
|
534
|
+
this.writeln(`.prop(`);
|
|
535
|
+
this.indent();
|
|
536
|
+
this.writeln(`"${escapeQuotes(prop.id)}",`);
|
|
537
|
+
}
|
|
496
538
|
this.annotateType(prop.getDefinition());
|
|
497
539
|
this.indent().defineMetadata(prop).unindent();
|
|
498
540
|
if (optional) this.writeln(" .optional()");
|
|
@@ -628,7 +670,7 @@ var Validator = class {
|
|
|
628
670
|
error(message, path$1, details) {
|
|
629
671
|
const errors = this.stackErrors[this.stackErrors.length - 1] || this.errors;
|
|
630
672
|
const error = {
|
|
631
|
-
path: path$1 || this.
|
|
673
|
+
path: path$1 || this.path,
|
|
632
674
|
message
|
|
633
675
|
};
|
|
634
676
|
if (details?.length) error.details = details;
|
|
@@ -641,7 +683,7 @@ var Validator = class {
|
|
|
641
683
|
this.push("");
|
|
642
684
|
this.errors = [];
|
|
643
685
|
this.stackErrors = [];
|
|
644
|
-
const passed = this.
|
|
686
|
+
const passed = this.validateSafe(this.def, value);
|
|
645
687
|
this.pop(!passed);
|
|
646
688
|
if (!passed) {
|
|
647
689
|
if (safe) return false;
|
|
@@ -649,10 +691,21 @@ var Validator = class {
|
|
|
649
691
|
}
|
|
650
692
|
return true;
|
|
651
693
|
}
|
|
652
|
-
|
|
694
|
+
validateSafe(def, value) {
|
|
653
695
|
if (this.isLimitExceeded()) return false;
|
|
654
696
|
if (!isAnnotatedType(def)) throw new Error("Can not validate not-annotated type");
|
|
697
|
+
if (typeof this.opts.replace === "function") def = this.opts.replace(def, this.path);
|
|
655
698
|
if (def.optional && value === undefined) return true;
|
|
699
|
+
for (const plugin of this.opts.plugins) {
|
|
700
|
+
const result = plugin(this, def, value);
|
|
701
|
+
if (result === false || result === true) return result;
|
|
702
|
+
}
|
|
703
|
+
return this.validateAnnotatedType(def, value);
|
|
704
|
+
}
|
|
705
|
+
get path() {
|
|
706
|
+
return this.stackPath.slice(1).join(".");
|
|
707
|
+
}
|
|
708
|
+
validateAnnotatedType(def, value) {
|
|
656
709
|
switch (def.type.kind) {
|
|
657
710
|
case "object": return this.validateObject(def, value);
|
|
658
711
|
case "union": return this.validateUnion(def, value);
|
|
@@ -668,7 +721,7 @@ var Validator = class {
|
|
|
668
721
|
const popped = [];
|
|
669
722
|
for (const item of def.type.items) {
|
|
670
723
|
this.push(`[${item.type.kind || item.type.designType}(${i})]`);
|
|
671
|
-
if (this.
|
|
724
|
+
if (this.validateSafe(item, value)) {
|
|
672
725
|
this.pop(false);
|
|
673
726
|
return true;
|
|
674
727
|
}
|
|
@@ -682,7 +735,7 @@ var Validator = class {
|
|
|
682
735
|
return false;
|
|
683
736
|
}
|
|
684
737
|
validateIntersection(def, value) {
|
|
685
|
-
for (const item of def.type.items) if (!this.
|
|
738
|
+
for (const item of def.type.items) if (!this.validateSafe(item, value)) return false;
|
|
686
739
|
return true;
|
|
687
740
|
}
|
|
688
741
|
validateTuple(def, value) {
|
|
@@ -693,7 +746,7 @@ var Validator = class {
|
|
|
693
746
|
let i = 0;
|
|
694
747
|
for (const item of def.type.items) {
|
|
695
748
|
this.push(`[${i}]`);
|
|
696
|
-
if (!this.
|
|
749
|
+
if (!this.validateSafe(item, value[i])) {
|
|
697
750
|
this.pop(true);
|
|
698
751
|
return false;
|
|
699
752
|
}
|
|
@@ -721,7 +774,7 @@ var Validator = class {
|
|
|
721
774
|
let passed = true;
|
|
722
775
|
for (const item of value) {
|
|
723
776
|
this.push(`[${i}]`);
|
|
724
|
-
if (!this.
|
|
777
|
+
if (!this.validateSafe(def.type.of, item)) {
|
|
725
778
|
passed = false;
|
|
726
779
|
this.pop(true);
|
|
727
780
|
if (this.isLimitExceeded()) return false;
|
|
@@ -740,7 +793,7 @@ var Validator = class {
|
|
|
740
793
|
const typeKeys = new Set();
|
|
741
794
|
const skipList = new Set();
|
|
742
795
|
if (this.opts.skipList) {
|
|
743
|
-
const path$1 = this.stackPath.length > 1 ? this.
|
|
796
|
+
const path$1 = this.stackPath.length > 1 ? this.path + "." : "";
|
|
744
797
|
this.opts.skipList.forEach((item) => {
|
|
745
798
|
if (item.startsWith(path$1)) {
|
|
746
799
|
const key = item.slice(path$1.length);
|
|
@@ -750,7 +803,7 @@ var Validator = class {
|
|
|
750
803
|
});
|
|
751
804
|
}
|
|
752
805
|
let partialFunctionMatched = false;
|
|
753
|
-
if (typeof this.opts.partial === "function") partialFunctionMatched = this.opts.partial(def, this.
|
|
806
|
+
if (typeof this.opts.partial === "function") partialFunctionMatched = this.opts.partial(def, this.path);
|
|
754
807
|
for (const [key, item] of def.type.props.entries()) {
|
|
755
808
|
if (skipList.has(key)) continue;
|
|
756
809
|
typeKeys.add(key);
|
|
@@ -758,15 +811,35 @@ var Validator = class {
|
|
|
758
811
|
if (partialFunctionMatched || this.opts.partial === "deep" || this.opts.partial === true && this.stackPath.length <= 1) continue;
|
|
759
812
|
}
|
|
760
813
|
this.push(key);
|
|
761
|
-
if (this.
|
|
814
|
+
if (this.validateSafe(item, value[key])) this.pop(false);
|
|
762
815
|
else {
|
|
763
816
|
passed = false;
|
|
764
817
|
this.pop(true);
|
|
765
818
|
if (this.isLimitExceeded()) return false;
|
|
766
819
|
}
|
|
767
820
|
}
|
|
768
|
-
for (const key of valueKeys)
|
|
769
|
-
|
|
821
|
+
for (const key of valueKeys)
|
|
822
|
+
/** matched patterns for unknown keys */ if (!typeKeys.has(key)) {
|
|
823
|
+
const matched = [];
|
|
824
|
+
for (const { pattern, def: propDef } of def.type.propsPatterns) if (pattern.test(key)) matched.push({
|
|
825
|
+
pattern,
|
|
826
|
+
def: propDef
|
|
827
|
+
});
|
|
828
|
+
if (matched.length) {
|
|
829
|
+
let keyPassed = false;
|
|
830
|
+
for (const { def: def$1 } of matched) if (this.validateSafe(def$1, value[key])) {
|
|
831
|
+
this.pop(false);
|
|
832
|
+
keyPassed = true;
|
|
833
|
+
break;
|
|
834
|
+
}
|
|
835
|
+
if (!keyPassed) {
|
|
836
|
+
this.push(key);
|
|
837
|
+
this.validateSafe(matched[0].def, value[key]);
|
|
838
|
+
this.pop(true);
|
|
839
|
+
passed = false;
|
|
840
|
+
if (this.isLimitExceeded()) return false;
|
|
841
|
+
}
|
|
842
|
+
} else if (this.opts.unknwonProps !== "ignore") {
|
|
770
843
|
if (this.opts.unknwonProps === "error") {
|
|
771
844
|
this.push(key);
|
|
772
845
|
this.error(`Unexpected property`);
|
|
@@ -884,7 +957,8 @@ else {
|
|
|
884
957
|
partial: false,
|
|
885
958
|
unknwonProps: "error",
|
|
886
959
|
errorLimit: 10,
|
|
887
|
-
...opts
|
|
960
|
+
...opts,
|
|
961
|
+
plugins: opts?.plugins || []
|
|
888
962
|
};
|
|
889
963
|
}
|
|
890
964
|
};
|
|
@@ -908,7 +982,10 @@ function defineAnnotatedType(_kind, base) {
|
|
|
908
982
|
"intersection",
|
|
909
983
|
"tuple"
|
|
910
984
|
].includes(kind)) type.items = [];
|
|
911
|
-
if (kind === "object")
|
|
985
|
+
if (kind === "object") {
|
|
986
|
+
type.props = new Map();
|
|
987
|
+
type.propsPatterns = [];
|
|
988
|
+
}
|
|
912
989
|
type.tags = new Set();
|
|
913
990
|
const metadata = base?.metadata || new Map();
|
|
914
991
|
if (base) Object.assign(base, {
|
|
@@ -956,8 +1033,19 @@ else base = {
|
|
|
956
1033
|
this.$def.props.set(name, value);
|
|
957
1034
|
return this;
|
|
958
1035
|
},
|
|
959
|
-
|
|
960
|
-
this.$
|
|
1036
|
+
propPattern(pattern, def) {
|
|
1037
|
+
this.$def.propsPatterns.push({
|
|
1038
|
+
pattern,
|
|
1039
|
+
def
|
|
1040
|
+
});
|
|
1041
|
+
return this;
|
|
1042
|
+
},
|
|
1043
|
+
optional(value = true) {
|
|
1044
|
+
this.$type.optional = value;
|
|
1045
|
+
return this;
|
|
1046
|
+
},
|
|
1047
|
+
copyMetadata(fromMetadata, ignore) {
|
|
1048
|
+
for (const [key, value] of fromMetadata.entries()) if (!ignore || !ignore.has(key)) this.$metadata.set(key, value);
|
|
961
1049
|
return this;
|
|
962
1050
|
},
|
|
963
1051
|
refTo(type$1, chain) {
|
|
@@ -967,7 +1055,7 @@ else base = {
|
|
|
967
1055
|
let keys = "";
|
|
968
1056
|
for (const c of chain || []) {
|
|
969
1057
|
keys += `["${c}"]`;
|
|
970
|
-
if (newBase.type.kind === "object") newBase = newBase.type.props.get(c);
|
|
1058
|
+
if (newBase.type.kind === "object" && newBase.type.props.has(c)) newBase = newBase.type.props.get(c);
|
|
971
1059
|
else throw new Error(`Can't find prop ${typeName}${keys}`);
|
|
972
1060
|
}
|
|
973
1061
|
if (!newBase && keys) throw new Error(`Can't find prop ${typeName}${keys}`);
|
|
@@ -995,10 +1083,23 @@ else this.$metadata.set(key, value);
|
|
|
995
1083
|
};
|
|
996
1084
|
return handle;
|
|
997
1085
|
}
|
|
1086
|
+
function isAnnotatedTypeOfPrimitive(t) {
|
|
1087
|
+
if (["array", "object"].includes(t.type.kind)) return false;
|
|
1088
|
+
if (!t.type.kind) return true;
|
|
1089
|
+
if ([
|
|
1090
|
+
"union",
|
|
1091
|
+
"tuple",
|
|
1092
|
+
"intersection"
|
|
1093
|
+
].includes(t.type.kind)) {
|
|
1094
|
+
for (const item of t.type.items) if (!isAnnotatedTypeOfPrimitive(item)) return false;
|
|
1095
|
+
return true;
|
|
1096
|
+
}
|
|
1097
|
+
return false;
|
|
1098
|
+
}
|
|
998
1099
|
|
|
999
1100
|
//#endregion
|
|
1000
1101
|
//#region packages/typescript/src/index.ts
|
|
1001
1102
|
var src_default = tsPlugin;
|
|
1002
1103
|
|
|
1003
1104
|
//#endregion
|
|
1004
|
-
export { Validator, ValidatorError, src_default as default, defineAnnotatedType, isAnnotatedType };
|
|
1105
|
+
export { Validator, ValidatorError, src_default as default, defineAnnotatedType, isAnnotatedType, isAnnotatedTypeOfPrimitive };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atscript/typescript",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.18",
|
|
4
4
|
"description": "Atscript: typescript-gen support.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.mjs",
|
|
@@ -46,13 +46,15 @@
|
|
|
46
46
|
},
|
|
47
47
|
"homepage": "https://github.com/moostjs/atscript/tree/main/packages/typescript#readme",
|
|
48
48
|
"license": "ISC",
|
|
49
|
+
"peerDependencies": {
|
|
50
|
+
"@atscript/core": "^0.0.18"
|
|
51
|
+
},
|
|
49
52
|
"dependencies": {
|
|
50
|
-
"@moostjs/event-cli": "^0.5.
|
|
51
|
-
"moost": "^0.5.
|
|
52
|
-
"@atscript/core": "^0.0.17"
|
|
53
|
+
"@moostjs/event-cli": "^0.5.30",
|
|
54
|
+
"moost": "^0.5.30"
|
|
53
55
|
},
|
|
54
56
|
"devDependencies": {
|
|
55
|
-
"vitest": "
|
|
57
|
+
"vitest": "3.2.4"
|
|
56
58
|
},
|
|
57
59
|
"scripts": {
|
|
58
60
|
"pub": "pnpm publish --access public",
|