@atscript/typescript 0.1.3 → 0.1.5
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 +28 -3
- package/dist/index.cjs +28 -3
- package/dist/index.mjs +28 -3
- package/dist/utils.cjs +26 -3
- package/dist/utils.d.ts +16 -4
- package/dist/utils.mjs +26 -4
- package/package.json +2 -2
package/dist/cli.cjs
CHANGED
|
@@ -298,6 +298,10 @@ var TypeRenderer = class TypeRenderer extends BaseRenderer {
|
|
|
298
298
|
patterns.push(prop);
|
|
299
299
|
continue;
|
|
300
300
|
}
|
|
301
|
+
if (this.isPhantomProp(prop.getDefinition())) {
|
|
302
|
+
this.writeln(`// ${prop.id}: phantom`);
|
|
303
|
+
continue;
|
|
304
|
+
}
|
|
301
305
|
const optional = !!prop.token("optional");
|
|
302
306
|
this.write(wrapProp(prop.id), optional ? "?" : "", ": ");
|
|
303
307
|
const renderedDef = this.renderTypeDefString(prop.getDefinition());
|
|
@@ -401,11 +405,20 @@ else if ((0, __atscript_core.isPrimitive)(realDef)) typeDef = `TAtscriptTypeFina
|
|
|
401
405
|
this.writeln(`const __is_atscript_annotated_type: true`);
|
|
402
406
|
this.writeln(`const type: ${typeDef}`);
|
|
403
407
|
this.writeln(`const metadata: TMetadataMap<AtscriptMetadata>`);
|
|
404
|
-
this.writeln(`const validator: (opts?: Partial<TValidatorOptions>) => Validator<
|
|
408
|
+
this.writeln(`const validator: (opts?: Partial<TValidatorOptions>) => Validator<typeof ${name}, ${name}>`);
|
|
405
409
|
if (resolveJsonSchemaMode(this.opts) === false) this.writeln("/** @deprecated JSON Schema support is disabled. Calling this method will throw a runtime error. To enable, set `jsonSchema: 'lazy'` or `jsonSchema: 'bundle'` in tsPlugin options, or add `@emit.jsonSchema` annotation to individual interfaces. */");
|
|
406
410
|
this.writeln("const toJsonSchema: () => any");
|
|
407
411
|
this.popln();
|
|
408
412
|
}
|
|
413
|
+
isPhantomProp(def) {
|
|
414
|
+
if (!def) return false;
|
|
415
|
+
if ((0, __atscript_core.isPrimitive)(def) && def.id === "phantom") return true;
|
|
416
|
+
if ((0, __atscript_core.isRef)(def)) {
|
|
417
|
+
const unwound = this.doc.unwindType(def.id, def.chain)?.def;
|
|
418
|
+
return (0, __atscript_core.isPrimitive)(unwound) && unwound.id === "phantom";
|
|
419
|
+
}
|
|
420
|
+
return false;
|
|
421
|
+
}
|
|
409
422
|
isTypeTarget(name, doc) {
|
|
410
423
|
const d = doc || this.doc;
|
|
411
424
|
const decl = d.getDeclarationOwnerNode(name);
|
|
@@ -448,7 +461,11 @@ function renderPrimitiveTypeDef(def) {
|
|
|
448
461
|
//#region packages/typescript/src/traverse.ts
|
|
449
462
|
function forAnnotatedType(def, handlers) {
|
|
450
463
|
switch (def.type.kind) {
|
|
451
|
-
case "":
|
|
464
|
+
case "": {
|
|
465
|
+
const typed = def;
|
|
466
|
+
if (handlers.phantom && typed.type.designType === "phantom") return handlers.phantom(typed);
|
|
467
|
+
return handlers.final(typed);
|
|
468
|
+
}
|
|
452
469
|
case "object": return handlers.object(def);
|
|
453
470
|
case "array": return handlers.array(def);
|
|
454
471
|
case "union": return handlers.union(def);
|
|
@@ -542,6 +559,7 @@ var Validator = class {
|
|
|
542
559
|
validateAnnotatedType(def, value) {
|
|
543
560
|
return forAnnotatedType(def, {
|
|
544
561
|
final: (d) => this.validatePrimitive(d, value),
|
|
562
|
+
phantom: () => true,
|
|
545
563
|
object: (d) => this.validateObject(d, value),
|
|
546
564
|
array: (d) => this.validateArray(d, value),
|
|
547
565
|
union: (d) => this.validateUnion(d, value),
|
|
@@ -638,7 +656,7 @@ var Validator = class {
|
|
|
638
656
|
let partialFunctionMatched = false;
|
|
639
657
|
if (typeof this.opts.partial === "function") partialFunctionMatched = this.opts.partial(def, this.path);
|
|
640
658
|
for (const [key, item] of def.type.props.entries()) {
|
|
641
|
-
if (skipList.has(key)) continue;
|
|
659
|
+
if (skipList.has(key) || isPhantomType(item)) continue;
|
|
642
660
|
typeKeys.add(key);
|
|
643
661
|
if (value[key] === undefined) {
|
|
644
662
|
if (partialFunctionMatched || this.opts.partial === "deep" || this.opts.partial === true && this.stackPath.length <= 1) continue;
|
|
@@ -920,6 +938,9 @@ else if (!newBase) throw new Error(`"${typeName}" is not annotated type`);
|
|
|
920
938
|
};
|
|
921
939
|
return handle;
|
|
922
940
|
}
|
|
941
|
+
function isPhantomType(def) {
|
|
942
|
+
return def.type.kind === "" && def.type.designType === "phantom";
|
|
943
|
+
}
|
|
923
944
|
|
|
924
945
|
//#endregion
|
|
925
946
|
//#region packages/typescript/src/json-schema.ts
|
|
@@ -927,10 +948,14 @@ function buildJsonSchema(type) {
|
|
|
927
948
|
const build$1 = (def) => {
|
|
928
949
|
const meta = def.metadata;
|
|
929
950
|
return forAnnotatedType(def, {
|
|
951
|
+
phantom() {
|
|
952
|
+
return {};
|
|
953
|
+
},
|
|
930
954
|
object(d) {
|
|
931
955
|
const properties = {};
|
|
932
956
|
const required = [];
|
|
933
957
|
for (const [key, val] of d.type.props.entries()) {
|
|
958
|
+
if (isPhantomType(val)) continue;
|
|
934
959
|
properties[key] = build$1(val);
|
|
935
960
|
if (!val.optional) required.push(key);
|
|
936
961
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -295,6 +295,10 @@ var TypeRenderer = class TypeRenderer extends BaseRenderer {
|
|
|
295
295
|
patterns.push(prop);
|
|
296
296
|
continue;
|
|
297
297
|
}
|
|
298
|
+
if (this.isPhantomProp(prop.getDefinition())) {
|
|
299
|
+
this.writeln(`// ${prop.id}: phantom`);
|
|
300
|
+
continue;
|
|
301
|
+
}
|
|
298
302
|
const optional = !!prop.token("optional");
|
|
299
303
|
this.write(wrapProp(prop.id), optional ? "?" : "", ": ");
|
|
300
304
|
const renderedDef = this.renderTypeDefString(prop.getDefinition());
|
|
@@ -398,11 +402,20 @@ else if ((0, __atscript_core.isPrimitive)(realDef)) typeDef = `TAtscriptTypeFina
|
|
|
398
402
|
this.writeln(`const __is_atscript_annotated_type: true`);
|
|
399
403
|
this.writeln(`const type: ${typeDef}`);
|
|
400
404
|
this.writeln(`const metadata: TMetadataMap<AtscriptMetadata>`);
|
|
401
|
-
this.writeln(`const validator: (opts?: Partial<TValidatorOptions>) => Validator<
|
|
405
|
+
this.writeln(`const validator: (opts?: Partial<TValidatorOptions>) => Validator<typeof ${name}, ${name}>`);
|
|
402
406
|
if (resolveJsonSchemaMode(this.opts) === false) this.writeln("/** @deprecated JSON Schema support is disabled. Calling this method will throw a runtime error. To enable, set `jsonSchema: 'lazy'` or `jsonSchema: 'bundle'` in tsPlugin options, or add `@emit.jsonSchema` annotation to individual interfaces. */");
|
|
403
407
|
this.writeln("const toJsonSchema: () => any");
|
|
404
408
|
this.popln();
|
|
405
409
|
}
|
|
410
|
+
isPhantomProp(def) {
|
|
411
|
+
if (!def) return false;
|
|
412
|
+
if ((0, __atscript_core.isPrimitive)(def) && def.id === "phantom") return true;
|
|
413
|
+
if ((0, __atscript_core.isRef)(def)) {
|
|
414
|
+
const unwound = this.doc.unwindType(def.id, def.chain)?.def;
|
|
415
|
+
return (0, __atscript_core.isPrimitive)(unwound) && unwound.id === "phantom";
|
|
416
|
+
}
|
|
417
|
+
return false;
|
|
418
|
+
}
|
|
406
419
|
isTypeTarget(name, doc) {
|
|
407
420
|
const d = doc || this.doc;
|
|
408
421
|
const decl = d.getDeclarationOwnerNode(name);
|
|
@@ -445,7 +458,11 @@ function renderPrimitiveTypeDef(def) {
|
|
|
445
458
|
//#region packages/typescript/src/traverse.ts
|
|
446
459
|
function forAnnotatedType(def, handlers) {
|
|
447
460
|
switch (def.type.kind) {
|
|
448
|
-
case "":
|
|
461
|
+
case "": {
|
|
462
|
+
const typed = def;
|
|
463
|
+
if (handlers.phantom && typed.type.designType === "phantom") return handlers.phantom(typed);
|
|
464
|
+
return handlers.final(typed);
|
|
465
|
+
}
|
|
449
466
|
case "object": return handlers.object(def);
|
|
450
467
|
case "array": return handlers.array(def);
|
|
451
468
|
case "union": return handlers.union(def);
|
|
@@ -539,6 +556,7 @@ var Validator = class {
|
|
|
539
556
|
validateAnnotatedType(def, value) {
|
|
540
557
|
return forAnnotatedType(def, {
|
|
541
558
|
final: (d) => this.validatePrimitive(d, value),
|
|
559
|
+
phantom: () => true,
|
|
542
560
|
object: (d) => this.validateObject(d, value),
|
|
543
561
|
array: (d) => this.validateArray(d, value),
|
|
544
562
|
union: (d) => this.validateUnion(d, value),
|
|
@@ -635,7 +653,7 @@ var Validator = class {
|
|
|
635
653
|
let partialFunctionMatched = false;
|
|
636
654
|
if (typeof this.opts.partial === "function") partialFunctionMatched = this.opts.partial(def, this.path);
|
|
637
655
|
for (const [key, item] of def.type.props.entries()) {
|
|
638
|
-
if (skipList.has(key)) continue;
|
|
656
|
+
if (skipList.has(key) || isPhantomType(item)) continue;
|
|
639
657
|
typeKeys.add(key);
|
|
640
658
|
if (value[key] === undefined) {
|
|
641
659
|
if (partialFunctionMatched || this.opts.partial === "deep" || this.opts.partial === true && this.stackPath.length <= 1) continue;
|
|
@@ -917,6 +935,9 @@ else if (!newBase) throw new Error(`"${typeName}" is not annotated type`);
|
|
|
917
935
|
};
|
|
918
936
|
return handle;
|
|
919
937
|
}
|
|
938
|
+
function isPhantomType(def) {
|
|
939
|
+
return def.type.kind === "" && def.type.designType === "phantom";
|
|
940
|
+
}
|
|
920
941
|
|
|
921
942
|
//#endregion
|
|
922
943
|
//#region packages/typescript/src/json-schema.ts
|
|
@@ -924,10 +945,14 @@ function buildJsonSchema(type) {
|
|
|
924
945
|
const build = (def) => {
|
|
925
946
|
const meta = def.metadata;
|
|
926
947
|
return forAnnotatedType(def, {
|
|
948
|
+
phantom() {
|
|
949
|
+
return {};
|
|
950
|
+
},
|
|
927
951
|
object(d) {
|
|
928
952
|
const properties = {};
|
|
929
953
|
const required = [];
|
|
930
954
|
for (const [key, val] of d.type.props.entries()) {
|
|
955
|
+
if (isPhantomType(val)) continue;
|
|
931
956
|
properties[key] = build(val);
|
|
932
957
|
if (!val.optional) required.push(key);
|
|
933
958
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -271,6 +271,10 @@ var TypeRenderer = class TypeRenderer extends BaseRenderer {
|
|
|
271
271
|
patterns.push(prop);
|
|
272
272
|
continue;
|
|
273
273
|
}
|
|
274
|
+
if (this.isPhantomProp(prop.getDefinition())) {
|
|
275
|
+
this.writeln(`// ${prop.id}: phantom`);
|
|
276
|
+
continue;
|
|
277
|
+
}
|
|
274
278
|
const optional = !!prop.token("optional");
|
|
275
279
|
this.write(wrapProp(prop.id), optional ? "?" : "", ": ");
|
|
276
280
|
const renderedDef = this.renderTypeDefString(prop.getDefinition());
|
|
@@ -374,11 +378,20 @@ else if (isPrimitive(realDef)) typeDef = `TAtscriptTypeFinal<${name}>`;
|
|
|
374
378
|
this.writeln(`const __is_atscript_annotated_type: true`);
|
|
375
379
|
this.writeln(`const type: ${typeDef}`);
|
|
376
380
|
this.writeln(`const metadata: TMetadataMap<AtscriptMetadata>`);
|
|
377
|
-
this.writeln(`const validator: (opts?: Partial<TValidatorOptions>) => Validator<
|
|
381
|
+
this.writeln(`const validator: (opts?: Partial<TValidatorOptions>) => Validator<typeof ${name}, ${name}>`);
|
|
378
382
|
if (resolveJsonSchemaMode(this.opts) === false) this.writeln("/** @deprecated JSON Schema support is disabled. Calling this method will throw a runtime error. To enable, set `jsonSchema: 'lazy'` or `jsonSchema: 'bundle'` in tsPlugin options, or add `@emit.jsonSchema` annotation to individual interfaces. */");
|
|
379
383
|
this.writeln("const toJsonSchema: () => any");
|
|
380
384
|
this.popln();
|
|
381
385
|
}
|
|
386
|
+
isPhantomProp(def) {
|
|
387
|
+
if (!def) return false;
|
|
388
|
+
if (isPrimitive(def) && def.id === "phantom") return true;
|
|
389
|
+
if (isRef(def)) {
|
|
390
|
+
const unwound = this.doc.unwindType(def.id, def.chain)?.def;
|
|
391
|
+
return isPrimitive(unwound) && unwound.id === "phantom";
|
|
392
|
+
}
|
|
393
|
+
return false;
|
|
394
|
+
}
|
|
382
395
|
isTypeTarget(name, doc) {
|
|
383
396
|
const d = doc || this.doc;
|
|
384
397
|
const decl = d.getDeclarationOwnerNode(name);
|
|
@@ -421,7 +434,11 @@ function renderPrimitiveTypeDef(def) {
|
|
|
421
434
|
//#region packages/typescript/src/traverse.ts
|
|
422
435
|
function forAnnotatedType(def, handlers) {
|
|
423
436
|
switch (def.type.kind) {
|
|
424
|
-
case "":
|
|
437
|
+
case "": {
|
|
438
|
+
const typed = def;
|
|
439
|
+
if (handlers.phantom && typed.type.designType === "phantom") return handlers.phantom(typed);
|
|
440
|
+
return handlers.final(typed);
|
|
441
|
+
}
|
|
425
442
|
case "object": return handlers.object(def);
|
|
426
443
|
case "array": return handlers.array(def);
|
|
427
444
|
case "union": return handlers.union(def);
|
|
@@ -515,6 +532,7 @@ var Validator = class {
|
|
|
515
532
|
validateAnnotatedType(def, value) {
|
|
516
533
|
return forAnnotatedType(def, {
|
|
517
534
|
final: (d) => this.validatePrimitive(d, value),
|
|
535
|
+
phantom: () => true,
|
|
518
536
|
object: (d) => this.validateObject(d, value),
|
|
519
537
|
array: (d) => this.validateArray(d, value),
|
|
520
538
|
union: (d) => this.validateUnion(d, value),
|
|
@@ -611,7 +629,7 @@ var Validator = class {
|
|
|
611
629
|
let partialFunctionMatched = false;
|
|
612
630
|
if (typeof this.opts.partial === "function") partialFunctionMatched = this.opts.partial(def, this.path);
|
|
613
631
|
for (const [key, item] of def.type.props.entries()) {
|
|
614
|
-
if (skipList.has(key)) continue;
|
|
632
|
+
if (skipList.has(key) || isPhantomType(item)) continue;
|
|
615
633
|
typeKeys.add(key);
|
|
616
634
|
if (value[key] === undefined) {
|
|
617
635
|
if (partialFunctionMatched || this.opts.partial === "deep" || this.opts.partial === true && this.stackPath.length <= 1) continue;
|
|
@@ -893,6 +911,9 @@ else if (!newBase) throw new Error(`"${typeName}" is not annotated type`);
|
|
|
893
911
|
};
|
|
894
912
|
return handle;
|
|
895
913
|
}
|
|
914
|
+
function isPhantomType(def) {
|
|
915
|
+
return def.type.kind === "" && def.type.designType === "phantom";
|
|
916
|
+
}
|
|
896
917
|
|
|
897
918
|
//#endregion
|
|
898
919
|
//#region packages/typescript/src/json-schema.ts
|
|
@@ -900,10 +921,14 @@ function buildJsonSchema(type) {
|
|
|
900
921
|
const build = (def) => {
|
|
901
922
|
const meta = def.metadata;
|
|
902
923
|
return forAnnotatedType(def, {
|
|
924
|
+
phantom() {
|
|
925
|
+
return {};
|
|
926
|
+
},
|
|
903
927
|
object(d) {
|
|
904
928
|
const properties = {};
|
|
905
929
|
const required = [];
|
|
906
930
|
for (const [key, val] of d.type.props.entries()) {
|
|
931
|
+
if (isPhantomType(val)) continue;
|
|
907
932
|
properties[key] = build(val);
|
|
908
933
|
if (!val.optional) required.push(key);
|
|
909
934
|
}
|
package/dist/utils.cjs
CHANGED
|
@@ -3,7 +3,11 @@
|
|
|
3
3
|
//#region packages/typescript/src/traverse.ts
|
|
4
4
|
function forAnnotatedType(def, handlers) {
|
|
5
5
|
switch (def.type.kind) {
|
|
6
|
-
case "":
|
|
6
|
+
case "": {
|
|
7
|
+
const typed = def;
|
|
8
|
+
if (handlers.phantom && typed.type.designType === "phantom") return handlers.phantom(typed);
|
|
9
|
+
return handlers.final(typed);
|
|
10
|
+
}
|
|
7
11
|
case "object": return handlers.object(def);
|
|
8
12
|
case "array": return handlers.array(def);
|
|
9
13
|
case "union": return handlers.union(def);
|
|
@@ -97,6 +101,7 @@ var Validator = class {
|
|
|
97
101
|
validateAnnotatedType(def, value) {
|
|
98
102
|
return forAnnotatedType(def, {
|
|
99
103
|
final: (d) => this.validatePrimitive(d, value),
|
|
104
|
+
phantom: () => true,
|
|
100
105
|
object: (d) => this.validateObject(d, value),
|
|
101
106
|
array: (d) => this.validateArray(d, value),
|
|
102
107
|
union: (d) => this.validateUnion(d, value),
|
|
@@ -193,7 +198,7 @@ var Validator = class {
|
|
|
193
198
|
let partialFunctionMatched = false;
|
|
194
199
|
if (typeof this.opts.partial === "function") partialFunctionMatched = this.opts.partial(def, this.path);
|
|
195
200
|
for (const [key, item] of def.type.props.entries()) {
|
|
196
|
-
if (skipList.has(key)) continue;
|
|
201
|
+
if (skipList.has(key) || isPhantomType(item)) continue;
|
|
197
202
|
typeKeys.add(key);
|
|
198
203
|
if (value[key] === undefined) {
|
|
199
204
|
if (partialFunctionMatched || this.opts.partial === "deep" || this.opts.partial === true && this.stackPath.length <= 1) continue;
|
|
@@ -475,6 +480,9 @@ else if (!newBase) throw new Error(`"${typeName}" is not annotated type`);
|
|
|
475
480
|
};
|
|
476
481
|
return handle;
|
|
477
482
|
}
|
|
483
|
+
function isPhantomType(def) {
|
|
484
|
+
return def.type.kind === "" && def.type.designType === "phantom";
|
|
485
|
+
}
|
|
478
486
|
function isAnnotatedTypeOfPrimitive(t) {
|
|
479
487
|
if (["array", "object"].includes(t.type.kind)) return false;
|
|
480
488
|
if (!t.type.kind) return true;
|
|
@@ -495,10 +503,14 @@ function buildJsonSchema(type) {
|
|
|
495
503
|
const build = (def) => {
|
|
496
504
|
const meta = def.metadata;
|
|
497
505
|
return forAnnotatedType(def, {
|
|
506
|
+
phantom() {
|
|
507
|
+
return {};
|
|
508
|
+
},
|
|
498
509
|
object(d) {
|
|
499
510
|
const properties = {};
|
|
500
511
|
const required = [];
|
|
501
512
|
for (const [key, val] of d.type.props.entries()) {
|
|
513
|
+
if (isPhantomType(val)) continue;
|
|
502
514
|
properties[key] = build(val);
|
|
503
515
|
if (!val.optional) required.push(key);
|
|
504
516
|
}
|
|
@@ -671,6 +683,13 @@ function serializeNode(def, path, options) {
|
|
|
671
683
|
}
|
|
672
684
|
function serializeTypeDef(def, path, options) {
|
|
673
685
|
return forAnnotatedType(def, {
|
|
686
|
+
phantom(d) {
|
|
687
|
+
return {
|
|
688
|
+
kind: "",
|
|
689
|
+
designType: d.type.designType,
|
|
690
|
+
tags: Array.from(d.type.tags)
|
|
691
|
+
};
|
|
692
|
+
},
|
|
674
693
|
final(d) {
|
|
675
694
|
const result = {
|
|
676
695
|
kind: "",
|
|
@@ -682,7 +701,10 @@ function serializeTypeDef(def, path, options) {
|
|
|
682
701
|
},
|
|
683
702
|
object(d) {
|
|
684
703
|
const props = {};
|
|
685
|
-
for (const [key, val] of d.type.props.entries())
|
|
704
|
+
for (const [key, val] of d.type.props.entries()) {
|
|
705
|
+
if (isPhantomType(val)) continue;
|
|
706
|
+
props[key] = serializeNode(val, [...path, key], options);
|
|
707
|
+
}
|
|
686
708
|
const propsPatterns = d.type.propsPatterns.map((pp) => ({
|
|
687
709
|
pattern: {
|
|
688
710
|
source: pp.pattern.source,
|
|
@@ -819,4 +841,5 @@ exports.forAnnotatedType = forAnnotatedType
|
|
|
819
841
|
exports.fromJsonSchema = fromJsonSchema
|
|
820
842
|
exports.isAnnotatedType = isAnnotatedType
|
|
821
843
|
exports.isAnnotatedTypeOfPrimitive = isAnnotatedTypeOfPrimitive
|
|
844
|
+
exports.isPhantomType = isPhantomType
|
|
822
845
|
exports.serializeAnnotatedType = serializeAnnotatedType
|
package/dist/utils.d.ts
CHANGED
|
@@ -130,7 +130,7 @@ interface TAtscriptTypeFinal<DataType = unknown> {
|
|
|
130
130
|
/**
|
|
131
131
|
* design type
|
|
132
132
|
*/
|
|
133
|
-
designType: 'string' | 'number' | 'boolean' | 'undefined' | 'null' | 'object' | 'any' | 'never';
|
|
133
|
+
designType: 'string' | 'number' | 'boolean' | 'undefined' | 'null' | 'object' | 'any' | 'never' | 'phantom';
|
|
134
134
|
/**
|
|
135
135
|
* value for literals
|
|
136
136
|
*/
|
|
@@ -156,10 +156,10 @@ type TAtscriptTypeDef<DataType = unknown> = TAtscriptTypeComplex<DataType> | TAt
|
|
|
156
156
|
* @typeParam T - The underlying type definition (e.g. {@link TAtscriptTypeObject}).
|
|
157
157
|
* @typeParam DataType - The TypeScript type the validated data narrows to (auto-inferred from `T`).
|
|
158
158
|
*/
|
|
159
|
-
interface TAtscriptAnnotatedType<T = TAtscriptTypeDef, DataType = InferDataType<T>> {
|
|
159
|
+
interface TAtscriptAnnotatedType<T extends TAtscriptTypeDef = TAtscriptTypeDef, DataType = InferDataType<T>> {
|
|
160
160
|
__is_atscript_annotated_type: true;
|
|
161
161
|
type: T;
|
|
162
|
-
validator
|
|
162
|
+
validator(opts?: Partial<TValidatorOptions>): Validator<this, DataType>;
|
|
163
163
|
metadata: TMetadataMap<AtscriptMetadata>;
|
|
164
164
|
optional?: boolean;
|
|
165
165
|
}
|
|
@@ -224,6 +224,13 @@ interface TAnnotatedTypeHandle {
|
|
|
224
224
|
}, chain?: string[]): TAnnotatedTypeHandle;
|
|
225
225
|
annotate(key: keyof AtscriptMetadata, value: any, asArray?: boolean): TAnnotatedTypeHandle;
|
|
226
226
|
}
|
|
227
|
+
/**
|
|
228
|
+
* Checks whether an annotated type is a phantom type.
|
|
229
|
+
*
|
|
230
|
+
* Phantom types do not affect the data type, validation, or schema,
|
|
231
|
+
* but are discoverable via runtime type traversal.
|
|
232
|
+
*/
|
|
233
|
+
declare function isPhantomType(def: TAtscriptAnnotatedType): boolean;
|
|
227
234
|
/**
|
|
228
235
|
* Checks whether an annotated type resolves to a primitive (non-object, non-array) shape.
|
|
229
236
|
*
|
|
@@ -280,6 +287,10 @@ declare function fromJsonSchema(schema: TJsonSchema): TAtscriptAnnotatedType;
|
|
|
280
287
|
* Provides the common `switch (def.type.kind)` pattern used by
|
|
281
288
|
* the validator, JSON-schema builder, and serializer.
|
|
282
289
|
* Each caller supplies its own handlers that control recursion.
|
|
290
|
+
*
|
|
291
|
+
* When a `phantom` handler is provided, phantom types (`designType === 'phantom'`)
|
|
292
|
+
* are dispatched to it instead of `final`. This allows consumers to skip or
|
|
293
|
+
* handle phantom props without polluting their `final` handler.
|
|
283
294
|
*/
|
|
284
295
|
declare function forAnnotatedType<R>(def: TAtscriptAnnotatedType, handlers: {
|
|
285
296
|
final: (def: TAtscriptAnnotatedType<TAtscriptTypeFinal>) => R;
|
|
@@ -288,6 +299,7 @@ declare function forAnnotatedType<R>(def: TAtscriptAnnotatedType, handlers: {
|
|
|
288
299
|
union: (def: TAtscriptAnnotatedType<TAtscriptTypeComplex>) => R;
|
|
289
300
|
intersection: (def: TAtscriptAnnotatedType<TAtscriptTypeComplex>) => R;
|
|
290
301
|
tuple: (def: TAtscriptAnnotatedType<TAtscriptTypeComplex>) => R;
|
|
302
|
+
phantom?: (def: TAtscriptAnnotatedType<TAtscriptTypeFinal>) => R;
|
|
291
303
|
}): R;
|
|
292
304
|
|
|
293
305
|
/** Current serialization format version. Bumped on breaking changes to the serialized shape. */
|
|
@@ -396,5 +408,5 @@ declare function serializeAnnotatedType(type: TAtscriptAnnotatedType, options?:
|
|
|
396
408
|
*/
|
|
397
409
|
declare function deserializeAnnotatedType(data: TSerializedAnnotatedType): TAtscriptAnnotatedType;
|
|
398
410
|
|
|
399
|
-
export { SERIALIZE_VERSION, Validator, ValidatorError, annotate, buildJsonSchema, defineAnnotatedType, deserializeAnnotatedType, forAnnotatedType, fromJsonSchema, isAnnotatedType, isAnnotatedTypeOfPrimitive, serializeAnnotatedType };
|
|
411
|
+
export { SERIALIZE_VERSION, Validator, ValidatorError, annotate, buildJsonSchema, defineAnnotatedType, deserializeAnnotatedType, forAnnotatedType, fromJsonSchema, isAnnotatedType, isAnnotatedTypeOfPrimitive, isPhantomType, serializeAnnotatedType };
|
|
400
412
|
export type { InferDataType, TAnnotatedTypeHandle, TAtscriptAnnotatedType, TAtscriptAnnotatedTypeConstructor, TAtscriptTypeArray, TAtscriptTypeComplex, TAtscriptTypeDef, TAtscriptTypeFinal, TAtscriptTypeObject, TMetadataMap, TProcessAnnotationContext, TSerializeOptions, TSerializedAnnotatedType, TSerializedAnnotatedTypeInner, TSerializedTypeArray, TSerializedTypeComplex, TSerializedTypeDef, TSerializedTypeFinal, TSerializedTypeObject, TValidatorOptions, TValidatorPlugin, TValidatorPluginContext };
|
package/dist/utils.mjs
CHANGED
|
@@ -2,7 +2,11 @@
|
|
|
2
2
|
//#region packages/typescript/src/traverse.ts
|
|
3
3
|
function forAnnotatedType(def, handlers) {
|
|
4
4
|
switch (def.type.kind) {
|
|
5
|
-
case "":
|
|
5
|
+
case "": {
|
|
6
|
+
const typed = def;
|
|
7
|
+
if (handlers.phantom && typed.type.designType === "phantom") return handlers.phantom(typed);
|
|
8
|
+
return handlers.final(typed);
|
|
9
|
+
}
|
|
6
10
|
case "object": return handlers.object(def);
|
|
7
11
|
case "array": return handlers.array(def);
|
|
8
12
|
case "union": return handlers.union(def);
|
|
@@ -96,6 +100,7 @@ var Validator = class {
|
|
|
96
100
|
validateAnnotatedType(def, value) {
|
|
97
101
|
return forAnnotatedType(def, {
|
|
98
102
|
final: (d) => this.validatePrimitive(d, value),
|
|
103
|
+
phantom: () => true,
|
|
99
104
|
object: (d) => this.validateObject(d, value),
|
|
100
105
|
array: (d) => this.validateArray(d, value),
|
|
101
106
|
union: (d) => this.validateUnion(d, value),
|
|
@@ -192,7 +197,7 @@ var Validator = class {
|
|
|
192
197
|
let partialFunctionMatched = false;
|
|
193
198
|
if (typeof this.opts.partial === "function") partialFunctionMatched = this.opts.partial(def, this.path);
|
|
194
199
|
for (const [key, item] of def.type.props.entries()) {
|
|
195
|
-
if (skipList.has(key)) continue;
|
|
200
|
+
if (skipList.has(key) || isPhantomType(item)) continue;
|
|
196
201
|
typeKeys.add(key);
|
|
197
202
|
if (value[key] === undefined) {
|
|
198
203
|
if (partialFunctionMatched || this.opts.partial === "deep" || this.opts.partial === true && this.stackPath.length <= 1) continue;
|
|
@@ -474,6 +479,9 @@ else if (!newBase) throw new Error(`"${typeName}" is not annotated type`);
|
|
|
474
479
|
};
|
|
475
480
|
return handle;
|
|
476
481
|
}
|
|
482
|
+
function isPhantomType(def) {
|
|
483
|
+
return def.type.kind === "" && def.type.designType === "phantom";
|
|
484
|
+
}
|
|
477
485
|
function isAnnotatedTypeOfPrimitive(t) {
|
|
478
486
|
if (["array", "object"].includes(t.type.kind)) return false;
|
|
479
487
|
if (!t.type.kind) return true;
|
|
@@ -494,10 +502,14 @@ function buildJsonSchema(type) {
|
|
|
494
502
|
const build = (def) => {
|
|
495
503
|
const meta = def.metadata;
|
|
496
504
|
return forAnnotatedType(def, {
|
|
505
|
+
phantom() {
|
|
506
|
+
return {};
|
|
507
|
+
},
|
|
497
508
|
object(d) {
|
|
498
509
|
const properties = {};
|
|
499
510
|
const required = [];
|
|
500
511
|
for (const [key, val] of d.type.props.entries()) {
|
|
512
|
+
if (isPhantomType(val)) continue;
|
|
501
513
|
properties[key] = build(val);
|
|
502
514
|
if (!val.optional) required.push(key);
|
|
503
515
|
}
|
|
@@ -670,6 +682,13 @@ function serializeNode(def, path, options) {
|
|
|
670
682
|
}
|
|
671
683
|
function serializeTypeDef(def, path, options) {
|
|
672
684
|
return forAnnotatedType(def, {
|
|
685
|
+
phantom(d) {
|
|
686
|
+
return {
|
|
687
|
+
kind: "",
|
|
688
|
+
designType: d.type.designType,
|
|
689
|
+
tags: Array.from(d.type.tags)
|
|
690
|
+
};
|
|
691
|
+
},
|
|
673
692
|
final(d) {
|
|
674
693
|
const result = {
|
|
675
694
|
kind: "",
|
|
@@ -681,7 +700,10 @@ function serializeTypeDef(def, path, options) {
|
|
|
681
700
|
},
|
|
682
701
|
object(d) {
|
|
683
702
|
const props = {};
|
|
684
|
-
for (const [key, val] of d.type.props.entries())
|
|
703
|
+
for (const [key, val] of d.type.props.entries()) {
|
|
704
|
+
if (isPhantomType(val)) continue;
|
|
705
|
+
props[key] = serializeNode(val, [...path, key], options);
|
|
706
|
+
}
|
|
685
707
|
const propsPatterns = d.type.propsPatterns.map((pp) => ({
|
|
686
708
|
pattern: {
|
|
687
709
|
source: pp.pattern.source,
|
|
@@ -807,4 +829,4 @@ function deserializeTypeDef(t) {
|
|
|
807
829
|
}
|
|
808
830
|
|
|
809
831
|
//#endregion
|
|
810
|
-
export { SERIALIZE_VERSION, Validator, ValidatorError, annotate, buildJsonSchema, defineAnnotatedType, deserializeAnnotatedType, forAnnotatedType, fromJsonSchema, isAnnotatedType, isAnnotatedTypeOfPrimitive, serializeAnnotatedType };
|
|
832
|
+
export { SERIALIZE_VERSION, Validator, ValidatorError, annotate, buildJsonSchema, defineAnnotatedType, deserializeAnnotatedType, forAnnotatedType, fromJsonSchema, isAnnotatedType, isAnnotatedTypeOfPrimitive, isPhantomType, serializeAnnotatedType };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atscript/typescript",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
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.5"
|
|
74
74
|
},
|
|
75
75
|
"dependencies": {
|
|
76
76
|
"@moostjs/event-cli": "^0.5.32",
|