@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/index.mjs CHANGED
@@ -455,28 +455,72 @@ else {
455
455
  *
456
456
  * - **Single PK** (one `@meta.id`) → `static __pk: <scalar type>`
457
457
  * - **Compound PK** (multiple `@meta.id`) → `static __pk: { field1: Type1; field2: Type2 }`
458
- * - **No PK** → no `__pk` emitted
458
+ * - **No PK** → no `__pk` emitted (unless unique indexes exist)
459
+ * - **Unique indexes** (`@db.index.unique`) → appended as union members
460
+ * - **Mongo collection** → always includes `string` (ObjectId) in the union;
461
+ * if no `@meta.id` fields, `__pk` is just `string`
459
462
  */ renderPk(node) {
463
+ const isMongoCollection = !!node.annotations?.some((a) => a.name === "db.mongo.collection");
460
464
  let struct;
461
465
  if (node.hasExtends) struct = this.doc.resolveInterfaceExtends(node);
462
466
  if (!struct) struct = node.getDefinition();
463
467
  if (!struct || !isStructure(struct)) return;
468
+ const structNode = struct;
464
469
  const pkProps = [];
465
- for (const [name, prop] of struct.props) {
470
+ const uniqueByIndex = new Map();
471
+ for (const [name, prop] of structNode.props) {
466
472
  if (prop.token("identifier")?.pattern) continue;
473
+ if (isMongoCollection && name === "_id") continue;
467
474
  if (prop.countAnnotations("meta.id") > 0) pkProps.push({
468
475
  name,
469
476
  prop
470
477
  });
478
+ if (prop.annotations) {
479
+ for (const ann of prop.annotations) if (ann.name === "db.index.unique") {
480
+ const indexName = ann.args[0]?.text ?? name;
481
+ let group = uniqueByIndex.get(indexName);
482
+ if (!group) {
483
+ group = [];
484
+ uniqueByIndex.set(indexName, group);
485
+ }
486
+ group.push({
487
+ name,
488
+ prop
489
+ });
490
+ }
491
+ }
492
+ }
493
+ const uniqueProps = [];
494
+ const pkNames = new Set(pkProps.map((p) => p.name));
495
+ for (const fields of uniqueByIndex.values()) if (fields.length === 1 && !pkNames.has(fields[0].name)) uniqueProps.push(fields[0]);
496
+ if (pkProps.length === 0 && uniqueProps.length === 0 && !isMongoCollection) return;
497
+ let mongoIdType;
498
+ if (isMongoCollection) {
499
+ const idProp = structNode.props.get("_id");
500
+ if (idProp) mongoIdType = this.renderTypeDefString(idProp.getDefinition()).trim();
501
+ mongoIdType ?? (mongoIdType = "string");
502
+ }
503
+ const uniqueTypes = [];
504
+ const seenTypes = new Set();
505
+ for (const { prop } of uniqueProps) {
506
+ const rendered = this.renderTypeDefString(prop.getDefinition()).trim();
507
+ if (!seenTypes.has(rendered)) {
508
+ seenTypes.add(rendered);
509
+ uniqueTypes.push(rendered);
510
+ }
471
511
  }
472
- if (pkProps.length === 0) return;
473
512
  this.writeln();
474
- if (pkProps.length === 1) {
513
+ const uniqueSuffix = uniqueTypes.length > 0 ? ` | ${uniqueTypes.join(" | ")}` : "";
514
+ if (pkProps.length === 0 && !isMongoCollection) this.writeln(`static __pk: ${uniqueTypes.join(" | ")}`);
515
+ else if (pkProps.length === 0) this.writeln(`static __pk: ${mongoIdType}${uniqueSuffix}`);
516
+ else if (pkProps.length === 1) {
475
517
  this.write("static __pk: ");
476
- const renderedDef = this.renderTypeDefString(pkProps[0].prop.getDefinition());
477
- renderedDef.split("\n").forEach((l) => this.writeln(l));
518
+ if (isMongoCollection) this.write(`${mongoIdType} | `);
519
+ const renderedDef = this.renderTypeDefString(pkProps[0].prop.getDefinition()).trim();
520
+ this.writeln(`${renderedDef}${uniqueSuffix}`);
478
521
  } else {
479
522
  this.write("static __pk: ");
523
+ if (isMongoCollection) this.write(`${mongoIdType} | `);
480
524
  this.blockln("{}");
481
525
  for (const { name, prop } of pkProps) {
482
526
  this.write(wrapProp(name), ": ");
@@ -484,6 +528,7 @@ else {
484
528
  renderedDef.split("\n").forEach((l) => this.writeln(l));
485
529
  }
486
530
  this.pop();
531
+ this.writeln(uniqueSuffix);
487
532
  }
488
533
  }
489
534
  phantomPropType(def) {
@@ -971,6 +1016,24 @@ var ValidatorError = class extends Error {
971
1016
 
972
1017
  //#endregion
973
1018
  //#region packages/typescript/src/annotated-type.ts
1019
+ const COMPLEX_KINDS = new Set([
1020
+ "union",
1021
+ "intersection",
1022
+ "tuple"
1023
+ ]);
1024
+ /** Shared validator method reused by all annotated type nodes. */ function validatorMethod(opts) {
1025
+ return new Validator(this, opts);
1026
+ }
1027
+ function createAnnotatedTypeNode(type, metadata, opts) {
1028
+ return {
1029
+ __is_atscript_annotated_type: true,
1030
+ type,
1031
+ metadata,
1032
+ validator: validatorMethod,
1033
+ id: opts?.id,
1034
+ optional: opts?.optional
1035
+ };
1036
+ }
974
1037
  function isAnnotatedType(type) {
975
1038
  return type && type.__is_atscript_annotated_type;
976
1039
  }
@@ -987,38 +1050,24 @@ function defineAnnotatedType(_kind, base) {
987
1050
  const kind = _kind || "";
988
1051
  const type = base?.type || {};
989
1052
  type.kind = kind;
990
- if ([
991
- "union",
992
- "intersection",
993
- "tuple"
994
- ].includes(kind)) type.items = [];
1053
+ if (COMPLEX_KINDS.has(kind)) type.items = [];
995
1054
  if (kind === "object") {
996
1055
  type.props = new Map();
997
1056
  type.propsPatterns = [];
998
1057
  }
999
1058
  type.tags = new Set();
1000
1059
  const metadata = base?.metadata || new Map();
1001
- if (base) Object.assign(base, {
1060
+ const payload = {
1002
1061
  __is_atscript_annotated_type: true,
1003
1062
  metadata,
1004
1063
  type,
1005
- validator(opts) {
1006
- return new Validator(this, opts);
1007
- }
1008
- });
1009
- else base = {
1010
- __is_atscript_annotated_type: true,
1011
- metadata,
1012
- type,
1013
- validator(opts) {
1014
- return new Validator(this, opts);
1015
- }
1064
+ validator: validatorMethod
1016
1065
  };
1066
+ base = base ? Object.assign(base, payload) : payload;
1017
1067
  const handle = {
1018
1068
  $type: base,
1019
1069
  $def: type,
1020
1070
  $metadata: metadata,
1021
- _existingObject: undefined,
1022
1071
  tags(...tags) {
1023
1072
  for (const tag of tags) this.$def.tags.add(tag);
1024
1073
  return this;
@@ -1059,27 +1108,18 @@ else base = {
1059
1108
  return this;
1060
1109
  },
1061
1110
  refTo(type$1, chain) {
1111
+ if (!isAnnotatedType(type$1)) throw new Error(`${type$1} is not annotated type`);
1062
1112
  let newBase = type$1;
1063
1113
  const typeName = type$1.name || "Unknown";
1064
- if (isAnnotatedType(newBase)) {
1065
- let keys = "";
1066
- for (const c of chain || []) {
1067
- keys += `["${c}"]`;
1068
- if (newBase.type.kind === "object" && newBase.type.props.has(c)) newBase = newBase.type.props.get(c);
1069
- else throw new Error(`Can't find prop ${typeName}${keys}`);
1114
+ if (chain) for (let i = 0; i < chain.length; i++) {
1115
+ const c = chain[i];
1116
+ if (newBase.type.kind === "object" && newBase.type.props.has(c)) newBase = newBase.type.props.get(c);
1117
+ else {
1118
+ const keys = chain.slice(0, i + 1).map((k) => `["${k}"]`).join("");
1119
+ throw new Error(`Can't find prop ${typeName}${keys}`);
1070
1120
  }
1071
- if (!newBase && keys) throw new Error(`Can't find prop ${typeName}${keys}`);
1072
- else if (!newBase) throw new Error(`"${typeName}" is not annotated type`);
1073
- this.$type = {
1074
- __is_atscript_annotated_type: true,
1075
- type: newBase.type,
1076
- metadata,
1077
- id: newBase.id,
1078
- validator(opts) {
1079
- return new Validator(this, opts);
1080
- }
1081
- };
1082
- } else throw new Error(`${type$1} is not annotated type`);
1121
+ }
1122
+ this.$type = createAnnotatedTypeNode(newBase.type, metadata, { id: newBase.id });
1083
1123
  return this;
1084
1124
  },
1085
1125
  annotate(key, value, asArray) {
@@ -1129,10 +1169,10 @@ function forAnnotatedType(def, handlers) {
1129
1169
  const firstObj = items[0].type;
1130
1170
  const candidates = [];
1131
1171
  for (const [propName, propType] of firstObj.props.entries()) if (propType.type.kind === "" && propType.type.value !== undefined) candidates.push(propName);
1132
- const validCandidates = [];
1172
+ let result = null;
1133
1173
  for (const candidate of candidates) {
1134
1174
  const values = new Set();
1135
- const mapping = {};
1175
+ const indexMapping = {};
1136
1176
  let valid = true;
1137
1177
  for (let i = 0; i < items.length; i++) {
1138
1178
  const obj = items[i].type;
@@ -1147,19 +1187,21 @@ function forAnnotatedType(def, handlers) {
1147
1187
  break;
1148
1188
  }
1149
1189
  values.add(val);
1150
- mapping[String(val)] = `#/oneOf/${i}`;
1190
+ indexMapping[String(val)] = i;
1191
+ }
1192
+ if (valid) {
1193
+ if (result) return null;
1194
+ result = {
1195
+ propertyName: candidate,
1196
+ indexMapping
1197
+ };
1151
1198
  }
1152
- if (valid) validCandidates.push({
1153
- propertyName: candidate,
1154
- mapping
1155
- });
1156
1199
  }
1157
- if (validCandidates.length === 1) return validCandidates[0];
1158
- return null;
1200
+ return result;
1159
1201
  }
1160
1202
  function buildJsonSchema(type) {
1161
1203
  const defs = {};
1162
- let isRoot = true;
1204
+ let hasDefs = false;
1163
1205
  const buildObject = (d) => {
1164
1206
  const properties = {};
1165
1207
  const required = [];
@@ -1176,15 +1218,15 @@ function buildJsonSchema(type) {
1176
1218
  return schema$1;
1177
1219
  };
1178
1220
  const build = (def) => {
1179
- if (def.id && def.type.kind === "object" && !isRoot) {
1221
+ if (def.id && def.type.kind === "object" && def !== type) {
1180
1222
  const name = def.id;
1181
1223
  if (!defs[name]) {
1224
+ hasDefs = true;
1182
1225
  defs[name] = {};
1183
1226
  defs[name] = buildObject(def);
1184
1227
  }
1185
1228
  return { $ref: `#/$defs/${name}` };
1186
1229
  }
1187
- isRoot = false;
1188
1230
  const meta = def.metadata;
1189
1231
  return forAnnotatedType(def, {
1190
1232
  phantom() {
@@ -1209,11 +1251,9 @@ function buildJsonSchema(type) {
1209
1251
  if (disc) {
1210
1252
  const oneOf = d.type.items.map(build);
1211
1253
  const mapping = {};
1212
- for (const [val, origPath] of Object.entries(disc.mapping)) {
1213
- const idx = Number.parseInt(origPath.split("/").pop(), 10);
1254
+ for (const [val, idx] of Object.entries(disc.indexMapping)) {
1214
1255
  const item = d.type.items[idx];
1215
- if (item.id && defs[item.id]) mapping[val] = `#/$defs/${item.id}`;
1216
- else mapping[val] = origPath;
1256
+ mapping[val] = item.id && defs[item.id] ? `#/$defs/${item.id}` : `#/oneOf/${idx}`;
1217
1257
  }
1218
1258
  return {
1219
1259
  oneOf,
@@ -1263,7 +1303,7 @@ else schema$1.allOf = (schema$1.allOf || []).concat(patterns.map((p) => ({ patte
1263
1303
  });
1264
1304
  };
1265
1305
  const schema = build(type);
1266
- if (Object.keys(defs).length > 0) return {
1306
+ if (hasDefs) return {
1267
1307
  ...schema,
1268
1308
  $defs: defs
1269
1309
  };
package/dist/utils.cjs CHANGED
@@ -436,6 +436,25 @@ var ValidatorError = class extends Error {
436
436
 
437
437
  //#endregion
438
438
  //#region packages/typescript/src/annotated-type.ts
439
+ const COMPLEX_KINDS = new Set([
440
+ "union",
441
+ "intersection",
442
+ "tuple"
443
+ ]);
444
+ const NON_PRIMITIVE_KINDS = new Set(["array", "object"]);
445
+ /** Shared validator method reused by all annotated type nodes. */ function validatorMethod(opts) {
446
+ return new Validator(this, opts);
447
+ }
448
+ function createAnnotatedTypeNode(type, metadata, opts) {
449
+ return {
450
+ __is_atscript_annotated_type: true,
451
+ type,
452
+ metadata,
453
+ validator: validatorMethod,
454
+ id: opts?.id,
455
+ optional: opts?.optional
456
+ };
457
+ }
439
458
  function isAnnotatedType(type) {
440
459
  return type && type.__is_atscript_annotated_type;
441
460
  }
@@ -454,32 +473,22 @@ function cloneRefProp(parentType, propName) {
454
473
  const existing = objType.props.get(propName);
455
474
  if (!existing) return;
456
475
  const clonedType = cloneTypeDef(existing.type);
457
- objType.props.set(propName, {
458
- __is_atscript_annotated_type: true,
459
- type: clonedType,
460
- metadata: new Map(existing.metadata),
476
+ objType.props.set(propName, createAnnotatedTypeNode(clonedType, new Map(existing.metadata), {
461
477
  id: existing.id,
462
- optional: existing.optional,
463
- validator(opts) {
464
- return new Validator(this, opts);
465
- }
466
- });
478
+ optional: existing.optional
479
+ }));
467
480
  }
468
481
  function cloneTypeDef(type) {
469
482
  if (type.kind === "object") {
470
483
  const obj = type;
484
+ const props = new Map();
485
+ for (const [k, v] of obj.props) props.set(k, createAnnotatedTypeNode(v.type, new Map(v.metadata), {
486
+ id: v.id,
487
+ optional: v.optional
488
+ }));
471
489
  return {
472
490
  kind: "object",
473
- props: new Map(Array.from(obj.props.entries()).map(([k, v]) => [k, {
474
- __is_atscript_annotated_type: true,
475
- type: v.type,
476
- metadata: new Map(v.metadata),
477
- id: v.id,
478
- optional: v.optional,
479
- validator(opts) {
480
- return new Validator(this, opts);
481
- }
482
- }])),
491
+ props,
483
492
  propsPatterns: [...obj.propsPatterns],
484
493
  tags: new Set(obj.tags)
485
494
  };
@@ -509,38 +518,24 @@ function defineAnnotatedType(_kind, base) {
509
518
  const kind = _kind || "";
510
519
  const type = base?.type || {};
511
520
  type.kind = kind;
512
- if ([
513
- "union",
514
- "intersection",
515
- "tuple"
516
- ].includes(kind)) type.items = [];
521
+ if (COMPLEX_KINDS.has(kind)) type.items = [];
517
522
  if (kind === "object") {
518
523
  type.props = new Map();
519
524
  type.propsPatterns = [];
520
525
  }
521
526
  type.tags = new Set();
522
527
  const metadata = base?.metadata || new Map();
523
- if (base) Object.assign(base, {
524
- __is_atscript_annotated_type: true,
525
- metadata,
526
- type,
527
- validator(opts) {
528
- return new Validator(this, opts);
529
- }
530
- });
531
- else base = {
528
+ const payload = {
532
529
  __is_atscript_annotated_type: true,
533
530
  metadata,
534
531
  type,
535
- validator(opts) {
536
- return new Validator(this, opts);
537
- }
532
+ validator: validatorMethod
538
533
  };
534
+ base = base ? Object.assign(base, payload) : payload;
539
535
  const handle = {
540
536
  $type: base,
541
537
  $def: type,
542
538
  $metadata: metadata,
543
- _existingObject: undefined,
544
539
  tags(...tags) {
545
540
  for (const tag of tags) this.$def.tags.add(tag);
546
541
  return this;
@@ -581,27 +576,18 @@ else base = {
581
576
  return this;
582
577
  },
583
578
  refTo(type$1, chain) {
579
+ if (!isAnnotatedType(type$1)) throw new Error(`${type$1} is not annotated type`);
584
580
  let newBase = type$1;
585
581
  const typeName = type$1.name || "Unknown";
586
- if (isAnnotatedType(newBase)) {
587
- let keys = "";
588
- for (const c of chain || []) {
589
- keys += `["${c}"]`;
590
- if (newBase.type.kind === "object" && newBase.type.props.has(c)) newBase = newBase.type.props.get(c);
591
- else throw new Error(`Can't find prop ${typeName}${keys}`);
582
+ if (chain) for (let i = 0; i < chain.length; i++) {
583
+ const c = chain[i];
584
+ if (newBase.type.kind === "object" && newBase.type.props.has(c)) newBase = newBase.type.props.get(c);
585
+ else {
586
+ const keys = chain.slice(0, i + 1).map((k) => `["${k}"]`).join("");
587
+ throw new Error(`Can't find prop ${typeName}${keys}`);
592
588
  }
593
- if (!newBase && keys) throw new Error(`Can't find prop ${typeName}${keys}`);
594
- else if (!newBase) throw new Error(`"${typeName}" is not annotated type`);
595
- this.$type = {
596
- __is_atscript_annotated_type: true,
597
- type: newBase.type,
598
- metadata,
599
- id: newBase.id,
600
- validator(opts) {
601
- return new Validator(this, opts);
602
- }
603
- };
604
- } else throw new Error(`${type$1} is not annotated type`);
589
+ }
590
+ this.$type = createAnnotatedTypeNode(newBase.type, metadata, { id: newBase.id });
605
591
  return this;
606
592
  },
607
593
  annotate(key, value, asArray) {
@@ -619,13 +605,9 @@ function isPhantomType(def) {
619
605
  return def.type.kind === "" && def.type.designType === "phantom";
620
606
  }
621
607
  function isAnnotatedTypeOfPrimitive(t) {
622
- if (["array", "object"].includes(t.type.kind)) return false;
608
+ if (NON_PRIMITIVE_KINDS.has(t.type.kind)) return false;
623
609
  if (!t.type.kind) return true;
624
- if ([
625
- "union",
626
- "tuple",
627
- "intersection"
628
- ].includes(t.type.kind)) {
610
+ if (COMPLEX_KINDS.has(t.type.kind)) {
629
611
  for (const item of t.type.items) if (!isAnnotatedTypeOfPrimitive(item)) return false;
630
612
  return true;
631
613
  }
@@ -664,10 +646,10 @@ function forAnnotatedType(def, handlers) {
664
646
  const firstObj = items[0].type;
665
647
  const candidates = [];
666
648
  for (const [propName, propType] of firstObj.props.entries()) if (propType.type.kind === "" && propType.type.value !== undefined) candidates.push(propName);
667
- const validCandidates = [];
649
+ let result = null;
668
650
  for (const candidate of candidates) {
669
651
  const values = new Set();
670
- const mapping = {};
652
+ const indexMapping = {};
671
653
  let valid = true;
672
654
  for (let i = 0; i < items.length; i++) {
673
655
  const obj = items[i].type;
@@ -682,19 +664,21 @@ function forAnnotatedType(def, handlers) {
682
664
  break;
683
665
  }
684
666
  values.add(val);
685
- mapping[String(val)] = `#/oneOf/${i}`;
667
+ indexMapping[String(val)] = i;
668
+ }
669
+ if (valid) {
670
+ if (result) return null;
671
+ result = {
672
+ propertyName: candidate,
673
+ indexMapping
674
+ };
686
675
  }
687
- if (valid) validCandidates.push({
688
- propertyName: candidate,
689
- mapping
690
- });
691
676
  }
692
- if (validCandidates.length === 1) return validCandidates[0];
693
- return null;
677
+ return result;
694
678
  }
695
679
  function buildJsonSchema(type) {
696
680
  const defs = {};
697
- let isRoot = true;
681
+ let hasDefs = false;
698
682
  const buildObject = (d) => {
699
683
  const properties = {};
700
684
  const required = [];
@@ -711,15 +695,15 @@ function buildJsonSchema(type) {
711
695
  return schema$1;
712
696
  };
713
697
  const build$1 = (def) => {
714
- if (def.id && def.type.kind === "object" && !isRoot) {
698
+ if (def.id && def.type.kind === "object" && def !== type) {
715
699
  const name = def.id;
716
700
  if (!defs[name]) {
701
+ hasDefs = true;
717
702
  defs[name] = {};
718
703
  defs[name] = buildObject(def);
719
704
  }
720
705
  return { $ref: `#/$defs/${name}` };
721
706
  }
722
- isRoot = false;
723
707
  const meta = def.metadata;
724
708
  return forAnnotatedType(def, {
725
709
  phantom() {
@@ -744,11 +728,9 @@ function buildJsonSchema(type) {
744
728
  if (disc) {
745
729
  const oneOf = d.type.items.map(build$1);
746
730
  const mapping = {};
747
- for (const [val, origPath] of Object.entries(disc.mapping)) {
748
- const idx = Number.parseInt(origPath.split("/").pop(), 10);
731
+ for (const [val, idx] of Object.entries(disc.indexMapping)) {
749
732
  const item = d.type.items[idx];
750
- if (item.id && defs[item.id]) mapping[val] = `#/$defs/${item.id}`;
751
- else mapping[val] = origPath;
733
+ mapping[val] = item.id && defs[item.id] ? `#/$defs/${item.id}` : `#/oneOf/${idx}`;
752
734
  }
753
735
  return {
754
736
  oneOf,
@@ -798,7 +780,7 @@ else schema$1.allOf = (schema$1.allOf || []).concat(patterns.map((p) => ({ patte
798
780
  });
799
781
  };
800
782
  const schema = build$1(type);
801
- if (Object.keys(defs).length > 0) return {
783
+ if (hasDefs) return {
802
784
  ...schema,
803
785
  $defs: defs
804
786
  };
@@ -813,6 +795,8 @@ function fromJsonSchema(schema) {
813
795
  const refName = s.$ref.replace(/^#\/(\$defs|definitions)\//, "");
814
796
  if (resolved.has(refName)) return resolved.get(refName);
815
797
  if (defsSource[refName]) {
798
+ const placeholder = defineAnnotatedType().designType("any").$type;
799
+ resolved.set(refName, placeholder);
816
800
  const type = convert(defsSource[refName]);
817
801
  resolved.set(refName, type);
818
802
  return type;
@@ -1223,16 +1207,10 @@ function deserializeAnnotatedType(data) {
1223
1207
  function deserializeNode(data) {
1224
1208
  const metadata = new Map(Object.entries(data.metadata));
1225
1209
  const type = deserializeTypeDef(data.type);
1226
- const result = {
1227
- __is_atscript_annotated_type: true,
1228
- type,
1229
- metadata,
1230
- validator(opts) {
1231
- return new Validator(this, opts);
1232
- }
1233
- };
1234
- if (data.optional) result.optional = true;
1235
- if (data.id) result.id = data.id;
1210
+ const result = createAnnotatedTypeNode(type, metadata, {
1211
+ optional: data.optional || undefined,
1212
+ id: data.id || undefined
1213
+ });
1236
1214
  return result;
1237
1215
  }
1238
1216
  function deserializeTypeDef(t) {
@@ -1284,6 +1262,7 @@ exports.ValidatorError = ValidatorError
1284
1262
  exports.annotate = annotate
1285
1263
  exports.buildJsonSchema = buildJsonSchema
1286
1264
  exports.cloneRefProp = cloneRefProp
1265
+ exports.createAnnotatedTypeNode = createAnnotatedTypeNode
1287
1266
  exports.createDataFromAnnotatedType = createDataFromAnnotatedType
1288
1267
  exports.defineAnnotatedType = defineAnnotatedType
1289
1268
  exports.deserializeAnnotatedType = deserializeAnnotatedType
package/dist/utils.d.ts CHANGED
@@ -96,6 +96,14 @@ declare class ValidatorError extends Error {
96
96
  constructor(errors: TError[]);
97
97
  }
98
98
 
99
+ /**
100
+ * Creates a minimal annotated type node from a type def and metadata map.
101
+ * Centralises the shape so callers never duplicate the boilerplate.
102
+ */
103
+ declare function createAnnotatedTypeNode(type: TAtscriptTypeDef, metadata: TMetadataMap<AtscriptMetadata>, opts?: {
104
+ id?: string;
105
+ optional?: boolean;
106
+ }): TAtscriptAnnotatedType;
99
107
  /** Type definition for union, intersection, or tuple types. */
100
108
  interface TAtscriptTypeComplex<DataType = unknown> {
101
109
  kind: 'union' | 'intersection' | 'tuple';
@@ -235,7 +243,6 @@ interface TAnnotatedTypeHandle {
235
243
  kind: TKind;
236
244
  } & Omit<TAtscriptTypeComplex, 'kind'> & Omit<TAtscriptTypeFinal, 'kind'> & Omit<TAtscriptTypeArray, 'kind'> & Omit<TAtscriptTypeObject<string>, 'kind'>;
237
245
  $metadata: TMetadataMap<AtscriptMetadata>;
238
- _existingObject: TAtscriptAnnotatedType | undefined;
239
246
  tags(...tags: string[]): TAnnotatedTypeHandle;
240
247
  designType(value: TAtscriptTypeFinal['designType']): TAnnotatedTypeHandle;
241
248
  value(value: string | number | boolean): TAnnotatedTypeHandle;
@@ -559,5 +566,5 @@ type PrimaryKeyOf<T> = T extends {
559
566
  __pk: infer PK;
560
567
  } ? PK : unknown;
561
568
 
562
- export { SERIALIZE_VERSION, Validator, ValidatorError, annotate, buildJsonSchema, cloneRefProp, createDataFromAnnotatedType, defineAnnotatedType, deserializeAnnotatedType, flattenAnnotatedType, forAnnotatedType, fromJsonSchema, isAnnotatedType, isAnnotatedTypeOfPrimitive, isPhantomType, mergeJsonSchemas, serializeAnnotatedType, throwFeatureDisabled };
569
+ export { SERIALIZE_VERSION, Validator, ValidatorError, annotate, buildJsonSchema, cloneRefProp, createAnnotatedTypeNode, createDataFromAnnotatedType, defineAnnotatedType, deserializeAnnotatedType, flattenAnnotatedType, forAnnotatedType, fromJsonSchema, isAnnotatedType, isAnnotatedTypeOfPrimitive, isPhantomType, mergeJsonSchemas, serializeAnnotatedType, throwFeatureDisabled };
563
570
  export type { FlatOf, InferDataType, PrimaryKeyOf, TAnnotatedTypeHandle, TAtscriptAnnotatedType, TAtscriptAnnotatedTypeConstructor, TAtscriptDataType, TAtscriptTypeArray, TAtscriptTypeComplex, TAtscriptTypeDef, TAtscriptTypeFinal, TAtscriptTypeObject, TCreateDataOptions, TFlattenOptions, TJsonSchema, TMetadataMap, TProcessAnnotationContext, TSerializeOptions, TSerializedAnnotatedType, TSerializedAnnotatedTypeInner, TSerializedTypeArray, TSerializedTypeComplex, TSerializedTypeDef, TSerializedTypeFinal, TSerializedTypeObject, TValidatorOptions, TValidatorPlugin, TValidatorPluginContext, TValueResolver };