@atscript/typescript 0.1.0 → 0.1.2

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 CHANGED
@@ -325,7 +325,7 @@ var TypeRenderer = class TypeRenderer extends BaseRenderer {
325
325
  this.writeln("static __is_atscript_annotated_type: true");
326
326
  this.writeln(`static type: TAtscriptTypeObject<keyof ${asClass}>`);
327
327
  this.writeln(`static metadata: TMetadataMap<AtscriptMetadata>`);
328
- this.writeln(`static validator: <TT extends TAtscriptAnnotatedTypeConstructor = ${asClass}>(opts?: Partial<TValidatorOptions>) => Validator<TT>`);
328
+ this.writeln(`static validator: <TT extends TAtscriptAnnotatedTypeConstructor = typeof ${asClass}>(opts?: Partial<TValidatorOptions>) => Validator<TT>`);
329
329
  this.writeln("static toJsonSchema: () => any");
330
330
  }
331
331
  this.pop();
@@ -354,33 +354,33 @@ else this.writeln("{}");
354
354
  renderAnnotate(node) {
355
355
  if (node.isMutating) return;
356
356
  const targetName = node.targetName;
357
- const unwound = this.doc.unwindType(targetName);
358
- if (!unwound?.def) return;
359
- const def = this.doc.mergeIntersection(unwound.def);
360
357
  this.writeln();
361
358
  const exported = node.token("export")?.text === "export";
362
359
  this.renderJsDoc(node);
363
- if ((0, __atscript_core.isStructure)(def) || (0, __atscript_core.isInterface)(def)) {
364
- this.write(exported ? "export declare " : "declare ");
365
- this.write(`class ${node.id} `);
366
- this.renderStructure(def, node.id);
367
- } else {
360
+ if (this.isTypeTarget(targetName)) {
368
361
  this.write(exported ? "export " : "declare ");
369
- this.write(`type ${node.id} = `);
370
- this.renderTypeDef(def);
362
+ this.write(`type ${node.id} = ${targetName}`);
363
+ this.writeln();
364
+ const unwound = this.doc.unwindType(targetName);
365
+ this.renderTypeNamespaceFor(node.id, unwound?.def);
366
+ } else {
367
+ this.write(exported ? "export declare " : "declare ");
368
+ this.writeln(`class ${node.id} extends ${targetName} {}`);
369
+ this.writeln();
371
370
  }
372
- this.writeln();
373
371
  }
374
372
  renderTypeNamespace(node) {
375
- this.write(`declare namespace ${node.id} `);
373
+ this.renderTypeNamespaceFor(node.id, node.getDefinition());
374
+ }
375
+ renderTypeNamespaceFor(name, inputDef) {
376
+ this.write(`declare namespace ${name} `);
376
377
  this.blockln("{}");
377
- const def = node.getDefinition();
378
378
  let typeDef = "TAtscriptTypeDef";
379
- if (def) {
380
- let realDef = def;
381
- if ((0, __atscript_core.isRef)(def)) realDef = this.doc.unwindType(def.id, def.chain)?.def || realDef;
379
+ if (inputDef) {
380
+ let realDef = inputDef;
381
+ if ((0, __atscript_core.isRef)(inputDef)) realDef = this.doc.unwindType(inputDef.id, inputDef.chain)?.def || realDef;
382
382
  realDef = this.doc.mergeIntersection(realDef);
383
- if ((0, __atscript_core.isStructure)(realDef) || (0, __atscript_core.isInterface)(realDef)) typeDef = `TAtscriptTypeObject<keyof ${node.id}>`;
383
+ if ((0, __atscript_core.isStructure)(realDef) || (0, __atscript_core.isInterface)(realDef)) typeDef = `TAtscriptTypeObject<keyof ${name}>`;
384
384
  else if ((0, __atscript_core.isGroup)(realDef)) typeDef = "TAtscriptTypeComplex";
385
385
  else if ((0, __atscript_core.isArray)(realDef)) typeDef = "TAtscriptTypeArray";
386
386
  else if ((0, __atscript_core.isPrimitive)(realDef)) typeDef = "TAtscriptTypeFinal";
@@ -388,10 +388,19 @@ else if ((0, __atscript_core.isPrimitive)(realDef)) typeDef = "TAtscriptTypeFina
388
388
  this.writeln(`const __is_atscript_annotated_type: true`);
389
389
  this.writeln(`const type: ${typeDef}`);
390
390
  this.writeln(`const metadata: TMetadataMap<AtscriptMetadata>`);
391
- this.writeln(`const validator: <TT extends TAtscriptAnnotatedTypeConstructor = ${node.id}>(opts?: Partial<TValidatorOptions>) => Validator<TT>`);
391
+ this.writeln(`const validator: (opts?: Partial<TValidatorOptions>) => Validator<TAtscriptAnnotatedTypeConstructor, ${name}>`);
392
392
  this.writeln("const toJsonSchema: () => any");
393
393
  this.popln();
394
394
  }
395
+ isTypeTarget(name, doc) {
396
+ const d = doc || this.doc;
397
+ const decl = d.getDeclarationOwnerNode(name);
398
+ if (!decl?.node) return false;
399
+ if (decl.node.entity === "type") return true;
400
+ if (decl.node.entity === "interface") return false;
401
+ if (decl.node.entity === "annotate") return this.isTypeTarget(decl.node.targetName, decl.doc);
402
+ return false;
403
+ }
395
404
  renderJsDoc(node) {
396
405
  const range = node.token("identifier")?.range;
397
406
  const rangeStr = range ? `:${range.start.line + 1}:${range.start.character + 1}` : "";
@@ -760,6 +769,15 @@ var ValidatorError = class extends Error {
760
769
  function isAnnotatedType(type) {
761
770
  return type && type.__is_atscript_annotated_type;
762
771
  }
772
+ function annotate(metadata, key, value, asArray) {
773
+ if (!metadata) return;
774
+ if (asArray) if (metadata.has(key)) {
775
+ const a = metadata.get(key);
776
+ if (Array.isArray(a)) a.push(value);
777
+ else metadata.set(key, [a, value]);
778
+ } else metadata.set(key, [value]);
779
+ else metadata.set(key, value);
780
+ }
763
781
  function defineAnnotatedType(_kind, base) {
764
782
  const kind = _kind || "";
765
783
  const type = base?.type || {};
@@ -859,12 +877,7 @@ else if (!newBase) throw new Error(`"${typeName}" is not annotated type`);
859
877
  return this;
860
878
  },
861
879
  annotate(key, value, asArray) {
862
- if (asArray) if (this.$metadata.has(key)) {
863
- const a = this.$metadata.get(key);
864
- if (Array.isArray(a)) a.push(value);
865
- else this.$metadata.set(key, [a, value]);
866
- } else this.$metadata.set(key, [value]);
867
- else this.$metadata.set(key, value);
880
+ annotate(this.$metadata, key, value, asArray);
868
881
  return this;
869
882
  }
870
883
  };
@@ -968,7 +981,7 @@ var JsRenderer = class extends BaseRenderer {
968
981
  pre() {
969
982
  this.writeln("// prettier-ignore-start");
970
983
  this.writeln("/* eslint-disable */");
971
- const imports = ["defineAnnotatedType as $"];
984
+ const imports = ["defineAnnotatedType as $", "annotate as $a"];
972
985
  if (!this.opts?.preRenderJsonSchema) imports.push("buildJsonSchema as $$");
973
986
  this.writeln(`import { ${imports.join(", ")} } from "@atscript/typescript/utils"`);
974
987
  }
@@ -987,37 +1000,42 @@ var JsRenderer = class extends BaseRenderer {
987
1000
  post() {
988
1001
  for (const node of this.postAnnotate) if (node.entity === "annotate") {
989
1002
  const annotateNode = node;
990
- const unwound = this.doc.unwindType(annotateNode.targetName);
991
- if (unwound?.def) {
992
- let def = this.doc.mergeIntersection(unwound.def);
993
- if ((0, __atscript_core.isInterface)(def)) def = def.getDefinition() || def;
994
- this._adHocAnnotations = this.buildAdHocMap([annotateNode]);
995
- this.annotateType(def, node.id);
996
- this._adHocAnnotations = null;
997
- this.indent();
998
- this.defineMetadataForAnnotateAlias(annotateNode);
999
- this.unindent();
1000
- this.writeln();
1003
+ if (annotateNode.isMutating) this.renderMutatingAnnotateNode(annotateNode);
1004
+ else {
1005
+ const unwound = this.doc.unwindType(annotateNode.targetName);
1006
+ if (unwound?.def) {
1007
+ let def = this.doc.mergeIntersection(unwound.def);
1008
+ if ((0, __atscript_core.isInterface)(def)) def = def.getDefinition() || def;
1009
+ this._adHocAnnotations = this.buildAdHocMap([annotateNode]);
1010
+ this.annotateType(def, node.id);
1011
+ this._adHocAnnotations = null;
1012
+ this.indent();
1013
+ this.defineMetadataForAnnotateAlias(annotateNode);
1014
+ this.unindent();
1015
+ this.writeln();
1016
+ }
1001
1017
  }
1002
1018
  } else {
1003
- const mutatingNodes = this.doc.getAnnotateNodesFor(node.id).filter((n) => n.isMutating);
1004
- this._adHocAnnotations = this.buildAdHocMap(mutatingNodes);
1005
1019
  this.annotateType(node.getDefinition(), node.id);
1006
- this._adHocAnnotations = null;
1007
1020
  this.indent().defineMetadata(node).unindent();
1008
1021
  this.writeln();
1009
1022
  }
1010
- this.renderMutatingAnnotates();
1011
1023
  this.writeln("// prettier-ignore-end");
1012
1024
  super.post();
1013
1025
  }
1026
+ renderClassStatics(node) {
1027
+ this.writeln("static __is_atscript_annotated_type = true");
1028
+ this.writeln("static type = {}");
1029
+ this.writeln("static metadata = new Map()");
1030
+ this.renderJsonSchemaMethod(node);
1031
+ }
1014
1032
  renderInterface(node) {
1015
1033
  this.writeln();
1016
1034
  const exported = node.token("export")?.text === "export";
1017
1035
  this.write(exported ? "export " : "");
1018
1036
  this.write(`class ${node.id} `);
1019
1037
  this.blockln("{}");
1020
- this.renderJsonSchemaMethod(node);
1038
+ this.renderClassStatics(node);
1021
1039
  this.popln();
1022
1040
  this.postAnnotate.push(node);
1023
1041
  this.writeln();
@@ -1028,14 +1046,14 @@ var JsRenderer = class extends BaseRenderer {
1028
1046
  this.write(exported ? "export " : "");
1029
1047
  this.write(`class ${node.id} `);
1030
1048
  this.blockln("{}");
1031
- this.renderJsonSchemaMethod(node);
1049
+ this.renderClassStatics(node);
1032
1050
  this.popln();
1033
1051
  this.postAnnotate.push(node);
1034
1052
  this.writeln();
1035
1053
  }
1036
1054
  renderAnnotate(node) {
1037
1055
  if (node.isMutating) {
1038
- this.mutatingAnnotates.push(node);
1056
+ this.postAnnotate.push(node);
1039
1057
  return;
1040
1058
  }
1041
1059
  const targetName = node.targetName;
@@ -1046,7 +1064,7 @@ var JsRenderer = class extends BaseRenderer {
1046
1064
  this.write(exported ? "export " : "");
1047
1065
  this.write(`class ${node.id} `);
1048
1066
  this.blockln("{}");
1049
- this.renderJsonSchemaMethod(node);
1067
+ this.renderClassStatics(node);
1050
1068
  this.popln();
1051
1069
  this.postAnnotate.push(node);
1052
1070
  this.writeln();
@@ -1323,18 +1341,13 @@ else handle.prop(prop.id, propHandle.$type);
1323
1341
  return this;
1324
1342
  }
1325
1343
  defineMetadata(node) {
1326
- const annotations = this.doc.evalAnnotationsForNode(node);
1327
- let adHocNames;
1328
- let adHoc;
1344
+ let annotations = this.doc.evalAnnotationsForNode(node);
1329
1345
  if (this._adHocAnnotations && this._propPath.length > 0) {
1330
1346
  const path$3 = this._propPath.join(".");
1331
- adHoc = this._adHocAnnotations.get(path$3);
1332
- if (adHoc) adHocNames = new Set(adHoc.map((a) => a.name));
1347
+ const adHoc = this._adHocAnnotations.get(path$3);
1348
+ if (adHoc) annotations = this.doc.mergeNodesAnnotations(annotations, adHoc);
1333
1349
  }
1334
1350
  annotations?.forEach((an) => {
1335
- if (!adHocNames || !adHocNames.has(an.name)) this.resolveAnnotationValue(node, an);
1336
- });
1337
- adHoc?.forEach((an) => {
1338
1351
  this.resolveAnnotationValue(node, an);
1339
1352
  });
1340
1353
  return this;
@@ -1346,11 +1359,8 @@ else handle.prop(prop.id, propHandle.$type);
1346
1359
  const annotateAnnotations = this.doc.evalAnnotationsForNode(annotateNode);
1347
1360
  const targetDecl = this.doc.getDeclarationOwnerNode(annotateNode.targetName);
1348
1361
  const targetAnnotations = targetDecl?.node ? targetDecl.doc.evalAnnotationsForNode(targetDecl.node) : undefined;
1349
- const overriddenNames = new Set(annotateAnnotations?.map((a) => a.name));
1350
- targetAnnotations?.forEach((an) => {
1351
- if (!overriddenNames.has(an.name)) this.resolveAnnotationValue(annotateNode, an);
1352
- });
1353
- annotateAnnotations?.forEach((an) => {
1362
+ const merged = this.doc.mergeNodesAnnotations(targetAnnotations, annotateAnnotations);
1363
+ merged.forEach((an) => {
1354
1364
  this.resolveAnnotationValue(annotateNode, an);
1355
1365
  });
1356
1366
  return this;
@@ -1389,47 +1399,123 @@ else targetValue = "true";
1389
1399
  multiple: !!multiple
1390
1400
  };
1391
1401
  }
1392
- renderMutatingAnnotates() {
1393
- for (const node of this.mutatingAnnotates) {
1394
- const targetName = node.targetName;
1395
- for (const entry of node.entries) {
1396
- const anns = entry.annotations;
1397
- if (!anns || anns.length === 0) continue;
1398
- const parts = entry.hasChain ? [entry.id, ...entry.chain.map((c) => c.text)] : [entry.id];
1399
- let accessor = targetName;
1400
- for (const part of parts) accessor += `.type.props.get("${escapeQuotes(part)}")?`;
1402
+ renderMutatingAnnotateNode(node) {
1403
+ const targetName = node.targetName;
1404
+ const targetDef = this.resolveTargetDef(targetName);
1405
+ this.writeln("// Ad-hoc annotations for ", targetName);
1406
+ for (const entry of node.entries) {
1407
+ const anns = entry.annotations;
1408
+ if (!anns || anns.length === 0) continue;
1409
+ const parts = entry.hasChain ? [entry.id, ...entry.chain.map((c) => c.text)] : [entry.id];
1410
+ const accessors = this.buildMutatingAccessors(targetName, targetDef, parts);
1411
+ for (const accessor of accessors) {
1412
+ const cleared = new Set();
1401
1413
  for (const an of anns) {
1402
1414
  const { value, multiple } = this.computeAnnotationValue(entry, an);
1403
1415
  if (multiple) {
1404
- this.writeln(`{`);
1405
- this.indent();
1406
- this.writeln(`const __t = ${accessor}.metadata`);
1407
- this.writeln(`const __k = "${escapeQuotes(an.name)}"`);
1408
- this.writeln(`const __v = ${value}`);
1409
- this.writeln(`if (__t) { const __e = __t.get(__k); __t.set(__k, Array.isArray(__e) ? [...__e, __v] : __e !== undefined ? [__e, __v] : [__v]) }`);
1410
- this.unindent();
1411
- this.writeln(`}`);
1412
- } else this.writeln(`${accessor}.metadata.set("${escapeQuotes(an.name)}", ${value})`);
1416
+ if (!cleared.has(an.name)) {
1417
+ const spec = this.doc.resolveAnnotation(an.name);
1418
+ if (!spec || spec.config.mergeStrategy !== "append") this.writeln(`${accessor}.metadata.delete("${escapeQuotes(an.name)}")`);
1419
+ cleared.add(an.name);
1420
+ }
1421
+ this.writeln(`$a(${accessor}.metadata, "${escapeQuotes(an.name)}", ${value}, true)`);
1422
+ } else this.writeln(`$a(${accessor}.metadata, "${escapeQuotes(an.name)}", ${value})`);
1413
1423
  }
1414
1424
  }
1415
- const topAnnotations = node.annotations;
1416
- if (topAnnotations && topAnnotations.length > 0) for (const an of topAnnotations) {
1425
+ }
1426
+ const topAnnotations = node.annotations;
1427
+ if (topAnnotations && topAnnotations.length > 0) {
1428
+ const cleared = new Set();
1429
+ for (const an of topAnnotations) {
1417
1430
  const { value, multiple } = this.computeAnnotationValue(node, an);
1418
1431
  if (multiple) {
1419
- this.writeln(`{`);
1420
- this.indent();
1421
- this.writeln(`const __t = ${targetName}.metadata`);
1422
- this.writeln(`const __k = "${escapeQuotes(an.name)}"`);
1423
- this.writeln(`const __v = ${value}`);
1424
- this.writeln(`if (__t) { const __e = __t.get(__k); __t.set(__k, Array.isArray(__e) ? [...__e, __v] : __e !== undefined ? [__e, __v] : [__v]) }`);
1425
- this.unindent();
1426
- this.writeln(`}`);
1427
- } else this.writeln(`${targetName}.metadata.set("${escapeQuotes(an.name)}", ${value})`);
1432
+ if (!cleared.has(an.name)) {
1433
+ const spec = this.doc.resolveAnnotation(an.name);
1434
+ if (!spec || spec.config.mergeStrategy !== "append") this.writeln(`${targetName}.metadata.delete("${escapeQuotes(an.name)}")`);
1435
+ cleared.add(an.name);
1436
+ }
1437
+ this.writeln(`$a(${targetName}.metadata, "${escapeQuotes(an.name)}", ${value}, true)`);
1438
+ } else this.writeln(`$a(${targetName}.metadata, "${escapeQuotes(an.name)}", ${value})`);
1439
+ }
1440
+ }
1441
+ this.writeln();
1442
+ }
1443
+ resolveTargetDef(targetName) {
1444
+ const unwound = this.doc.unwindType(targetName);
1445
+ if (!unwound?.def) return undefined;
1446
+ let def = unwound.def;
1447
+ if ((0, __atscript_core.isInterface)(def)) def = def.getDefinition() || def;
1448
+ return def;
1449
+ }
1450
+ /**
1451
+ * Builds the runtime accessor paths for mutating annotate entries.
1452
+ * Computes exact paths at compile time by walking the AST,
1453
+ * so the generated JS accesses props directly without runtime search.
1454
+ * Returns multiple paths when a property appears in multiple union branches.
1455
+ */ buildMutatingAccessors(targetName, targetDef, parts) {
1456
+ let accessors = [{
1457
+ prefix: targetName + ".type",
1458
+ def: targetDef
1459
+ }];
1460
+ for (let i = 0; i < parts.length; i++) {
1461
+ const nextAccessors = [];
1462
+ for (const { prefix, def } of accessors) {
1463
+ const results = this.buildPropPaths(def, parts[i]);
1464
+ if (results.length > 0) for (const result of results) if (i < parts.length - 1) nextAccessors.push({
1465
+ prefix: prefix + result.path + "?.type",
1466
+ def: result.propDef
1467
+ });
1468
+ else nextAccessors.push({
1469
+ prefix: prefix + result.path + "?",
1470
+ def: result.propDef
1471
+ });
1472
+ else {
1473
+ const suffix = `.props.get("${escapeQuotes(parts[i])}")` + (i < parts.length - 1 ? "?.type" : "?");
1474
+ nextAccessors.push({
1475
+ prefix: prefix + suffix,
1476
+ def: undefined
1477
+ });
1478
+ }
1428
1479
  }
1480
+ accessors = nextAccessors;
1481
+ }
1482
+ return accessors.map((a) => a.prefix);
1483
+ }
1484
+ /**
1485
+ * Finds a property in a type tree at compile time, returning all
1486
+ * matching runtime path strings and prop definitions for further chaining.
1487
+ * Returns multiple results when the same property appears in different union branches.
1488
+ */ buildPropPaths(def, propName) {
1489
+ if (!def) return [];
1490
+ def = this.doc.mergeIntersection(def);
1491
+ if ((0, __atscript_core.isRef)(def)) {
1492
+ const ref = def;
1493
+ const unwound = this.doc.unwindType(ref.id, ref.chain)?.def;
1494
+ return this.buildPropPaths(unwound, propName);
1495
+ }
1496
+ if ((0, __atscript_core.isInterface)(def)) return this.buildPropPaths(def.getDefinition(), propName);
1497
+ if ((0, __atscript_core.isStructure)(def)) {
1498
+ const prop = def.props.get(propName);
1499
+ if (prop) return [{
1500
+ path: `.props.get("${escapeQuotes(propName)}")`,
1501
+ propDef: prop.getDefinition()
1502
+ }];
1503
+ return [];
1504
+ }
1505
+ if ((0, __atscript_core.isGroup)(def)) {
1506
+ const group = def;
1507
+ const items = group.unwrap();
1508
+ const results = [];
1509
+ for (let i = 0; i < items.length; i++) for (const result of this.buildPropPaths(items[i], propName)) results.push({
1510
+ path: `.items[${i}].type${result.path}`,
1511
+ propDef: result.propDef
1512
+ });
1513
+ return results;
1429
1514
  }
1515
+ return [];
1430
1516
  }
1431
1517
  constructor(doc, opts) {
1432
- super(doc), _define_property$1(this, "opts", void 0), _define_property$1(this, "postAnnotate", void 0), _define_property$1(this, "mutatingAnnotates", void 0), _define_property$1(this, "_adHocAnnotations", void 0), _define_property$1(this, "_propPath", void 0), this.opts = opts, this.postAnnotate = [], this.mutatingAnnotates = [], this._adHocAnnotations = null, this._propPath = [];
1518
+ super(doc), _define_property$1(this, "opts", void 0), _define_property$1(this, "postAnnotate", void 0), _define_property$1(this, "_adHocAnnotations", void 0), _define_property$1(this, "_propPath", void 0), this.opts = opts, this.postAnnotate = [], this._adHocAnnotations = null, this._propPath = [];
1433
1519
  }
1434
1520
  };
1435
1521
 
package/dist/index.cjs CHANGED
@@ -322,7 +322,7 @@ var TypeRenderer = class TypeRenderer extends BaseRenderer {
322
322
  this.writeln("static __is_atscript_annotated_type: true");
323
323
  this.writeln(`static type: TAtscriptTypeObject<keyof ${asClass}>`);
324
324
  this.writeln(`static metadata: TMetadataMap<AtscriptMetadata>`);
325
- this.writeln(`static validator: <TT extends TAtscriptAnnotatedTypeConstructor = ${asClass}>(opts?: Partial<TValidatorOptions>) => Validator<TT>`);
325
+ this.writeln(`static validator: <TT extends TAtscriptAnnotatedTypeConstructor = typeof ${asClass}>(opts?: Partial<TValidatorOptions>) => Validator<TT>`);
326
326
  this.writeln("static toJsonSchema: () => any");
327
327
  }
328
328
  this.pop();
@@ -351,33 +351,33 @@ else this.writeln("{}");
351
351
  renderAnnotate(node) {
352
352
  if (node.isMutating) return;
353
353
  const targetName = node.targetName;
354
- const unwound = this.doc.unwindType(targetName);
355
- if (!unwound?.def) return;
356
- const def = this.doc.mergeIntersection(unwound.def);
357
354
  this.writeln();
358
355
  const exported = node.token("export")?.text === "export";
359
356
  this.renderJsDoc(node);
360
- if ((0, __atscript_core.isStructure)(def) || (0, __atscript_core.isInterface)(def)) {
361
- this.write(exported ? "export declare " : "declare ");
362
- this.write(`class ${node.id} `);
363
- this.renderStructure(def, node.id);
364
- } else {
357
+ if (this.isTypeTarget(targetName)) {
365
358
  this.write(exported ? "export " : "declare ");
366
- this.write(`type ${node.id} = `);
367
- this.renderTypeDef(def);
359
+ this.write(`type ${node.id} = ${targetName}`);
360
+ this.writeln();
361
+ const unwound = this.doc.unwindType(targetName);
362
+ this.renderTypeNamespaceFor(node.id, unwound?.def);
363
+ } else {
364
+ this.write(exported ? "export declare " : "declare ");
365
+ this.writeln(`class ${node.id} extends ${targetName} {}`);
366
+ this.writeln();
368
367
  }
369
- this.writeln();
370
368
  }
371
369
  renderTypeNamespace(node) {
372
- this.write(`declare namespace ${node.id} `);
370
+ this.renderTypeNamespaceFor(node.id, node.getDefinition());
371
+ }
372
+ renderTypeNamespaceFor(name, inputDef) {
373
+ this.write(`declare namespace ${name} `);
373
374
  this.blockln("{}");
374
- const def = node.getDefinition();
375
375
  let typeDef = "TAtscriptTypeDef";
376
- if (def) {
377
- let realDef = def;
378
- if ((0, __atscript_core.isRef)(def)) realDef = this.doc.unwindType(def.id, def.chain)?.def || realDef;
376
+ if (inputDef) {
377
+ let realDef = inputDef;
378
+ if ((0, __atscript_core.isRef)(inputDef)) realDef = this.doc.unwindType(inputDef.id, inputDef.chain)?.def || realDef;
379
379
  realDef = this.doc.mergeIntersection(realDef);
380
- if ((0, __atscript_core.isStructure)(realDef) || (0, __atscript_core.isInterface)(realDef)) typeDef = `TAtscriptTypeObject<keyof ${node.id}>`;
380
+ if ((0, __atscript_core.isStructure)(realDef) || (0, __atscript_core.isInterface)(realDef)) typeDef = `TAtscriptTypeObject<keyof ${name}>`;
381
381
  else if ((0, __atscript_core.isGroup)(realDef)) typeDef = "TAtscriptTypeComplex";
382
382
  else if ((0, __atscript_core.isArray)(realDef)) typeDef = "TAtscriptTypeArray";
383
383
  else if ((0, __atscript_core.isPrimitive)(realDef)) typeDef = "TAtscriptTypeFinal";
@@ -385,10 +385,19 @@ else if ((0, __atscript_core.isPrimitive)(realDef)) typeDef = "TAtscriptTypeFina
385
385
  this.writeln(`const __is_atscript_annotated_type: true`);
386
386
  this.writeln(`const type: ${typeDef}`);
387
387
  this.writeln(`const metadata: TMetadataMap<AtscriptMetadata>`);
388
- this.writeln(`const validator: <TT extends TAtscriptAnnotatedTypeConstructor = ${node.id}>(opts?: Partial<TValidatorOptions>) => Validator<TT>`);
388
+ this.writeln(`const validator: (opts?: Partial<TValidatorOptions>) => Validator<TAtscriptAnnotatedTypeConstructor, ${name}>`);
389
389
  this.writeln("const toJsonSchema: () => any");
390
390
  this.popln();
391
391
  }
392
+ isTypeTarget(name, doc) {
393
+ const d = doc || this.doc;
394
+ const decl = d.getDeclarationOwnerNode(name);
395
+ if (!decl?.node) return false;
396
+ if (decl.node.entity === "type") return true;
397
+ if (decl.node.entity === "interface") return false;
398
+ if (decl.node.entity === "annotate") return this.isTypeTarget(decl.node.targetName, decl.doc);
399
+ return false;
400
+ }
392
401
  renderJsDoc(node) {
393
402
  const range = node.token("identifier")?.range;
394
403
  const rangeStr = range ? `:${range.start.line + 1}:${range.start.character + 1}` : "";
@@ -757,6 +766,15 @@ var ValidatorError = class extends Error {
757
766
  function isAnnotatedType(type) {
758
767
  return type && type.__is_atscript_annotated_type;
759
768
  }
769
+ function annotate(metadata, key, value, asArray) {
770
+ if (!metadata) return;
771
+ if (asArray) if (metadata.has(key)) {
772
+ const a = metadata.get(key);
773
+ if (Array.isArray(a)) a.push(value);
774
+ else metadata.set(key, [a, value]);
775
+ } else metadata.set(key, [value]);
776
+ else metadata.set(key, value);
777
+ }
760
778
  function defineAnnotatedType(_kind, base) {
761
779
  const kind = _kind || "";
762
780
  const type = base?.type || {};
@@ -856,12 +874,7 @@ else if (!newBase) throw new Error(`"${typeName}" is not annotated type`);
856
874
  return this;
857
875
  },
858
876
  annotate(key, value, asArray) {
859
- if (asArray) if (this.$metadata.has(key)) {
860
- const a = this.$metadata.get(key);
861
- if (Array.isArray(a)) a.push(value);
862
- else this.$metadata.set(key, [a, value]);
863
- } else this.$metadata.set(key, [value]);
864
- else this.$metadata.set(key, value);
877
+ annotate(this.$metadata, key, value, asArray);
865
878
  return this;
866
879
  }
867
880
  };
@@ -965,7 +978,7 @@ var JsRenderer = class extends BaseRenderer {
965
978
  pre() {
966
979
  this.writeln("// prettier-ignore-start");
967
980
  this.writeln("/* eslint-disable */");
968
- const imports = ["defineAnnotatedType as $"];
981
+ const imports = ["defineAnnotatedType as $", "annotate as $a"];
969
982
  if (!this.opts?.preRenderJsonSchema) imports.push("buildJsonSchema as $$");
970
983
  this.writeln(`import { ${imports.join(", ")} } from "@atscript/typescript/utils"`);
971
984
  }
@@ -984,37 +997,42 @@ var JsRenderer = class extends BaseRenderer {
984
997
  post() {
985
998
  for (const node of this.postAnnotate) if (node.entity === "annotate") {
986
999
  const annotateNode = node;
987
- const unwound = this.doc.unwindType(annotateNode.targetName);
988
- if (unwound?.def) {
989
- let def = this.doc.mergeIntersection(unwound.def);
990
- if ((0, __atscript_core.isInterface)(def)) def = def.getDefinition() || def;
991
- this._adHocAnnotations = this.buildAdHocMap([annotateNode]);
992
- this.annotateType(def, node.id);
993
- this._adHocAnnotations = null;
994
- this.indent();
995
- this.defineMetadataForAnnotateAlias(annotateNode);
996
- this.unindent();
997
- this.writeln();
1000
+ if (annotateNode.isMutating) this.renderMutatingAnnotateNode(annotateNode);
1001
+ else {
1002
+ const unwound = this.doc.unwindType(annotateNode.targetName);
1003
+ if (unwound?.def) {
1004
+ let def = this.doc.mergeIntersection(unwound.def);
1005
+ if ((0, __atscript_core.isInterface)(def)) def = def.getDefinition() || def;
1006
+ this._adHocAnnotations = this.buildAdHocMap([annotateNode]);
1007
+ this.annotateType(def, node.id);
1008
+ this._adHocAnnotations = null;
1009
+ this.indent();
1010
+ this.defineMetadataForAnnotateAlias(annotateNode);
1011
+ this.unindent();
1012
+ this.writeln();
1013
+ }
998
1014
  }
999
1015
  } else {
1000
- const mutatingNodes = this.doc.getAnnotateNodesFor(node.id).filter((n) => n.isMutating);
1001
- this._adHocAnnotations = this.buildAdHocMap(mutatingNodes);
1002
1016
  this.annotateType(node.getDefinition(), node.id);
1003
- this._adHocAnnotations = null;
1004
1017
  this.indent().defineMetadata(node).unindent();
1005
1018
  this.writeln();
1006
1019
  }
1007
- this.renderMutatingAnnotates();
1008
1020
  this.writeln("// prettier-ignore-end");
1009
1021
  super.post();
1010
1022
  }
1023
+ renderClassStatics(node) {
1024
+ this.writeln("static __is_atscript_annotated_type = true");
1025
+ this.writeln("static type = {}");
1026
+ this.writeln("static metadata = new Map()");
1027
+ this.renderJsonSchemaMethod(node);
1028
+ }
1011
1029
  renderInterface(node) {
1012
1030
  this.writeln();
1013
1031
  const exported = node.token("export")?.text === "export";
1014
1032
  this.write(exported ? "export " : "");
1015
1033
  this.write(`class ${node.id} `);
1016
1034
  this.blockln("{}");
1017
- this.renderJsonSchemaMethod(node);
1035
+ this.renderClassStatics(node);
1018
1036
  this.popln();
1019
1037
  this.postAnnotate.push(node);
1020
1038
  this.writeln();
@@ -1025,14 +1043,14 @@ var JsRenderer = class extends BaseRenderer {
1025
1043
  this.write(exported ? "export " : "");
1026
1044
  this.write(`class ${node.id} `);
1027
1045
  this.blockln("{}");
1028
- this.renderJsonSchemaMethod(node);
1046
+ this.renderClassStatics(node);
1029
1047
  this.popln();
1030
1048
  this.postAnnotate.push(node);
1031
1049
  this.writeln();
1032
1050
  }
1033
1051
  renderAnnotate(node) {
1034
1052
  if (node.isMutating) {
1035
- this.mutatingAnnotates.push(node);
1053
+ this.postAnnotate.push(node);
1036
1054
  return;
1037
1055
  }
1038
1056
  const targetName = node.targetName;
@@ -1043,7 +1061,7 @@ var JsRenderer = class extends BaseRenderer {
1043
1061
  this.write(exported ? "export " : "");
1044
1062
  this.write(`class ${node.id} `);
1045
1063
  this.blockln("{}");
1046
- this.renderJsonSchemaMethod(node);
1064
+ this.renderClassStatics(node);
1047
1065
  this.popln();
1048
1066
  this.postAnnotate.push(node);
1049
1067
  this.writeln();
@@ -1320,18 +1338,13 @@ else handle.prop(prop.id, propHandle.$type);
1320
1338
  return this;
1321
1339
  }
1322
1340
  defineMetadata(node) {
1323
- const annotations = this.doc.evalAnnotationsForNode(node);
1324
- let adHocNames;
1325
- let adHoc;
1341
+ let annotations = this.doc.evalAnnotationsForNode(node);
1326
1342
  if (this._adHocAnnotations && this._propPath.length > 0) {
1327
1343
  const path$2 = this._propPath.join(".");
1328
- adHoc = this._adHocAnnotations.get(path$2);
1329
- if (adHoc) adHocNames = new Set(adHoc.map((a) => a.name));
1344
+ const adHoc = this._adHocAnnotations.get(path$2);
1345
+ if (adHoc) annotations = this.doc.mergeNodesAnnotations(annotations, adHoc);
1330
1346
  }
1331
1347
  annotations?.forEach((an) => {
1332
- if (!adHocNames || !adHocNames.has(an.name)) this.resolveAnnotationValue(node, an);
1333
- });
1334
- adHoc?.forEach((an) => {
1335
1348
  this.resolveAnnotationValue(node, an);
1336
1349
  });
1337
1350
  return this;
@@ -1343,11 +1356,8 @@ else handle.prop(prop.id, propHandle.$type);
1343
1356
  const annotateAnnotations = this.doc.evalAnnotationsForNode(annotateNode);
1344
1357
  const targetDecl = this.doc.getDeclarationOwnerNode(annotateNode.targetName);
1345
1358
  const targetAnnotations = targetDecl?.node ? targetDecl.doc.evalAnnotationsForNode(targetDecl.node) : undefined;
1346
- const overriddenNames = new Set(annotateAnnotations?.map((a) => a.name));
1347
- targetAnnotations?.forEach((an) => {
1348
- if (!overriddenNames.has(an.name)) this.resolveAnnotationValue(annotateNode, an);
1349
- });
1350
- annotateAnnotations?.forEach((an) => {
1359
+ const merged = this.doc.mergeNodesAnnotations(targetAnnotations, annotateAnnotations);
1360
+ merged.forEach((an) => {
1351
1361
  this.resolveAnnotationValue(annotateNode, an);
1352
1362
  });
1353
1363
  return this;
@@ -1386,47 +1396,123 @@ else targetValue = "true";
1386
1396
  multiple: !!multiple
1387
1397
  };
1388
1398
  }
1389
- renderMutatingAnnotates() {
1390
- for (const node of this.mutatingAnnotates) {
1391
- const targetName = node.targetName;
1392
- for (const entry of node.entries) {
1393
- const anns = entry.annotations;
1394
- if (!anns || anns.length === 0) continue;
1395
- const parts = entry.hasChain ? [entry.id, ...entry.chain.map((c) => c.text)] : [entry.id];
1396
- let accessor = targetName;
1397
- for (const part of parts) accessor += `.type.props.get("${escapeQuotes(part)}")?`;
1399
+ renderMutatingAnnotateNode(node) {
1400
+ const targetName = node.targetName;
1401
+ const targetDef = this.resolveTargetDef(targetName);
1402
+ this.writeln("// Ad-hoc annotations for ", targetName);
1403
+ for (const entry of node.entries) {
1404
+ const anns = entry.annotations;
1405
+ if (!anns || anns.length === 0) continue;
1406
+ const parts = entry.hasChain ? [entry.id, ...entry.chain.map((c) => c.text)] : [entry.id];
1407
+ const accessors = this.buildMutatingAccessors(targetName, targetDef, parts);
1408
+ for (const accessor of accessors) {
1409
+ const cleared = new Set();
1398
1410
  for (const an of anns) {
1399
1411
  const { value, multiple } = this.computeAnnotationValue(entry, an);
1400
1412
  if (multiple) {
1401
- this.writeln(`{`);
1402
- this.indent();
1403
- this.writeln(`const __t = ${accessor}.metadata`);
1404
- this.writeln(`const __k = "${escapeQuotes(an.name)}"`);
1405
- this.writeln(`const __v = ${value}`);
1406
- this.writeln(`if (__t) { const __e = __t.get(__k); __t.set(__k, Array.isArray(__e) ? [...__e, __v] : __e !== undefined ? [__e, __v] : [__v]) }`);
1407
- this.unindent();
1408
- this.writeln(`}`);
1409
- } else this.writeln(`${accessor}.metadata.set("${escapeQuotes(an.name)}", ${value})`);
1413
+ if (!cleared.has(an.name)) {
1414
+ const spec = this.doc.resolveAnnotation(an.name);
1415
+ if (!spec || spec.config.mergeStrategy !== "append") this.writeln(`${accessor}.metadata.delete("${escapeQuotes(an.name)}")`);
1416
+ cleared.add(an.name);
1417
+ }
1418
+ this.writeln(`$a(${accessor}.metadata, "${escapeQuotes(an.name)}", ${value}, true)`);
1419
+ } else this.writeln(`$a(${accessor}.metadata, "${escapeQuotes(an.name)}", ${value})`);
1410
1420
  }
1411
1421
  }
1412
- const topAnnotations = node.annotations;
1413
- if (topAnnotations && topAnnotations.length > 0) for (const an of topAnnotations) {
1422
+ }
1423
+ const topAnnotations = node.annotations;
1424
+ if (topAnnotations && topAnnotations.length > 0) {
1425
+ const cleared = new Set();
1426
+ for (const an of topAnnotations) {
1414
1427
  const { value, multiple } = this.computeAnnotationValue(node, an);
1415
1428
  if (multiple) {
1416
- this.writeln(`{`);
1417
- this.indent();
1418
- this.writeln(`const __t = ${targetName}.metadata`);
1419
- this.writeln(`const __k = "${escapeQuotes(an.name)}"`);
1420
- this.writeln(`const __v = ${value}`);
1421
- this.writeln(`if (__t) { const __e = __t.get(__k); __t.set(__k, Array.isArray(__e) ? [...__e, __v] : __e !== undefined ? [__e, __v] : [__v]) }`);
1422
- this.unindent();
1423
- this.writeln(`}`);
1424
- } else this.writeln(`${targetName}.metadata.set("${escapeQuotes(an.name)}", ${value})`);
1429
+ if (!cleared.has(an.name)) {
1430
+ const spec = this.doc.resolveAnnotation(an.name);
1431
+ if (!spec || spec.config.mergeStrategy !== "append") this.writeln(`${targetName}.metadata.delete("${escapeQuotes(an.name)}")`);
1432
+ cleared.add(an.name);
1433
+ }
1434
+ this.writeln(`$a(${targetName}.metadata, "${escapeQuotes(an.name)}", ${value}, true)`);
1435
+ } else this.writeln(`$a(${targetName}.metadata, "${escapeQuotes(an.name)}", ${value})`);
1436
+ }
1437
+ }
1438
+ this.writeln();
1439
+ }
1440
+ resolveTargetDef(targetName) {
1441
+ const unwound = this.doc.unwindType(targetName);
1442
+ if (!unwound?.def) return undefined;
1443
+ let def = unwound.def;
1444
+ if ((0, __atscript_core.isInterface)(def)) def = def.getDefinition() || def;
1445
+ return def;
1446
+ }
1447
+ /**
1448
+ * Builds the runtime accessor paths for mutating annotate entries.
1449
+ * Computes exact paths at compile time by walking the AST,
1450
+ * so the generated JS accesses props directly without runtime search.
1451
+ * Returns multiple paths when a property appears in multiple union branches.
1452
+ */ buildMutatingAccessors(targetName, targetDef, parts) {
1453
+ let accessors = [{
1454
+ prefix: targetName + ".type",
1455
+ def: targetDef
1456
+ }];
1457
+ for (let i = 0; i < parts.length; i++) {
1458
+ const nextAccessors = [];
1459
+ for (const { prefix, def } of accessors) {
1460
+ const results = this.buildPropPaths(def, parts[i]);
1461
+ if (results.length > 0) for (const result of results) if (i < parts.length - 1) nextAccessors.push({
1462
+ prefix: prefix + result.path + "?.type",
1463
+ def: result.propDef
1464
+ });
1465
+ else nextAccessors.push({
1466
+ prefix: prefix + result.path + "?",
1467
+ def: result.propDef
1468
+ });
1469
+ else {
1470
+ const suffix = `.props.get("${escapeQuotes(parts[i])}")` + (i < parts.length - 1 ? "?.type" : "?");
1471
+ nextAccessors.push({
1472
+ prefix: prefix + suffix,
1473
+ def: undefined
1474
+ });
1475
+ }
1425
1476
  }
1477
+ accessors = nextAccessors;
1478
+ }
1479
+ return accessors.map((a) => a.prefix);
1480
+ }
1481
+ /**
1482
+ * Finds a property in a type tree at compile time, returning all
1483
+ * matching runtime path strings and prop definitions for further chaining.
1484
+ * Returns multiple results when the same property appears in different union branches.
1485
+ */ buildPropPaths(def, propName) {
1486
+ if (!def) return [];
1487
+ def = this.doc.mergeIntersection(def);
1488
+ if ((0, __atscript_core.isRef)(def)) {
1489
+ const ref = def;
1490
+ const unwound = this.doc.unwindType(ref.id, ref.chain)?.def;
1491
+ return this.buildPropPaths(unwound, propName);
1492
+ }
1493
+ if ((0, __atscript_core.isInterface)(def)) return this.buildPropPaths(def.getDefinition(), propName);
1494
+ if ((0, __atscript_core.isStructure)(def)) {
1495
+ const prop = def.props.get(propName);
1496
+ if (prop) return [{
1497
+ path: `.props.get("${escapeQuotes(propName)}")`,
1498
+ propDef: prop.getDefinition()
1499
+ }];
1500
+ return [];
1501
+ }
1502
+ if ((0, __atscript_core.isGroup)(def)) {
1503
+ const group = def;
1504
+ const items = group.unwrap();
1505
+ const results = [];
1506
+ for (let i = 0; i < items.length; i++) for (const result of this.buildPropPaths(items[i], propName)) results.push({
1507
+ path: `.items[${i}].type${result.path}`,
1508
+ propDef: result.propDef
1509
+ });
1510
+ return results;
1426
1511
  }
1512
+ return [];
1427
1513
  }
1428
1514
  constructor(doc, opts) {
1429
- super(doc), _define_property(this, "opts", void 0), _define_property(this, "postAnnotate", void 0), _define_property(this, "mutatingAnnotates", void 0), _define_property(this, "_adHocAnnotations", void 0), _define_property(this, "_propPath", void 0), this.opts = opts, this.postAnnotate = [], this.mutatingAnnotates = [], this._adHocAnnotations = null, this._propPath = [];
1515
+ super(doc), _define_property(this, "opts", void 0), _define_property(this, "postAnnotate", void 0), _define_property(this, "_adHocAnnotations", void 0), _define_property(this, "_propPath", void 0), this.opts = opts, this.postAnnotate = [], this._adHocAnnotations = null, this._propPath = [];
1430
1516
  }
1431
1517
  };
1432
1518
 
package/dist/index.mjs CHANGED
@@ -298,7 +298,7 @@ var TypeRenderer = class TypeRenderer extends BaseRenderer {
298
298
  this.writeln("static __is_atscript_annotated_type: true");
299
299
  this.writeln(`static type: TAtscriptTypeObject<keyof ${asClass}>`);
300
300
  this.writeln(`static metadata: TMetadataMap<AtscriptMetadata>`);
301
- this.writeln(`static validator: <TT extends TAtscriptAnnotatedTypeConstructor = ${asClass}>(opts?: Partial<TValidatorOptions>) => Validator<TT>`);
301
+ this.writeln(`static validator: <TT extends TAtscriptAnnotatedTypeConstructor = typeof ${asClass}>(opts?: Partial<TValidatorOptions>) => Validator<TT>`);
302
302
  this.writeln("static toJsonSchema: () => any");
303
303
  }
304
304
  this.pop();
@@ -327,33 +327,33 @@ else this.writeln("{}");
327
327
  renderAnnotate(node) {
328
328
  if (node.isMutating) return;
329
329
  const targetName = node.targetName;
330
- const unwound = this.doc.unwindType(targetName);
331
- if (!unwound?.def) return;
332
- const def = this.doc.mergeIntersection(unwound.def);
333
330
  this.writeln();
334
331
  const exported = node.token("export")?.text === "export";
335
332
  this.renderJsDoc(node);
336
- if (isStructure(def) || isInterface(def)) {
337
- this.write(exported ? "export declare " : "declare ");
338
- this.write(`class ${node.id} `);
339
- this.renderStructure(def, node.id);
340
- } else {
333
+ if (this.isTypeTarget(targetName)) {
341
334
  this.write(exported ? "export " : "declare ");
342
- this.write(`type ${node.id} = `);
343
- this.renderTypeDef(def);
335
+ this.write(`type ${node.id} = ${targetName}`);
336
+ this.writeln();
337
+ const unwound = this.doc.unwindType(targetName);
338
+ this.renderTypeNamespaceFor(node.id, unwound?.def);
339
+ } else {
340
+ this.write(exported ? "export declare " : "declare ");
341
+ this.writeln(`class ${node.id} extends ${targetName} {}`);
342
+ this.writeln();
344
343
  }
345
- this.writeln();
346
344
  }
347
345
  renderTypeNamespace(node) {
348
- this.write(`declare namespace ${node.id} `);
346
+ this.renderTypeNamespaceFor(node.id, node.getDefinition());
347
+ }
348
+ renderTypeNamespaceFor(name, inputDef) {
349
+ this.write(`declare namespace ${name} `);
349
350
  this.blockln("{}");
350
- const def = node.getDefinition();
351
351
  let typeDef = "TAtscriptTypeDef";
352
- if (def) {
353
- let realDef = def;
354
- if (isRef(def)) realDef = this.doc.unwindType(def.id, def.chain)?.def || realDef;
352
+ if (inputDef) {
353
+ let realDef = inputDef;
354
+ if (isRef(inputDef)) realDef = this.doc.unwindType(inputDef.id, inputDef.chain)?.def || realDef;
355
355
  realDef = this.doc.mergeIntersection(realDef);
356
- if (isStructure(realDef) || isInterface(realDef)) typeDef = `TAtscriptTypeObject<keyof ${node.id}>`;
356
+ if (isStructure(realDef) || isInterface(realDef)) typeDef = `TAtscriptTypeObject<keyof ${name}>`;
357
357
  else if (isGroup(realDef)) typeDef = "TAtscriptTypeComplex";
358
358
  else if (isArray(realDef)) typeDef = "TAtscriptTypeArray";
359
359
  else if (isPrimitive(realDef)) typeDef = "TAtscriptTypeFinal";
@@ -361,10 +361,19 @@ else if (isPrimitive(realDef)) typeDef = "TAtscriptTypeFinal";
361
361
  this.writeln(`const __is_atscript_annotated_type: true`);
362
362
  this.writeln(`const type: ${typeDef}`);
363
363
  this.writeln(`const metadata: TMetadataMap<AtscriptMetadata>`);
364
- this.writeln(`const validator: <TT extends TAtscriptAnnotatedTypeConstructor = ${node.id}>(opts?: Partial<TValidatorOptions>) => Validator<TT>`);
364
+ this.writeln(`const validator: (opts?: Partial<TValidatorOptions>) => Validator<TAtscriptAnnotatedTypeConstructor, ${name}>`);
365
365
  this.writeln("const toJsonSchema: () => any");
366
366
  this.popln();
367
367
  }
368
+ isTypeTarget(name, doc) {
369
+ const d = doc || this.doc;
370
+ const decl = d.getDeclarationOwnerNode(name);
371
+ if (!decl?.node) return false;
372
+ if (decl.node.entity === "type") return true;
373
+ if (decl.node.entity === "interface") return false;
374
+ if (decl.node.entity === "annotate") return this.isTypeTarget(decl.node.targetName, decl.doc);
375
+ return false;
376
+ }
368
377
  renderJsDoc(node) {
369
378
  const range = node.token("identifier")?.range;
370
379
  const rangeStr = range ? `:${range.start.line + 1}:${range.start.character + 1}` : "";
@@ -733,6 +742,15 @@ var ValidatorError = class extends Error {
733
742
  function isAnnotatedType(type) {
734
743
  return type && type.__is_atscript_annotated_type;
735
744
  }
745
+ function annotate(metadata, key, value, asArray) {
746
+ if (!metadata) return;
747
+ if (asArray) if (metadata.has(key)) {
748
+ const a = metadata.get(key);
749
+ if (Array.isArray(a)) a.push(value);
750
+ else metadata.set(key, [a, value]);
751
+ } else metadata.set(key, [value]);
752
+ else metadata.set(key, value);
753
+ }
736
754
  function defineAnnotatedType(_kind, base) {
737
755
  const kind = _kind || "";
738
756
  const type = base?.type || {};
@@ -832,12 +850,7 @@ else if (!newBase) throw new Error(`"${typeName}" is not annotated type`);
832
850
  return this;
833
851
  },
834
852
  annotate(key, value, asArray) {
835
- if (asArray) if (this.$metadata.has(key)) {
836
- const a = this.$metadata.get(key);
837
- if (Array.isArray(a)) a.push(value);
838
- else this.$metadata.set(key, [a, value]);
839
- } else this.$metadata.set(key, [value]);
840
- else this.$metadata.set(key, value);
853
+ annotate(this.$metadata, key, value, asArray);
841
854
  return this;
842
855
  }
843
856
  };
@@ -941,7 +954,7 @@ var JsRenderer = class extends BaseRenderer {
941
954
  pre() {
942
955
  this.writeln("// prettier-ignore-start");
943
956
  this.writeln("/* eslint-disable */");
944
- const imports = ["defineAnnotatedType as $"];
957
+ const imports = ["defineAnnotatedType as $", "annotate as $a"];
945
958
  if (!this.opts?.preRenderJsonSchema) imports.push("buildJsonSchema as $$");
946
959
  this.writeln(`import { ${imports.join(", ")} } from "@atscript/typescript/utils"`);
947
960
  }
@@ -960,37 +973,42 @@ var JsRenderer = class extends BaseRenderer {
960
973
  post() {
961
974
  for (const node of this.postAnnotate) if (node.entity === "annotate") {
962
975
  const annotateNode = node;
963
- const unwound = this.doc.unwindType(annotateNode.targetName);
964
- if (unwound?.def) {
965
- let def = this.doc.mergeIntersection(unwound.def);
966
- if (isInterface(def)) def = def.getDefinition() || def;
967
- this._adHocAnnotations = this.buildAdHocMap([annotateNode]);
968
- this.annotateType(def, node.id);
969
- this._adHocAnnotations = null;
970
- this.indent();
971
- this.defineMetadataForAnnotateAlias(annotateNode);
972
- this.unindent();
973
- this.writeln();
976
+ if (annotateNode.isMutating) this.renderMutatingAnnotateNode(annotateNode);
977
+ else {
978
+ const unwound = this.doc.unwindType(annotateNode.targetName);
979
+ if (unwound?.def) {
980
+ let def = this.doc.mergeIntersection(unwound.def);
981
+ if (isInterface(def)) def = def.getDefinition() || def;
982
+ this._adHocAnnotations = this.buildAdHocMap([annotateNode]);
983
+ this.annotateType(def, node.id);
984
+ this._adHocAnnotations = null;
985
+ this.indent();
986
+ this.defineMetadataForAnnotateAlias(annotateNode);
987
+ this.unindent();
988
+ this.writeln();
989
+ }
974
990
  }
975
991
  } else {
976
- const mutatingNodes = this.doc.getAnnotateNodesFor(node.id).filter((n) => n.isMutating);
977
- this._adHocAnnotations = this.buildAdHocMap(mutatingNodes);
978
992
  this.annotateType(node.getDefinition(), node.id);
979
- this._adHocAnnotations = null;
980
993
  this.indent().defineMetadata(node).unindent();
981
994
  this.writeln();
982
995
  }
983
- this.renderMutatingAnnotates();
984
996
  this.writeln("// prettier-ignore-end");
985
997
  super.post();
986
998
  }
999
+ renderClassStatics(node) {
1000
+ this.writeln("static __is_atscript_annotated_type = true");
1001
+ this.writeln("static type = {}");
1002
+ this.writeln("static metadata = new Map()");
1003
+ this.renderJsonSchemaMethod(node);
1004
+ }
987
1005
  renderInterface(node) {
988
1006
  this.writeln();
989
1007
  const exported = node.token("export")?.text === "export";
990
1008
  this.write(exported ? "export " : "");
991
1009
  this.write(`class ${node.id} `);
992
1010
  this.blockln("{}");
993
- this.renderJsonSchemaMethod(node);
1011
+ this.renderClassStatics(node);
994
1012
  this.popln();
995
1013
  this.postAnnotate.push(node);
996
1014
  this.writeln();
@@ -1001,14 +1019,14 @@ var JsRenderer = class extends BaseRenderer {
1001
1019
  this.write(exported ? "export " : "");
1002
1020
  this.write(`class ${node.id} `);
1003
1021
  this.blockln("{}");
1004
- this.renderJsonSchemaMethod(node);
1022
+ this.renderClassStatics(node);
1005
1023
  this.popln();
1006
1024
  this.postAnnotate.push(node);
1007
1025
  this.writeln();
1008
1026
  }
1009
1027
  renderAnnotate(node) {
1010
1028
  if (node.isMutating) {
1011
- this.mutatingAnnotates.push(node);
1029
+ this.postAnnotate.push(node);
1012
1030
  return;
1013
1031
  }
1014
1032
  const targetName = node.targetName;
@@ -1019,7 +1037,7 @@ var JsRenderer = class extends BaseRenderer {
1019
1037
  this.write(exported ? "export " : "");
1020
1038
  this.write(`class ${node.id} `);
1021
1039
  this.blockln("{}");
1022
- this.renderJsonSchemaMethod(node);
1040
+ this.renderClassStatics(node);
1023
1041
  this.popln();
1024
1042
  this.postAnnotate.push(node);
1025
1043
  this.writeln();
@@ -1296,18 +1314,13 @@ else handle.prop(prop.id, propHandle.$type);
1296
1314
  return this;
1297
1315
  }
1298
1316
  defineMetadata(node) {
1299
- const annotations = this.doc.evalAnnotationsForNode(node);
1300
- let adHocNames;
1301
- let adHoc;
1317
+ let annotations = this.doc.evalAnnotationsForNode(node);
1302
1318
  if (this._adHocAnnotations && this._propPath.length > 0) {
1303
1319
  const path$1 = this._propPath.join(".");
1304
- adHoc = this._adHocAnnotations.get(path$1);
1305
- if (adHoc) adHocNames = new Set(adHoc.map((a) => a.name));
1320
+ const adHoc = this._adHocAnnotations.get(path$1);
1321
+ if (adHoc) annotations = this.doc.mergeNodesAnnotations(annotations, adHoc);
1306
1322
  }
1307
1323
  annotations?.forEach((an) => {
1308
- if (!adHocNames || !adHocNames.has(an.name)) this.resolveAnnotationValue(node, an);
1309
- });
1310
- adHoc?.forEach((an) => {
1311
1324
  this.resolveAnnotationValue(node, an);
1312
1325
  });
1313
1326
  return this;
@@ -1319,11 +1332,8 @@ else handle.prop(prop.id, propHandle.$type);
1319
1332
  const annotateAnnotations = this.doc.evalAnnotationsForNode(annotateNode);
1320
1333
  const targetDecl = this.doc.getDeclarationOwnerNode(annotateNode.targetName);
1321
1334
  const targetAnnotations = targetDecl?.node ? targetDecl.doc.evalAnnotationsForNode(targetDecl.node) : undefined;
1322
- const overriddenNames = new Set(annotateAnnotations?.map((a) => a.name));
1323
- targetAnnotations?.forEach((an) => {
1324
- if (!overriddenNames.has(an.name)) this.resolveAnnotationValue(annotateNode, an);
1325
- });
1326
- annotateAnnotations?.forEach((an) => {
1335
+ const merged = this.doc.mergeNodesAnnotations(targetAnnotations, annotateAnnotations);
1336
+ merged.forEach((an) => {
1327
1337
  this.resolveAnnotationValue(annotateNode, an);
1328
1338
  });
1329
1339
  return this;
@@ -1362,47 +1372,123 @@ else targetValue = "true";
1362
1372
  multiple: !!multiple
1363
1373
  };
1364
1374
  }
1365
- renderMutatingAnnotates() {
1366
- for (const node of this.mutatingAnnotates) {
1367
- const targetName = node.targetName;
1368
- for (const entry of node.entries) {
1369
- const anns = entry.annotations;
1370
- if (!anns || anns.length === 0) continue;
1371
- const parts = entry.hasChain ? [entry.id, ...entry.chain.map((c) => c.text)] : [entry.id];
1372
- let accessor = targetName;
1373
- for (const part of parts) accessor += `.type.props.get("${escapeQuotes(part)}")?`;
1375
+ renderMutatingAnnotateNode(node) {
1376
+ const targetName = node.targetName;
1377
+ const targetDef = this.resolveTargetDef(targetName);
1378
+ this.writeln("// Ad-hoc annotations for ", targetName);
1379
+ for (const entry of node.entries) {
1380
+ const anns = entry.annotations;
1381
+ if (!anns || anns.length === 0) continue;
1382
+ const parts = entry.hasChain ? [entry.id, ...entry.chain.map((c) => c.text)] : [entry.id];
1383
+ const accessors = this.buildMutatingAccessors(targetName, targetDef, parts);
1384
+ for (const accessor of accessors) {
1385
+ const cleared = new Set();
1374
1386
  for (const an of anns) {
1375
1387
  const { value, multiple } = this.computeAnnotationValue(entry, an);
1376
1388
  if (multiple) {
1377
- this.writeln(`{`);
1378
- this.indent();
1379
- this.writeln(`const __t = ${accessor}.metadata`);
1380
- this.writeln(`const __k = "${escapeQuotes(an.name)}"`);
1381
- this.writeln(`const __v = ${value}`);
1382
- this.writeln(`if (__t) { const __e = __t.get(__k); __t.set(__k, Array.isArray(__e) ? [...__e, __v] : __e !== undefined ? [__e, __v] : [__v]) }`);
1383
- this.unindent();
1384
- this.writeln(`}`);
1385
- } else this.writeln(`${accessor}.metadata.set("${escapeQuotes(an.name)}", ${value})`);
1389
+ if (!cleared.has(an.name)) {
1390
+ const spec = this.doc.resolveAnnotation(an.name);
1391
+ if (!spec || spec.config.mergeStrategy !== "append") this.writeln(`${accessor}.metadata.delete("${escapeQuotes(an.name)}")`);
1392
+ cleared.add(an.name);
1393
+ }
1394
+ this.writeln(`$a(${accessor}.metadata, "${escapeQuotes(an.name)}", ${value}, true)`);
1395
+ } else this.writeln(`$a(${accessor}.metadata, "${escapeQuotes(an.name)}", ${value})`);
1386
1396
  }
1387
1397
  }
1388
- const topAnnotations = node.annotations;
1389
- if (topAnnotations && topAnnotations.length > 0) for (const an of topAnnotations) {
1398
+ }
1399
+ const topAnnotations = node.annotations;
1400
+ if (topAnnotations && topAnnotations.length > 0) {
1401
+ const cleared = new Set();
1402
+ for (const an of topAnnotations) {
1390
1403
  const { value, multiple } = this.computeAnnotationValue(node, an);
1391
1404
  if (multiple) {
1392
- this.writeln(`{`);
1393
- this.indent();
1394
- this.writeln(`const __t = ${targetName}.metadata`);
1395
- this.writeln(`const __k = "${escapeQuotes(an.name)}"`);
1396
- this.writeln(`const __v = ${value}`);
1397
- this.writeln(`if (__t) { const __e = __t.get(__k); __t.set(__k, Array.isArray(__e) ? [...__e, __v] : __e !== undefined ? [__e, __v] : [__v]) }`);
1398
- this.unindent();
1399
- this.writeln(`}`);
1400
- } else this.writeln(`${targetName}.metadata.set("${escapeQuotes(an.name)}", ${value})`);
1405
+ if (!cleared.has(an.name)) {
1406
+ const spec = this.doc.resolveAnnotation(an.name);
1407
+ if (!spec || spec.config.mergeStrategy !== "append") this.writeln(`${targetName}.metadata.delete("${escapeQuotes(an.name)}")`);
1408
+ cleared.add(an.name);
1409
+ }
1410
+ this.writeln(`$a(${targetName}.metadata, "${escapeQuotes(an.name)}", ${value}, true)`);
1411
+ } else this.writeln(`$a(${targetName}.metadata, "${escapeQuotes(an.name)}", ${value})`);
1412
+ }
1413
+ }
1414
+ this.writeln();
1415
+ }
1416
+ resolveTargetDef(targetName) {
1417
+ const unwound = this.doc.unwindType(targetName);
1418
+ if (!unwound?.def) return undefined;
1419
+ let def = unwound.def;
1420
+ if (isInterface(def)) def = def.getDefinition() || def;
1421
+ return def;
1422
+ }
1423
+ /**
1424
+ * Builds the runtime accessor paths for mutating annotate entries.
1425
+ * Computes exact paths at compile time by walking the AST,
1426
+ * so the generated JS accesses props directly without runtime search.
1427
+ * Returns multiple paths when a property appears in multiple union branches.
1428
+ */ buildMutatingAccessors(targetName, targetDef, parts) {
1429
+ let accessors = [{
1430
+ prefix: targetName + ".type",
1431
+ def: targetDef
1432
+ }];
1433
+ for (let i = 0; i < parts.length; i++) {
1434
+ const nextAccessors = [];
1435
+ for (const { prefix, def } of accessors) {
1436
+ const results = this.buildPropPaths(def, parts[i]);
1437
+ if (results.length > 0) for (const result of results) if (i < parts.length - 1) nextAccessors.push({
1438
+ prefix: prefix + result.path + "?.type",
1439
+ def: result.propDef
1440
+ });
1441
+ else nextAccessors.push({
1442
+ prefix: prefix + result.path + "?",
1443
+ def: result.propDef
1444
+ });
1445
+ else {
1446
+ const suffix = `.props.get("${escapeQuotes(parts[i])}")` + (i < parts.length - 1 ? "?.type" : "?");
1447
+ nextAccessors.push({
1448
+ prefix: prefix + suffix,
1449
+ def: undefined
1450
+ });
1451
+ }
1401
1452
  }
1453
+ accessors = nextAccessors;
1454
+ }
1455
+ return accessors.map((a) => a.prefix);
1456
+ }
1457
+ /**
1458
+ * Finds a property in a type tree at compile time, returning all
1459
+ * matching runtime path strings and prop definitions for further chaining.
1460
+ * Returns multiple results when the same property appears in different union branches.
1461
+ */ buildPropPaths(def, propName) {
1462
+ if (!def) return [];
1463
+ def = this.doc.mergeIntersection(def);
1464
+ if (isRef(def)) {
1465
+ const ref = def;
1466
+ const unwound = this.doc.unwindType(ref.id, ref.chain)?.def;
1467
+ return this.buildPropPaths(unwound, propName);
1468
+ }
1469
+ if (isInterface(def)) return this.buildPropPaths(def.getDefinition(), propName);
1470
+ if (isStructure(def)) {
1471
+ const prop = def.props.get(propName);
1472
+ if (prop) return [{
1473
+ path: `.props.get("${escapeQuotes(propName)}")`,
1474
+ propDef: prop.getDefinition()
1475
+ }];
1476
+ return [];
1477
+ }
1478
+ if (isGroup(def)) {
1479
+ const group = def;
1480
+ const items = group.unwrap();
1481
+ const results = [];
1482
+ for (let i = 0; i < items.length; i++) for (const result of this.buildPropPaths(items[i], propName)) results.push({
1483
+ path: `.items[${i}].type${result.path}`,
1484
+ propDef: result.propDef
1485
+ });
1486
+ return results;
1402
1487
  }
1488
+ return [];
1403
1489
  }
1404
1490
  constructor(doc, opts) {
1405
- super(doc), _define_property(this, "opts", void 0), _define_property(this, "postAnnotate", void 0), _define_property(this, "mutatingAnnotates", void 0), _define_property(this, "_adHocAnnotations", void 0), _define_property(this, "_propPath", void 0), this.opts = opts, this.postAnnotate = [], this.mutatingAnnotates = [], this._adHocAnnotations = null, this._propPath = [];
1491
+ super(doc), _define_property(this, "opts", void 0), _define_property(this, "postAnnotate", void 0), _define_property(this, "_adHocAnnotations", void 0), _define_property(this, "_propPath", void 0), this.opts = opts, this.postAnnotate = [], this._adHocAnnotations = null, this._propPath = [];
1406
1492
  }
1407
1493
  };
1408
1494
 
package/dist/utils.cjs CHANGED
@@ -338,6 +338,15 @@ var ValidatorError = class extends Error {
338
338
  function isAnnotatedType(type) {
339
339
  return type && type.__is_atscript_annotated_type;
340
340
  }
341
+ function annotate(metadata, key, value, asArray) {
342
+ if (!metadata) return;
343
+ if (asArray) if (metadata.has(key)) {
344
+ const a = metadata.get(key);
345
+ if (Array.isArray(a)) a.push(value);
346
+ else metadata.set(key, [a, value]);
347
+ } else metadata.set(key, [value]);
348
+ else metadata.set(key, value);
349
+ }
341
350
  function defineAnnotatedType(_kind, base) {
342
351
  const kind = _kind || "";
343
352
  const type = base?.type || {};
@@ -437,12 +446,7 @@ else if (!newBase) throw new Error(`"${typeName}" is not annotated type`);
437
446
  return this;
438
447
  },
439
448
  annotate(key, value, asArray) {
440
- if (asArray) if (this.$metadata.has(key)) {
441
- const a = this.$metadata.get(key);
442
- if (Array.isArray(a)) a.push(value);
443
- else this.$metadata.set(key, [a, value]);
444
- } else this.$metadata.set(key, [value]);
445
- else this.$metadata.set(key, value);
449
+ annotate(this.$metadata, key, value, asArray);
446
450
  return this;
447
451
  }
448
452
  };
@@ -546,6 +550,7 @@ else schema.allOf = (schema.allOf || []).concat(patterns.map((p) => ({ pattern:
546
550
  //#endregion
547
551
  exports.Validator = Validator
548
552
  exports.ValidatorError = ValidatorError
553
+ exports.annotate = annotate
549
554
  exports.buildJsonSchema = buildJsonSchema
550
555
  exports.defineAnnotatedType = defineAnnotatedType
551
556
  exports.isAnnotatedType = isAnnotatedType
package/dist/utils.d.ts CHANGED
@@ -18,10 +18,10 @@ interface TValidatorPluginContext {
18
18
  error: Validator<any>['error'];
19
19
  path: Validator<any>['path'];
20
20
  }
21
- declare class Validator<T extends TAtscriptAnnotatedTypeConstructor> {
22
- protected readonly def: T | TAtscriptAnnotatedType<any>;
21
+ declare class Validator<T extends TAtscriptAnnotatedTypeConstructor, IT = InstanceType<T>> {
22
+ protected readonly def: T;
23
23
  protected opts: TValidatorOptions;
24
- constructor(def: T | TAtscriptAnnotatedType<any>, opts?: Partial<TValidatorOptions>);
24
+ constructor(def: T, opts?: Partial<TValidatorOptions>);
25
25
  errors: TError[];
26
26
  protected stackErrors: TError[][];
27
27
  protected stackPath: string[];
@@ -31,7 +31,7 @@ declare class Validator<T extends TAtscriptAnnotatedTypeConstructor> {
31
31
  protected clear(): void;
32
32
  protected error(message: string, path?: string, details?: TError[]): void;
33
33
  protected throw(): void;
34
- validate<TT = T>(value: any, safe?: boolean): value is TT;
34
+ validate<TT = IT>(value: any, safe?: boolean): value is TT;
35
35
  protected validateSafe(def: TAtscriptAnnotatedType, value: any): boolean;
36
36
  protected get path(): string;
37
37
  protected validateAnnotatedType(def: TAtscriptAnnotatedType, value: any): boolean;
@@ -94,6 +94,11 @@ type TAtscriptAnnotatedTypeConstructor = TAtscriptAnnotatedType & (new (...args:
94
94
  * Type Guard to check if a type is atscript-annotated
95
95
  */
96
96
  declare function isAnnotatedType(type: any): type is TAtscriptAnnotatedType;
97
+ /**
98
+ * Standalone annotate function that handles both replace and append (array) strategies.
99
+ * Used by the handle's .annotate() method and by generated mutation statements.
100
+ */
101
+ declare function annotate<K extends keyof AtscriptMetadata>(metadata: TMetadataMap<AtscriptMetadata> | undefined, key: K, value: AtscriptMetadata[K] extends (infer E)[] ? E : AtscriptMetadata[K], asArray?: boolean): void;
97
102
  type TKind = '' | 'array' | 'object' | 'union' | 'intersection' | 'tuple';
98
103
  declare function defineAnnotatedType(_kind?: TKind, base?: any): TAnnotatedTypeHandle;
99
104
  /**
@@ -129,4 +134,5 @@ declare function isAnnotatedTypeOfPrimitive(t: TAtscriptAnnotatedType): boolean;
129
134
  type TJsonSchema = Record<string, any>;
130
135
  declare function buildJsonSchema(type: TAtscriptAnnotatedType): TJsonSchema;
131
136
 
132
- 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, buildJsonSchema, defineAnnotatedType, isAnnotatedType, isAnnotatedTypeOfPrimitive };
137
+ export { Validator, ValidatorError, annotate, buildJsonSchema, defineAnnotatedType, isAnnotatedType, isAnnotatedTypeOfPrimitive };
138
+ export type { TAnnotatedTypeHandle, TAtscriptAnnotatedType, TAtscriptAnnotatedTypeConstructor, TAtscriptTypeArray, TAtscriptTypeComplex, TAtscriptTypeDef, TAtscriptTypeFinal, TAtscriptTypeObject, TMetadataMap, TValidatorOptions, TValidatorPlugin, TValidatorPluginContext };
package/dist/utils.mjs CHANGED
@@ -337,6 +337,15 @@ var ValidatorError = class extends Error {
337
337
  function isAnnotatedType(type) {
338
338
  return type && type.__is_atscript_annotated_type;
339
339
  }
340
+ function annotate(metadata, key, value, asArray) {
341
+ if (!metadata) return;
342
+ if (asArray) if (metadata.has(key)) {
343
+ const a = metadata.get(key);
344
+ if (Array.isArray(a)) a.push(value);
345
+ else metadata.set(key, [a, value]);
346
+ } else metadata.set(key, [value]);
347
+ else metadata.set(key, value);
348
+ }
340
349
  function defineAnnotatedType(_kind, base) {
341
350
  const kind = _kind || "";
342
351
  const type = base?.type || {};
@@ -436,12 +445,7 @@ else if (!newBase) throw new Error(`"${typeName}" is not annotated type`);
436
445
  return this;
437
446
  },
438
447
  annotate(key, value, asArray) {
439
- if (asArray) if (this.$metadata.has(key)) {
440
- const a = this.$metadata.get(key);
441
- if (Array.isArray(a)) a.push(value);
442
- else this.$metadata.set(key, [a, value]);
443
- } else this.$metadata.set(key, [value]);
444
- else this.$metadata.set(key, value);
448
+ annotate(this.$metadata, key, value, asArray);
445
449
  return this;
446
450
  }
447
451
  };
@@ -543,4 +547,4 @@ else schema.allOf = (schema.allOf || []).concat(patterns.map((p) => ({ pattern:
543
547
  }
544
548
 
545
549
  //#endregion
546
- export { Validator, ValidatorError, buildJsonSchema, defineAnnotatedType, isAnnotatedType, isAnnotatedTypeOfPrimitive };
550
+ export { Validator, ValidatorError, annotate, buildJsonSchema, defineAnnotatedType, isAnnotatedType, isAnnotatedTypeOfPrimitive };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atscript/typescript",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
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.0"
73
+ "@atscript/core": "^0.1.2"
74
74
  },
75
75
  "dependencies": {
76
76
  "@moostjs/event-cli": "^0.5.32",