@atscript/typescript 0.1.16 → 0.1.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.cjs +84 -45
- package/dist/index.cjs +79 -40
- package/dist/index.mjs +79 -40
- package/dist/utils.cjs +35 -17
- package/dist/utils.d.ts +5 -5
- package/dist/utils.mjs +35 -17
- package/package.json +42 -42
package/dist/index.cjs
CHANGED
|
@@ -22,8 +22,8 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
22
22
|
}) : target, mod));
|
|
23
23
|
|
|
24
24
|
//#endregion
|
|
25
|
-
const __atscript_core = __toESM(require("@atscript/core"));
|
|
26
25
|
const path = __toESM(require("path"));
|
|
26
|
+
const __atscript_core = __toESM(require("@atscript/core"));
|
|
27
27
|
|
|
28
28
|
//#region packages/typescript/src/codegen/code-printer.ts
|
|
29
29
|
function _define_property$4(obj, key, value) {
|
|
@@ -108,7 +108,7 @@ else if (this.currentLine.length > 0) this.lines.push(this.currentLine);
|
|
|
108
108
|
return this;
|
|
109
109
|
}
|
|
110
110
|
doPop(withNewLine) {
|
|
111
|
-
if (
|
|
111
|
+
if (this.blockStack.length === 0) throw new Error("No block to pop (stack is empty).");
|
|
112
112
|
const closing = this.blockStack.pop();
|
|
113
113
|
this.unindent();
|
|
114
114
|
if (withNewLine) this.writeln(closing);
|
|
@@ -307,7 +307,7 @@ var TypeRenderer = class TypeRenderer extends BaseRenderer {
|
|
|
307
307
|
propsDefs.add(renderedDef);
|
|
308
308
|
renderedDef.split("\n").forEach((l) => this.writeln(l));
|
|
309
309
|
}
|
|
310
|
-
if (patterns.length) {
|
|
310
|
+
if (patterns.length > 0) {
|
|
311
311
|
this.write(`[key: string]: `);
|
|
312
312
|
if (patterns.length > 0) {
|
|
313
313
|
for (const prop of patterns) propsDefs.add(this.renderTypeDefString(prop.getDefinition()));
|
|
@@ -585,7 +585,7 @@ var Validator = class {
|
|
|
585
585
|
}
|
|
586
586
|
let i = 0;
|
|
587
587
|
for (const item of def.type.items) {
|
|
588
|
-
this.push(
|
|
588
|
+
this.push(String(i));
|
|
589
589
|
if (!this.validateSafe(item, value[i])) {
|
|
590
590
|
this.pop(true);
|
|
591
591
|
return false;
|
|
@@ -621,7 +621,7 @@ var Validator = class {
|
|
|
621
621
|
let i = 0;
|
|
622
622
|
let passed = true;
|
|
623
623
|
for (const item of value) {
|
|
624
|
-
this.push(
|
|
624
|
+
this.push(String(i));
|
|
625
625
|
if (!this.validateSafe(def.type.of, item)) {
|
|
626
626
|
passed = false;
|
|
627
627
|
this.pop(true);
|
|
@@ -673,7 +673,7 @@ else {
|
|
|
673
673
|
pattern,
|
|
674
674
|
def: propDef
|
|
675
675
|
});
|
|
676
|
-
if (matched.length) {
|
|
676
|
+
if (matched.length > 0) {
|
|
677
677
|
let keyPassed = false;
|
|
678
678
|
for (const { def: def$1 } of matched) if (this.validateSafe(def$1, value[key])) {
|
|
679
679
|
this.pop(false);
|
|
@@ -700,7 +700,7 @@ else {
|
|
|
700
700
|
return passed;
|
|
701
701
|
}
|
|
702
702
|
validatePrimitive(def, value) {
|
|
703
|
-
if (
|
|
703
|
+
if (def.type.value !== undefined) {
|
|
704
704
|
if (value !== def.type.value) {
|
|
705
705
|
this.error(`Expected ${def.type.value}, got ${value}`);
|
|
706
706
|
return false;
|
|
@@ -709,40 +709,46 @@ else {
|
|
|
709
709
|
}
|
|
710
710
|
const typeOfValue = Array.isArray(value) ? "array" : typeof value;
|
|
711
711
|
switch (def.type.designType) {
|
|
712
|
-
case "never":
|
|
712
|
+
case "never": {
|
|
713
713
|
this.error(`This type is impossible, must be an internal problem`);
|
|
714
714
|
return false;
|
|
715
|
+
}
|
|
715
716
|
case "any": return true;
|
|
716
|
-
case "string":
|
|
717
|
+
case "string": {
|
|
717
718
|
if (typeOfValue !== def.type.designType) {
|
|
718
719
|
this.error(`Expected ${def.type.designType}, got ${typeOfValue}`);
|
|
719
720
|
return false;
|
|
720
721
|
}
|
|
721
722
|
return this.validateString(def, value);
|
|
722
|
-
|
|
723
|
+
}
|
|
724
|
+
case "number": {
|
|
723
725
|
if (typeOfValue !== def.type.designType) {
|
|
724
726
|
this.error(`Expected ${def.type.designType}, got ${typeOfValue}`);
|
|
725
727
|
return false;
|
|
726
728
|
}
|
|
727
729
|
return this.validateNumber(def, value);
|
|
728
|
-
|
|
730
|
+
}
|
|
731
|
+
case "boolean": {
|
|
729
732
|
if (typeOfValue !== def.type.designType) {
|
|
730
733
|
this.error(`Expected ${def.type.designType}, got ${typeOfValue}`);
|
|
731
734
|
return false;
|
|
732
735
|
}
|
|
733
736
|
return this.validateBoolean(def, value);
|
|
734
|
-
|
|
737
|
+
}
|
|
738
|
+
case "undefined": {
|
|
735
739
|
if (value !== undefined) {
|
|
736
740
|
this.error(`Expected ${def.type.designType}, got ${typeOfValue}`);
|
|
737
741
|
return false;
|
|
738
742
|
}
|
|
739
743
|
return true;
|
|
740
|
-
|
|
744
|
+
}
|
|
745
|
+
case "null": {
|
|
741
746
|
if (value !== null) {
|
|
742
747
|
this.error(`Expected ${def.type.designType}, got ${typeOfValue}`);
|
|
743
748
|
return false;
|
|
744
749
|
}
|
|
745
750
|
return true;
|
|
751
|
+
}
|
|
746
752
|
default: throw new Error(`Unknown type "${def.type.designType}"`);
|
|
747
753
|
}
|
|
748
754
|
}
|
|
@@ -954,7 +960,6 @@ else throw new Error(`Can't find prop ${typeName}${keys}`);
|
|
|
954
960
|
}
|
|
955
961
|
if (!newBase && keys) throw new Error(`Can't find prop ${typeName}${keys}`);
|
|
956
962
|
else if (!newBase) throw new Error(`"${typeName}" is not annotated type`);
|
|
957
|
-
for (const [k, v] of newBase.metadata.entries()) if (!metadata.has(k)) metadata.set(k, Array.isArray(v) ? [...v] : v);
|
|
958
963
|
this.$type = {
|
|
959
964
|
__is_atscript_annotated_type: true,
|
|
960
965
|
type: newBase.type,
|
|
@@ -998,7 +1003,7 @@ function buildJsonSchema(type) {
|
|
|
998
1003
|
type: "object",
|
|
999
1004
|
properties
|
|
1000
1005
|
};
|
|
1001
|
-
if (required.length) schema.required = required;
|
|
1006
|
+
if (required.length > 0) schema.required = required;
|
|
1002
1007
|
return schema;
|
|
1003
1008
|
},
|
|
1004
1009
|
array(d) {
|
|
@@ -1261,34 +1266,39 @@ else handle.prop(prop.id, propHandle.$type);
|
|
|
1261
1266
|
annotations?.forEach((a) => {
|
|
1262
1267
|
switch (a.name) {
|
|
1263
1268
|
case "expect.minLength":
|
|
1264
|
-
case "expect.maxLength":
|
|
1269
|
+
case "expect.maxLength": {
|
|
1265
1270
|
if (a.args[0]) handle.annotate(a.name, {
|
|
1266
1271
|
length: Number(a.args[0].text),
|
|
1267
1272
|
message: a.args[1]?.text
|
|
1268
1273
|
});
|
|
1269
1274
|
break;
|
|
1270
|
-
|
|
1275
|
+
}
|
|
1276
|
+
case "expect.min": {
|
|
1271
1277
|
if (a.args[0]) handle.annotate(a.name, {
|
|
1272
1278
|
minValue: Number(a.args[0].text),
|
|
1273
1279
|
message: a.args[1]?.text
|
|
1274
1280
|
});
|
|
1275
1281
|
break;
|
|
1276
|
-
|
|
1282
|
+
}
|
|
1283
|
+
case "expect.max": {
|
|
1277
1284
|
if (a.args[0]) handle.annotate(a.name, {
|
|
1278
1285
|
maxValue: Number(a.args[0].text),
|
|
1279
1286
|
message: a.args[1]?.text
|
|
1280
1287
|
});
|
|
1281
1288
|
break;
|
|
1282
|
-
|
|
1289
|
+
}
|
|
1290
|
+
case "expect.pattern": {
|
|
1283
1291
|
handle.annotate(a.name, {
|
|
1284
1292
|
pattern: a.args[0]?.text || "",
|
|
1285
1293
|
flags: a.args[1]?.text,
|
|
1286
1294
|
message: a.args[2]?.text
|
|
1287
1295
|
}, true);
|
|
1288
1296
|
break;
|
|
1289
|
-
|
|
1297
|
+
}
|
|
1298
|
+
case "expect.int": {
|
|
1290
1299
|
handle.annotate(a.name, true);
|
|
1291
1300
|
break;
|
|
1301
|
+
}
|
|
1292
1302
|
default:
|
|
1293
1303
|
}
|
|
1294
1304
|
});
|
|
@@ -1303,11 +1313,24 @@ else handle.prop(prop.id, propHandle.$type);
|
|
|
1303
1313
|
const ref = node;
|
|
1304
1314
|
const decl = this.doc.unwindType(ref.id, ref.chain)?.def;
|
|
1305
1315
|
if ((0, __atscript_core.isPrimitive)(decl)) {
|
|
1306
|
-
this.
|
|
1307
|
-
|
|
1316
|
+
const ownerDecl = this.doc.getDeclarationOwnerNode(ref.id);
|
|
1317
|
+
if (!ownerDecl?.node || ownerDecl.node.entity !== "type" && ownerDecl.node.entity !== "interface") {
|
|
1318
|
+
this.annotateType(decl, name);
|
|
1319
|
+
return this;
|
|
1320
|
+
}
|
|
1308
1321
|
}
|
|
1309
1322
|
const chain = ref.hasChain ? `, [${ref.chain.map((c) => `"${escapeQuotes(c.text)}"`).join(", ")}]` : "";
|
|
1310
|
-
this.writeln(`$(${name ? `"", ${name}` : ""})`).indent().writeln(`.refTo(${ref.id}${chain})`)
|
|
1323
|
+
this.writeln(`$(${name ? `"", ${name}` : ""})`).indent().writeln(`.refTo(${ref.id}${chain})`);
|
|
1324
|
+
if (!ref.hasChain) {
|
|
1325
|
+
const ownerDecl = this.doc.getDeclarationOwnerNode(ref.id);
|
|
1326
|
+
if (ownerDecl?.node) {
|
|
1327
|
+
const typeAnnotations = ownerDecl.doc.evalAnnotationsForNode(ownerDecl.node);
|
|
1328
|
+
typeAnnotations?.forEach((an) => {
|
|
1329
|
+
this.resolveAnnotationValue(ownerDecl.node, an);
|
|
1330
|
+
});
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1333
|
+
this.unindent();
|
|
1311
1334
|
return this;
|
|
1312
1335
|
}
|
|
1313
1336
|
case "primitive": {
|
|
@@ -1336,7 +1359,7 @@ else handle.prop(prop.id, propHandle.$type);
|
|
|
1336
1359
|
return this;
|
|
1337
1360
|
}
|
|
1338
1361
|
default: {
|
|
1339
|
-
console.log("!!!!!!! UNKNOWN
|
|
1362
|
+
console.log("!!!!!!! UNKNOWN", node.entity);
|
|
1340
1363
|
return this;
|
|
1341
1364
|
}
|
|
1342
1365
|
}
|
|
@@ -1361,7 +1384,7 @@ else handle.prop(prop.id, propHandle.$type);
|
|
|
1361
1384
|
case "final": return this.writeln(`$(${d()}).designType("${def.value === "void" ? "undefined" : def.value}")`);
|
|
1362
1385
|
case "union":
|
|
1363
1386
|
case "intersection":
|
|
1364
|
-
case "tuple":
|
|
1387
|
+
case "tuple": {
|
|
1365
1388
|
this.writeln(`$(${d(def.kind)})`);
|
|
1366
1389
|
this.indent();
|
|
1367
1390
|
for (const itemDef of def.items) {
|
|
@@ -1374,7 +1397,8 @@ else handle.prop(prop.id, propHandle.$type);
|
|
|
1374
1397
|
}
|
|
1375
1398
|
this.unindent();
|
|
1376
1399
|
return;
|
|
1377
|
-
|
|
1400
|
+
}
|
|
1401
|
+
case "array": {
|
|
1378
1402
|
this.writeln(`$(${d("array")})`);
|
|
1379
1403
|
this.indent();
|
|
1380
1404
|
this.write(".of(");
|
|
@@ -1385,7 +1409,8 @@ else handle.prop(prop.id, propHandle.$type);
|
|
|
1385
1409
|
this.writeln(`)`);
|
|
1386
1410
|
this.unindent();
|
|
1387
1411
|
return;
|
|
1388
|
-
|
|
1412
|
+
}
|
|
1413
|
+
case "object": {
|
|
1389
1414
|
this.writeln(`$(${d("object")})`);
|
|
1390
1415
|
this.indent();
|
|
1391
1416
|
for (const [key, propDef] of Object.entries(def.props)) {
|
|
@@ -1412,6 +1437,7 @@ else handle.prop(prop.id, propHandle.$type);
|
|
|
1412
1437
|
}
|
|
1413
1438
|
this.unindent();
|
|
1414
1439
|
return;
|
|
1440
|
+
}
|
|
1415
1441
|
default: return this.writeln(`$(${d()}).designType("any")`);
|
|
1416
1442
|
}
|
|
1417
1443
|
}
|
|
@@ -1451,7 +1477,20 @@ else handle.prop(prop.id, propHandle.$type);
|
|
|
1451
1477
|
return this;
|
|
1452
1478
|
}
|
|
1453
1479
|
defineMetadata(node) {
|
|
1454
|
-
let annotations
|
|
1480
|
+
let annotations;
|
|
1481
|
+
const nodeDef = node.getDefinition?.();
|
|
1482
|
+
if (nodeDef && (0, __atscript_core.isRef)(nodeDef)) {
|
|
1483
|
+
const refNode = nodeDef;
|
|
1484
|
+
if (!refNode.hasChain) {
|
|
1485
|
+
const resolved = this.doc.unwindType(refNode.id, refNode.chain)?.def;
|
|
1486
|
+
if (resolved && !(0, __atscript_core.isPrimitive)(resolved)) annotations = node.annotations ?? [];
|
|
1487
|
+
else if (resolved && (0, __atscript_core.isPrimitive)(resolved)) {
|
|
1488
|
+
const ownerDecl = this.doc.getDeclarationOwnerNode(refNode.id);
|
|
1489
|
+
if (ownerDecl?.node && (ownerDecl.node.entity === "type" || ownerDecl.node.entity === "interface")) annotations = node.annotations ?? [];
|
|
1490
|
+
}
|
|
1491
|
+
}
|
|
1492
|
+
}
|
|
1493
|
+
if (annotations === undefined) annotations = this.doc.evalAnnotationsForNode(node);
|
|
1455
1494
|
if (this._adHocAnnotations && this._propPath.length > 0) {
|
|
1456
1495
|
const path$2 = this._propPath.join(".");
|
|
1457
1496
|
const adHoc = this._adHocAnnotations.get(path$2);
|
|
@@ -1502,7 +1541,7 @@ else targetValue = "true";
|
|
|
1502
1541
|
}
|
|
1503
1542
|
} else {
|
|
1504
1543
|
multiple = node.countAnnotations(an.name) > 1 || an.args.length > 1;
|
|
1505
|
-
if (an.args.length) targetValue = an.args[0].type === "text" ? `"${escapeQuotes(an.args[0].text)}"` : an.args[0].text;
|
|
1544
|
+
if (an.args.length > 0) targetValue = an.args[0].type === "text" ? `"${escapeQuotes(an.args[0].text)}"` : an.args[0].text;
|
|
1506
1545
|
}
|
|
1507
1546
|
return {
|
|
1508
1547
|
value: targetValue,
|
|
@@ -1564,7 +1603,7 @@ else targetValue = "true";
|
|
|
1564
1603
|
* Returns multiple paths when a property appears in multiple union branches.
|
|
1565
1604
|
*/ buildMutatingAccessors(targetName, targetDef, parts) {
|
|
1566
1605
|
let accessors = [{
|
|
1567
|
-
prefix: targetName
|
|
1606
|
+
prefix: `${targetName}.type`,
|
|
1568
1607
|
def: targetDef
|
|
1569
1608
|
}];
|
|
1570
1609
|
for (let i = 0; i < parts.length; i++) {
|
|
@@ -1572,17 +1611,17 @@ else targetValue = "true";
|
|
|
1572
1611
|
for (const { prefix, def } of accessors) {
|
|
1573
1612
|
const results = this.buildPropPaths(def, parts[i]);
|
|
1574
1613
|
if (results.length > 0) for (const result of results) if (i < parts.length - 1) nextAccessors.push({
|
|
1575
|
-
prefix: prefix
|
|
1614
|
+
prefix: `${prefix}${result.path}?.type`,
|
|
1576
1615
|
def: result.propDef
|
|
1577
1616
|
});
|
|
1578
1617
|
else nextAccessors.push({
|
|
1579
|
-
prefix: prefix
|
|
1618
|
+
prefix: `${prefix}${result.path}?`,
|
|
1580
1619
|
def: result.propDef
|
|
1581
1620
|
});
|
|
1582
1621
|
else {
|
|
1583
|
-
const suffix = `.props.get("${escapeQuotes(parts[i])}")
|
|
1622
|
+
const suffix = `.props.get("${escapeQuotes(parts[i])}")${i < parts.length - 1 ? "?.type" : "?"}`;
|
|
1584
1623
|
nextAccessors.push({
|
|
1585
|
-
prefix: prefix
|
|
1624
|
+
prefix: `${prefix}${suffix}`,
|
|
1586
1625
|
def: undefined
|
|
1587
1626
|
});
|
|
1588
1627
|
}
|
|
@@ -1637,9 +1676,9 @@ function resolveJsonSchemaMode(opts) {
|
|
|
1637
1676
|
}
|
|
1638
1677
|
const tsPlugin = (opts) => {
|
|
1639
1678
|
return {
|
|
1640
|
-
name: "
|
|
1679
|
+
name: "typescript",
|
|
1641
1680
|
render(doc, format) {
|
|
1642
|
-
if (format === "dts") return [{
|
|
1681
|
+
if (format === "dts" || format === __atscript_core.DEFAULT_FORMAT) return [{
|
|
1643
1682
|
fileName: `${doc.name}.d.ts`,
|
|
1644
1683
|
content: new TypeRenderer(doc, opts).render()
|
|
1645
1684
|
}];
|
|
@@ -1649,19 +1688,19 @@ const tsPlugin = (opts) => {
|
|
|
1649
1688
|
}];
|
|
1650
1689
|
},
|
|
1651
1690
|
async buildEnd(output, format, repo) {
|
|
1652
|
-
if (format === "dts") {
|
|
1691
|
+
if (format === "dts" || format === __atscript_core.DEFAULT_FORMAT) {
|
|
1653
1692
|
const annotations = await repo.getUsedAnnotations();
|
|
1654
1693
|
const tags = await repo.getPrimitivesTags() || new Set();
|
|
1655
|
-
|
|
1694
|
+
const rendered = [];
|
|
1656
1695
|
for (const [key, val] of Object.entries(annotations)) {
|
|
1657
1696
|
const multiple = val.multiple;
|
|
1658
|
-
|
|
1697
|
+
const typeLine = Array.from(val.types).map((t) => {
|
|
1659
1698
|
if (t.type === "object") return `{ ${Object.entries(t.props).map(([k, v]) => `${wrapProp(k)}${v.optional ? "?" : ""}: ${v.type}`).join(", ")} }`;
|
|
1660
1699
|
else return t.optional ? `${t.type} | true` : t.type;
|
|
1661
1700
|
}).join(" | ");
|
|
1662
1701
|
rendered.push(`${wrapProp(key)}: ${multiple ? "(" : ""}${typeLine}${multiple ? ")[]" : ""}`);
|
|
1663
1702
|
}
|
|
1664
|
-
|
|
1703
|
+
const renderedTags = Array.from(tags).map((f) => `"${escapeQuotes(f)}"`).join(" | ");
|
|
1665
1704
|
output.push({
|
|
1666
1705
|
content: "// prettier-ignore-start\n/* eslint-disable */\n/* oxlint-disable */\n/**\n * 🪄 This file was generated by Atscript\n * It is generated based on annotations used in this project\n * Do not edit this file!\n *\n * Use `npx asc -f dts` command to re-generate this file\n */\nexport {}\n\ndeclare global {\n interface AtscriptMetadata {\n " + rendered.join("\n ") + "\n }\n" + " type AtscriptPrimitiveTags = " + renderedTags + "\n" + "}\n" + "// prettier-ignore-end",
|
|
1667
1706
|
fileName: "atscript.d.ts",
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { isArray, isConst, isGroup, isInterface, isPrimitive, isRef, isStructure } from "@atscript/core";
|
|
2
1
|
import path from "path";
|
|
2
|
+
import { DEFAULT_FORMAT, isArray, isConst, isGroup, isInterface, isPrimitive, isRef, isStructure } from "@atscript/core";
|
|
3
3
|
|
|
4
4
|
//#region packages/typescript/src/codegen/code-printer.ts
|
|
5
5
|
function _define_property$4(obj, key, value) {
|
|
@@ -84,7 +84,7 @@ else if (this.currentLine.length > 0) this.lines.push(this.currentLine);
|
|
|
84
84
|
return this;
|
|
85
85
|
}
|
|
86
86
|
doPop(withNewLine) {
|
|
87
|
-
if (
|
|
87
|
+
if (this.blockStack.length === 0) throw new Error("No block to pop (stack is empty).");
|
|
88
88
|
const closing = this.blockStack.pop();
|
|
89
89
|
this.unindent();
|
|
90
90
|
if (withNewLine) this.writeln(closing);
|
|
@@ -283,7 +283,7 @@ var TypeRenderer = class TypeRenderer extends BaseRenderer {
|
|
|
283
283
|
propsDefs.add(renderedDef);
|
|
284
284
|
renderedDef.split("\n").forEach((l) => this.writeln(l));
|
|
285
285
|
}
|
|
286
|
-
if (patterns.length) {
|
|
286
|
+
if (patterns.length > 0) {
|
|
287
287
|
this.write(`[key: string]: `);
|
|
288
288
|
if (patterns.length > 0) {
|
|
289
289
|
for (const prop of patterns) propsDefs.add(this.renderTypeDefString(prop.getDefinition()));
|
|
@@ -561,7 +561,7 @@ var Validator = class {
|
|
|
561
561
|
}
|
|
562
562
|
let i = 0;
|
|
563
563
|
for (const item of def.type.items) {
|
|
564
|
-
this.push(
|
|
564
|
+
this.push(String(i));
|
|
565
565
|
if (!this.validateSafe(item, value[i])) {
|
|
566
566
|
this.pop(true);
|
|
567
567
|
return false;
|
|
@@ -597,7 +597,7 @@ var Validator = class {
|
|
|
597
597
|
let i = 0;
|
|
598
598
|
let passed = true;
|
|
599
599
|
for (const item of value) {
|
|
600
|
-
this.push(
|
|
600
|
+
this.push(String(i));
|
|
601
601
|
if (!this.validateSafe(def.type.of, item)) {
|
|
602
602
|
passed = false;
|
|
603
603
|
this.pop(true);
|
|
@@ -649,7 +649,7 @@ else {
|
|
|
649
649
|
pattern,
|
|
650
650
|
def: propDef
|
|
651
651
|
});
|
|
652
|
-
if (matched.length) {
|
|
652
|
+
if (matched.length > 0) {
|
|
653
653
|
let keyPassed = false;
|
|
654
654
|
for (const { def: def$1 } of matched) if (this.validateSafe(def$1, value[key])) {
|
|
655
655
|
this.pop(false);
|
|
@@ -676,7 +676,7 @@ else {
|
|
|
676
676
|
return passed;
|
|
677
677
|
}
|
|
678
678
|
validatePrimitive(def, value) {
|
|
679
|
-
if (
|
|
679
|
+
if (def.type.value !== undefined) {
|
|
680
680
|
if (value !== def.type.value) {
|
|
681
681
|
this.error(`Expected ${def.type.value}, got ${value}`);
|
|
682
682
|
return false;
|
|
@@ -685,40 +685,46 @@ else {
|
|
|
685
685
|
}
|
|
686
686
|
const typeOfValue = Array.isArray(value) ? "array" : typeof value;
|
|
687
687
|
switch (def.type.designType) {
|
|
688
|
-
case "never":
|
|
688
|
+
case "never": {
|
|
689
689
|
this.error(`This type is impossible, must be an internal problem`);
|
|
690
690
|
return false;
|
|
691
|
+
}
|
|
691
692
|
case "any": return true;
|
|
692
|
-
case "string":
|
|
693
|
+
case "string": {
|
|
693
694
|
if (typeOfValue !== def.type.designType) {
|
|
694
695
|
this.error(`Expected ${def.type.designType}, got ${typeOfValue}`);
|
|
695
696
|
return false;
|
|
696
697
|
}
|
|
697
698
|
return this.validateString(def, value);
|
|
698
|
-
|
|
699
|
+
}
|
|
700
|
+
case "number": {
|
|
699
701
|
if (typeOfValue !== def.type.designType) {
|
|
700
702
|
this.error(`Expected ${def.type.designType}, got ${typeOfValue}`);
|
|
701
703
|
return false;
|
|
702
704
|
}
|
|
703
705
|
return this.validateNumber(def, value);
|
|
704
|
-
|
|
706
|
+
}
|
|
707
|
+
case "boolean": {
|
|
705
708
|
if (typeOfValue !== def.type.designType) {
|
|
706
709
|
this.error(`Expected ${def.type.designType}, got ${typeOfValue}`);
|
|
707
710
|
return false;
|
|
708
711
|
}
|
|
709
712
|
return this.validateBoolean(def, value);
|
|
710
|
-
|
|
713
|
+
}
|
|
714
|
+
case "undefined": {
|
|
711
715
|
if (value !== undefined) {
|
|
712
716
|
this.error(`Expected ${def.type.designType}, got ${typeOfValue}`);
|
|
713
717
|
return false;
|
|
714
718
|
}
|
|
715
719
|
return true;
|
|
716
|
-
|
|
720
|
+
}
|
|
721
|
+
case "null": {
|
|
717
722
|
if (value !== null) {
|
|
718
723
|
this.error(`Expected ${def.type.designType}, got ${typeOfValue}`);
|
|
719
724
|
return false;
|
|
720
725
|
}
|
|
721
726
|
return true;
|
|
727
|
+
}
|
|
722
728
|
default: throw new Error(`Unknown type "${def.type.designType}"`);
|
|
723
729
|
}
|
|
724
730
|
}
|
|
@@ -930,7 +936,6 @@ else throw new Error(`Can't find prop ${typeName}${keys}`);
|
|
|
930
936
|
}
|
|
931
937
|
if (!newBase && keys) throw new Error(`Can't find prop ${typeName}${keys}`);
|
|
932
938
|
else if (!newBase) throw new Error(`"${typeName}" is not annotated type`);
|
|
933
|
-
for (const [k, v] of newBase.metadata.entries()) if (!metadata.has(k)) metadata.set(k, Array.isArray(v) ? [...v] : v);
|
|
934
939
|
this.$type = {
|
|
935
940
|
__is_atscript_annotated_type: true,
|
|
936
941
|
type: newBase.type,
|
|
@@ -974,7 +979,7 @@ function buildJsonSchema(type) {
|
|
|
974
979
|
type: "object",
|
|
975
980
|
properties
|
|
976
981
|
};
|
|
977
|
-
if (required.length) schema.required = required;
|
|
982
|
+
if (required.length > 0) schema.required = required;
|
|
978
983
|
return schema;
|
|
979
984
|
},
|
|
980
985
|
array(d) {
|
|
@@ -1237,34 +1242,39 @@ else handle.prop(prop.id, propHandle.$type);
|
|
|
1237
1242
|
annotations?.forEach((a) => {
|
|
1238
1243
|
switch (a.name) {
|
|
1239
1244
|
case "expect.minLength":
|
|
1240
|
-
case "expect.maxLength":
|
|
1245
|
+
case "expect.maxLength": {
|
|
1241
1246
|
if (a.args[0]) handle.annotate(a.name, {
|
|
1242
1247
|
length: Number(a.args[0].text),
|
|
1243
1248
|
message: a.args[1]?.text
|
|
1244
1249
|
});
|
|
1245
1250
|
break;
|
|
1246
|
-
|
|
1251
|
+
}
|
|
1252
|
+
case "expect.min": {
|
|
1247
1253
|
if (a.args[0]) handle.annotate(a.name, {
|
|
1248
1254
|
minValue: Number(a.args[0].text),
|
|
1249
1255
|
message: a.args[1]?.text
|
|
1250
1256
|
});
|
|
1251
1257
|
break;
|
|
1252
|
-
|
|
1258
|
+
}
|
|
1259
|
+
case "expect.max": {
|
|
1253
1260
|
if (a.args[0]) handle.annotate(a.name, {
|
|
1254
1261
|
maxValue: Number(a.args[0].text),
|
|
1255
1262
|
message: a.args[1]?.text
|
|
1256
1263
|
});
|
|
1257
1264
|
break;
|
|
1258
|
-
|
|
1265
|
+
}
|
|
1266
|
+
case "expect.pattern": {
|
|
1259
1267
|
handle.annotate(a.name, {
|
|
1260
1268
|
pattern: a.args[0]?.text || "",
|
|
1261
1269
|
flags: a.args[1]?.text,
|
|
1262
1270
|
message: a.args[2]?.text
|
|
1263
1271
|
}, true);
|
|
1264
1272
|
break;
|
|
1265
|
-
|
|
1273
|
+
}
|
|
1274
|
+
case "expect.int": {
|
|
1266
1275
|
handle.annotate(a.name, true);
|
|
1267
1276
|
break;
|
|
1277
|
+
}
|
|
1268
1278
|
default:
|
|
1269
1279
|
}
|
|
1270
1280
|
});
|
|
@@ -1279,11 +1289,24 @@ else handle.prop(prop.id, propHandle.$type);
|
|
|
1279
1289
|
const ref = node;
|
|
1280
1290
|
const decl = this.doc.unwindType(ref.id, ref.chain)?.def;
|
|
1281
1291
|
if (isPrimitive(decl)) {
|
|
1282
|
-
this.
|
|
1283
|
-
|
|
1292
|
+
const ownerDecl = this.doc.getDeclarationOwnerNode(ref.id);
|
|
1293
|
+
if (!ownerDecl?.node || ownerDecl.node.entity !== "type" && ownerDecl.node.entity !== "interface") {
|
|
1294
|
+
this.annotateType(decl, name);
|
|
1295
|
+
return this;
|
|
1296
|
+
}
|
|
1284
1297
|
}
|
|
1285
1298
|
const chain = ref.hasChain ? `, [${ref.chain.map((c) => `"${escapeQuotes(c.text)}"`).join(", ")}]` : "";
|
|
1286
|
-
this.writeln(`$(${name ? `"", ${name}` : ""})`).indent().writeln(`.refTo(${ref.id}${chain})`)
|
|
1299
|
+
this.writeln(`$(${name ? `"", ${name}` : ""})`).indent().writeln(`.refTo(${ref.id}${chain})`);
|
|
1300
|
+
if (!ref.hasChain) {
|
|
1301
|
+
const ownerDecl = this.doc.getDeclarationOwnerNode(ref.id);
|
|
1302
|
+
if (ownerDecl?.node) {
|
|
1303
|
+
const typeAnnotations = ownerDecl.doc.evalAnnotationsForNode(ownerDecl.node);
|
|
1304
|
+
typeAnnotations?.forEach((an) => {
|
|
1305
|
+
this.resolveAnnotationValue(ownerDecl.node, an);
|
|
1306
|
+
});
|
|
1307
|
+
}
|
|
1308
|
+
}
|
|
1309
|
+
this.unindent();
|
|
1287
1310
|
return this;
|
|
1288
1311
|
}
|
|
1289
1312
|
case "primitive": {
|
|
@@ -1312,7 +1335,7 @@ else handle.prop(prop.id, propHandle.$type);
|
|
|
1312
1335
|
return this;
|
|
1313
1336
|
}
|
|
1314
1337
|
default: {
|
|
1315
|
-
console.log("!!!!!!! UNKNOWN
|
|
1338
|
+
console.log("!!!!!!! UNKNOWN", node.entity);
|
|
1316
1339
|
return this;
|
|
1317
1340
|
}
|
|
1318
1341
|
}
|
|
@@ -1337,7 +1360,7 @@ else handle.prop(prop.id, propHandle.$type);
|
|
|
1337
1360
|
case "final": return this.writeln(`$(${d()}).designType("${def.value === "void" ? "undefined" : def.value}")`);
|
|
1338
1361
|
case "union":
|
|
1339
1362
|
case "intersection":
|
|
1340
|
-
case "tuple":
|
|
1363
|
+
case "tuple": {
|
|
1341
1364
|
this.writeln(`$(${d(def.kind)})`);
|
|
1342
1365
|
this.indent();
|
|
1343
1366
|
for (const itemDef of def.items) {
|
|
@@ -1350,7 +1373,8 @@ else handle.prop(prop.id, propHandle.$type);
|
|
|
1350
1373
|
}
|
|
1351
1374
|
this.unindent();
|
|
1352
1375
|
return;
|
|
1353
|
-
|
|
1376
|
+
}
|
|
1377
|
+
case "array": {
|
|
1354
1378
|
this.writeln(`$(${d("array")})`);
|
|
1355
1379
|
this.indent();
|
|
1356
1380
|
this.write(".of(");
|
|
@@ -1361,7 +1385,8 @@ else handle.prop(prop.id, propHandle.$type);
|
|
|
1361
1385
|
this.writeln(`)`);
|
|
1362
1386
|
this.unindent();
|
|
1363
1387
|
return;
|
|
1364
|
-
|
|
1388
|
+
}
|
|
1389
|
+
case "object": {
|
|
1365
1390
|
this.writeln(`$(${d("object")})`);
|
|
1366
1391
|
this.indent();
|
|
1367
1392
|
for (const [key, propDef] of Object.entries(def.props)) {
|
|
@@ -1388,6 +1413,7 @@ else handle.prop(prop.id, propHandle.$type);
|
|
|
1388
1413
|
}
|
|
1389
1414
|
this.unindent();
|
|
1390
1415
|
return;
|
|
1416
|
+
}
|
|
1391
1417
|
default: return this.writeln(`$(${d()}).designType("any")`);
|
|
1392
1418
|
}
|
|
1393
1419
|
}
|
|
@@ -1427,7 +1453,20 @@ else handle.prop(prop.id, propHandle.$type);
|
|
|
1427
1453
|
return this;
|
|
1428
1454
|
}
|
|
1429
1455
|
defineMetadata(node) {
|
|
1430
|
-
let annotations
|
|
1456
|
+
let annotations;
|
|
1457
|
+
const nodeDef = node.getDefinition?.();
|
|
1458
|
+
if (nodeDef && isRef(nodeDef)) {
|
|
1459
|
+
const refNode = nodeDef;
|
|
1460
|
+
if (!refNode.hasChain) {
|
|
1461
|
+
const resolved = this.doc.unwindType(refNode.id, refNode.chain)?.def;
|
|
1462
|
+
if (resolved && !isPrimitive(resolved)) annotations = node.annotations ?? [];
|
|
1463
|
+
else if (resolved && isPrimitive(resolved)) {
|
|
1464
|
+
const ownerDecl = this.doc.getDeclarationOwnerNode(refNode.id);
|
|
1465
|
+
if (ownerDecl?.node && (ownerDecl.node.entity === "type" || ownerDecl.node.entity === "interface")) annotations = node.annotations ?? [];
|
|
1466
|
+
}
|
|
1467
|
+
}
|
|
1468
|
+
}
|
|
1469
|
+
if (annotations === undefined) annotations = this.doc.evalAnnotationsForNode(node);
|
|
1431
1470
|
if (this._adHocAnnotations && this._propPath.length > 0) {
|
|
1432
1471
|
const path$1 = this._propPath.join(".");
|
|
1433
1472
|
const adHoc = this._adHocAnnotations.get(path$1);
|
|
@@ -1478,7 +1517,7 @@ else targetValue = "true";
|
|
|
1478
1517
|
}
|
|
1479
1518
|
} else {
|
|
1480
1519
|
multiple = node.countAnnotations(an.name) > 1 || an.args.length > 1;
|
|
1481
|
-
if (an.args.length) targetValue = an.args[0].type === "text" ? `"${escapeQuotes(an.args[0].text)}"` : an.args[0].text;
|
|
1520
|
+
if (an.args.length > 0) targetValue = an.args[0].type === "text" ? `"${escapeQuotes(an.args[0].text)}"` : an.args[0].text;
|
|
1482
1521
|
}
|
|
1483
1522
|
return {
|
|
1484
1523
|
value: targetValue,
|
|
@@ -1540,7 +1579,7 @@ else targetValue = "true";
|
|
|
1540
1579
|
* Returns multiple paths when a property appears in multiple union branches.
|
|
1541
1580
|
*/ buildMutatingAccessors(targetName, targetDef, parts) {
|
|
1542
1581
|
let accessors = [{
|
|
1543
|
-
prefix: targetName
|
|
1582
|
+
prefix: `${targetName}.type`,
|
|
1544
1583
|
def: targetDef
|
|
1545
1584
|
}];
|
|
1546
1585
|
for (let i = 0; i < parts.length; i++) {
|
|
@@ -1548,17 +1587,17 @@ else targetValue = "true";
|
|
|
1548
1587
|
for (const { prefix, def } of accessors) {
|
|
1549
1588
|
const results = this.buildPropPaths(def, parts[i]);
|
|
1550
1589
|
if (results.length > 0) for (const result of results) if (i < parts.length - 1) nextAccessors.push({
|
|
1551
|
-
prefix: prefix
|
|
1590
|
+
prefix: `${prefix}${result.path}?.type`,
|
|
1552
1591
|
def: result.propDef
|
|
1553
1592
|
});
|
|
1554
1593
|
else nextAccessors.push({
|
|
1555
|
-
prefix: prefix
|
|
1594
|
+
prefix: `${prefix}${result.path}?`,
|
|
1556
1595
|
def: result.propDef
|
|
1557
1596
|
});
|
|
1558
1597
|
else {
|
|
1559
|
-
const suffix = `.props.get("${escapeQuotes(parts[i])}")
|
|
1598
|
+
const suffix = `.props.get("${escapeQuotes(parts[i])}")${i < parts.length - 1 ? "?.type" : "?"}`;
|
|
1560
1599
|
nextAccessors.push({
|
|
1561
|
-
prefix: prefix
|
|
1600
|
+
prefix: `${prefix}${suffix}`,
|
|
1562
1601
|
def: undefined
|
|
1563
1602
|
});
|
|
1564
1603
|
}
|
|
@@ -1613,9 +1652,9 @@ function resolveJsonSchemaMode(opts) {
|
|
|
1613
1652
|
}
|
|
1614
1653
|
const tsPlugin = (opts) => {
|
|
1615
1654
|
return {
|
|
1616
|
-
name: "
|
|
1655
|
+
name: "typescript",
|
|
1617
1656
|
render(doc, format) {
|
|
1618
|
-
if (format === "dts") return [{
|
|
1657
|
+
if (format === "dts" || format === DEFAULT_FORMAT) return [{
|
|
1619
1658
|
fileName: `${doc.name}.d.ts`,
|
|
1620
1659
|
content: new TypeRenderer(doc, opts).render()
|
|
1621
1660
|
}];
|
|
@@ -1625,19 +1664,19 @@ const tsPlugin = (opts) => {
|
|
|
1625
1664
|
}];
|
|
1626
1665
|
},
|
|
1627
1666
|
async buildEnd(output, format, repo) {
|
|
1628
|
-
if (format === "dts") {
|
|
1667
|
+
if (format === "dts" || format === DEFAULT_FORMAT) {
|
|
1629
1668
|
const annotations = await repo.getUsedAnnotations();
|
|
1630
1669
|
const tags = await repo.getPrimitivesTags() || new Set();
|
|
1631
|
-
|
|
1670
|
+
const rendered = [];
|
|
1632
1671
|
for (const [key, val] of Object.entries(annotations)) {
|
|
1633
1672
|
const multiple = val.multiple;
|
|
1634
|
-
|
|
1673
|
+
const typeLine = Array.from(val.types).map((t) => {
|
|
1635
1674
|
if (t.type === "object") return `{ ${Object.entries(t.props).map(([k, v]) => `${wrapProp(k)}${v.optional ? "?" : ""}: ${v.type}`).join(", ")} }`;
|
|
1636
1675
|
else return t.optional ? `${t.type} | true` : t.type;
|
|
1637
1676
|
}).join(" | ");
|
|
1638
1677
|
rendered.push(`${wrapProp(key)}: ${multiple ? "(" : ""}${typeLine}${multiple ? ")[]" : ""}`);
|
|
1639
1678
|
}
|
|
1640
|
-
|
|
1679
|
+
const renderedTags = Array.from(tags).map((f) => `"${escapeQuotes(f)}"`).join(" | ");
|
|
1641
1680
|
output.push({
|
|
1642
1681
|
content: "// prettier-ignore-start\n/* eslint-disable */\n/* oxlint-disable */\n/**\n * 🪄 This file was generated by Atscript\n * It is generated based on annotations used in this project\n * Do not edit this file!\n *\n * Use `npx asc -f dts` command to re-generate this file\n */\nexport {}\n\ndeclare global {\n interface AtscriptMetadata {\n " + rendered.join("\n ") + "\n }\n" + " type AtscriptPrimitiveTags = " + renderedTags + "\n" + "}\n" + "// prettier-ignore-end",
|
|
1643
1682
|
fileName: "atscript.d.ts",
|