@atscript/typescript 0.1.32 → 0.1.33

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/utils.mjs CHANGED
@@ -435,6 +435,25 @@ var ValidatorError = class extends Error {
435
435
 
436
436
  //#endregion
437
437
  //#region packages/typescript/src/annotated-type.ts
438
+ const COMPLEX_KINDS = new Set([
439
+ "union",
440
+ "intersection",
441
+ "tuple"
442
+ ]);
443
+ const NON_PRIMITIVE_KINDS = new Set(["array", "object"]);
444
+ /** Shared validator method reused by all annotated type nodes. */ function validatorMethod(opts) {
445
+ return new Validator(this, opts);
446
+ }
447
+ function createAnnotatedTypeNode(type, metadata, opts) {
448
+ return {
449
+ __is_atscript_annotated_type: true,
450
+ type,
451
+ metadata,
452
+ validator: validatorMethod,
453
+ id: opts?.id,
454
+ optional: opts?.optional
455
+ };
456
+ }
438
457
  function isAnnotatedType(type) {
439
458
  return type && type.__is_atscript_annotated_type;
440
459
  }
@@ -453,32 +472,22 @@ function cloneRefProp(parentType, propName) {
453
472
  const existing = objType.props.get(propName);
454
473
  if (!existing) return;
455
474
  const clonedType = cloneTypeDef(existing.type);
456
- objType.props.set(propName, {
457
- __is_atscript_annotated_type: true,
458
- type: clonedType,
459
- metadata: new Map(existing.metadata),
475
+ objType.props.set(propName, createAnnotatedTypeNode(clonedType, new Map(existing.metadata), {
460
476
  id: existing.id,
461
- optional: existing.optional,
462
- validator(opts) {
463
- return new Validator(this, opts);
464
- }
465
- });
477
+ optional: existing.optional
478
+ }));
466
479
  }
467
480
  function cloneTypeDef(type) {
468
481
  if (type.kind === "object") {
469
482
  const obj = type;
483
+ const props = new Map();
484
+ for (const [k, v] of obj.props) props.set(k, createAnnotatedTypeNode(v.type, new Map(v.metadata), {
485
+ id: v.id,
486
+ optional: v.optional
487
+ }));
470
488
  return {
471
489
  kind: "object",
472
- props: new Map(Array.from(obj.props.entries()).map(([k, v]) => [k, {
473
- __is_atscript_annotated_type: true,
474
- type: v.type,
475
- metadata: new Map(v.metadata),
476
- id: v.id,
477
- optional: v.optional,
478
- validator(opts) {
479
- return new Validator(this, opts);
480
- }
481
- }])),
490
+ props,
482
491
  propsPatterns: [...obj.propsPatterns],
483
492
  tags: new Set(obj.tags)
484
493
  };
@@ -508,38 +517,24 @@ function defineAnnotatedType(_kind, base) {
508
517
  const kind = _kind || "";
509
518
  const type = base?.type || {};
510
519
  type.kind = kind;
511
- if ([
512
- "union",
513
- "intersection",
514
- "tuple"
515
- ].includes(kind)) type.items = [];
520
+ if (COMPLEX_KINDS.has(kind)) type.items = [];
516
521
  if (kind === "object") {
517
522
  type.props = new Map();
518
523
  type.propsPatterns = [];
519
524
  }
520
525
  type.tags = new Set();
521
526
  const metadata = base?.metadata || new Map();
522
- if (base) Object.assign(base, {
523
- __is_atscript_annotated_type: true,
524
- metadata,
525
- type,
526
- validator(opts) {
527
- return new Validator(this, opts);
528
- }
529
- });
530
- else base = {
527
+ const payload = {
531
528
  __is_atscript_annotated_type: true,
532
529
  metadata,
533
530
  type,
534
- validator(opts) {
535
- return new Validator(this, opts);
536
- }
531
+ validator: validatorMethod
537
532
  };
533
+ base = base ? Object.assign(base, payload) : payload;
538
534
  const handle = {
539
535
  $type: base,
540
536
  $def: type,
541
537
  $metadata: metadata,
542
- _existingObject: undefined,
543
538
  tags(...tags) {
544
539
  for (const tag of tags) this.$def.tags.add(tag);
545
540
  return this;
@@ -580,27 +575,18 @@ else base = {
580
575
  return this;
581
576
  },
582
577
  refTo(type$1, chain) {
578
+ if (!isAnnotatedType(type$1)) throw new Error(`${type$1} is not annotated type`);
583
579
  let newBase = type$1;
584
580
  const typeName = type$1.name || "Unknown";
585
- if (isAnnotatedType(newBase)) {
586
- let keys = "";
587
- for (const c of chain || []) {
588
- keys += `["${c}"]`;
589
- if (newBase.type.kind === "object" && newBase.type.props.has(c)) newBase = newBase.type.props.get(c);
590
- else throw new Error(`Can't find prop ${typeName}${keys}`);
581
+ if (chain) for (let i = 0; i < chain.length; i++) {
582
+ const c = chain[i];
583
+ if (newBase.type.kind === "object" && newBase.type.props.has(c)) newBase = newBase.type.props.get(c);
584
+ else {
585
+ const keys = chain.slice(0, i + 1).map((k) => `["${k}"]`).join("");
586
+ throw new Error(`Can't find prop ${typeName}${keys}`);
591
587
  }
592
- if (!newBase && keys) throw new Error(`Can't find prop ${typeName}${keys}`);
593
- else if (!newBase) throw new Error(`"${typeName}" is not annotated type`);
594
- this.$type = {
595
- __is_atscript_annotated_type: true,
596
- type: newBase.type,
597
- metadata,
598
- id: newBase.id,
599
- validator(opts) {
600
- return new Validator(this, opts);
601
- }
602
- };
603
- } else throw new Error(`${type$1} is not annotated type`);
588
+ }
589
+ this.$type = createAnnotatedTypeNode(newBase.type, metadata, { id: newBase.id });
604
590
  return this;
605
591
  },
606
592
  annotate(key, value, asArray) {
@@ -618,13 +604,9 @@ function isPhantomType(def) {
618
604
  return def.type.kind === "" && def.type.designType === "phantom";
619
605
  }
620
606
  function isAnnotatedTypeOfPrimitive(t) {
621
- if (["array", "object"].includes(t.type.kind)) return false;
607
+ if (NON_PRIMITIVE_KINDS.has(t.type.kind)) return false;
622
608
  if (!t.type.kind) return true;
623
- if ([
624
- "union",
625
- "tuple",
626
- "intersection"
627
- ].includes(t.type.kind)) {
609
+ if (COMPLEX_KINDS.has(t.type.kind)) {
628
610
  for (const item of t.type.items) if (!isAnnotatedTypeOfPrimitive(item)) return false;
629
611
  return true;
630
612
  }
@@ -663,10 +645,10 @@ function forAnnotatedType(def, handlers) {
663
645
  const firstObj = items[0].type;
664
646
  const candidates = [];
665
647
  for (const [propName, propType] of firstObj.props.entries()) if (propType.type.kind === "" && propType.type.value !== undefined) candidates.push(propName);
666
- const validCandidates = [];
648
+ let result = null;
667
649
  for (const candidate of candidates) {
668
650
  const values = new Set();
669
- const mapping = {};
651
+ const indexMapping = {};
670
652
  let valid = true;
671
653
  for (let i = 0; i < items.length; i++) {
672
654
  const obj = items[i].type;
@@ -681,19 +663,21 @@ function forAnnotatedType(def, handlers) {
681
663
  break;
682
664
  }
683
665
  values.add(val);
684
- mapping[String(val)] = `#/oneOf/${i}`;
666
+ indexMapping[String(val)] = i;
667
+ }
668
+ if (valid) {
669
+ if (result) return null;
670
+ result = {
671
+ propertyName: candidate,
672
+ indexMapping
673
+ };
685
674
  }
686
- if (valid) validCandidates.push({
687
- propertyName: candidate,
688
- mapping
689
- });
690
675
  }
691
- if (validCandidates.length === 1) return validCandidates[0];
692
- return null;
676
+ return result;
693
677
  }
694
678
  function buildJsonSchema(type) {
695
679
  const defs = {};
696
- let isRoot = true;
680
+ let hasDefs = false;
697
681
  const buildObject = (d) => {
698
682
  const properties = {};
699
683
  const required = [];
@@ -710,15 +694,15 @@ function buildJsonSchema(type) {
710
694
  return schema$1;
711
695
  };
712
696
  const build$1 = (def) => {
713
- if (def.id && def.type.kind === "object" && !isRoot) {
697
+ if (def.id && def.type.kind === "object" && def !== type) {
714
698
  const name = def.id;
715
699
  if (!defs[name]) {
700
+ hasDefs = true;
716
701
  defs[name] = {};
717
702
  defs[name] = buildObject(def);
718
703
  }
719
704
  return { $ref: `#/$defs/${name}` };
720
705
  }
721
- isRoot = false;
722
706
  const meta = def.metadata;
723
707
  return forAnnotatedType(def, {
724
708
  phantom() {
@@ -743,11 +727,9 @@ function buildJsonSchema(type) {
743
727
  if (disc) {
744
728
  const oneOf = d.type.items.map(build$1);
745
729
  const mapping = {};
746
- for (const [val, origPath] of Object.entries(disc.mapping)) {
747
- const idx = Number.parseInt(origPath.split("/").pop(), 10);
730
+ for (const [val, idx] of Object.entries(disc.indexMapping)) {
748
731
  const item = d.type.items[idx];
749
- if (item.id && defs[item.id]) mapping[val] = `#/$defs/${item.id}`;
750
- else mapping[val] = origPath;
732
+ mapping[val] = item.id && defs[item.id] ? `#/$defs/${item.id}` : `#/oneOf/${idx}`;
751
733
  }
752
734
  return {
753
735
  oneOf,
@@ -797,7 +779,7 @@ else schema$1.allOf = (schema$1.allOf || []).concat(patterns.map((p) => ({ patte
797
779
  });
798
780
  };
799
781
  const schema = build$1(type);
800
- if (Object.keys(defs).length > 0) return {
782
+ if (hasDefs) return {
801
783
  ...schema,
802
784
  $defs: defs
803
785
  };
@@ -812,6 +794,8 @@ function fromJsonSchema(schema) {
812
794
  const refName = s.$ref.replace(/^#\/(\$defs|definitions)\//, "");
813
795
  if (resolved.has(refName)) return resolved.get(refName);
814
796
  if (defsSource[refName]) {
797
+ const placeholder = defineAnnotatedType().designType("any").$type;
798
+ resolved.set(refName, placeholder);
815
799
  const type = convert(defsSource[refName]);
816
800
  resolved.set(refName, type);
817
801
  return type;
@@ -1222,16 +1206,10 @@ function deserializeAnnotatedType(data) {
1222
1206
  function deserializeNode(data) {
1223
1207
  const metadata = new Map(Object.entries(data.metadata));
1224
1208
  const type = deserializeTypeDef(data.type);
1225
- const result = {
1226
- __is_atscript_annotated_type: true,
1227
- type,
1228
- metadata,
1229
- validator(opts) {
1230
- return new Validator(this, opts);
1231
- }
1232
- };
1233
- if (data.optional) result.optional = true;
1234
- if (data.id) result.id = data.id;
1209
+ const result = createAnnotatedTypeNode(type, metadata, {
1210
+ optional: data.optional || undefined,
1211
+ id: data.id || undefined
1212
+ });
1235
1213
  return result;
1236
1214
  }
1237
1215
  function deserializeTypeDef(t) {
@@ -1277,4 +1255,4 @@ function deserializeTypeDef(t) {
1277
1255
  }
1278
1256
 
1279
1257
  //#endregion
1280
- export { SERIALIZE_VERSION, Validator, ValidatorError, annotate, buildJsonSchema, cloneRefProp, createDataFromAnnotatedType, defineAnnotatedType, deserializeAnnotatedType, flattenAnnotatedType, forAnnotatedType, fromJsonSchema, isAnnotatedType, isAnnotatedTypeOfPrimitive, isPhantomType, mergeJsonSchemas, serializeAnnotatedType, throwFeatureDisabled };
1258
+ export { SERIALIZE_VERSION, Validator, ValidatorError, annotate, buildJsonSchema, cloneRefProp, createAnnotatedTypeNode, createDataFromAnnotatedType, defineAnnotatedType, deserializeAnnotatedType, flattenAnnotatedType, forAnnotatedType, fromJsonSchema, isAnnotatedType, isAnnotatedTypeOfPrimitive, isPhantomType, mergeJsonSchemas, serializeAnnotatedType, throwFeatureDisabled };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atscript/typescript",
3
- "version": "0.1.32",
3
+ "version": "0.1.33",
4
4
  "description": "Atscript: typescript-gen support.",
5
5
  "keywords": [
6
6
  "annotations",
@@ -64,7 +64,7 @@
64
64
  "vitest": "3.2.4"
65
65
  },
66
66
  "peerDependencies": {
67
- "@atscript/core": "^0.1.32"
67
+ "@atscript/core": "^0.1.33"
68
68
  },
69
69
  "build": [
70
70
  {},