@atscript/typescript 0.1.50 → 0.1.52
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 +141 -5
- package/dist/index.cjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{plugin-D96fH7Va.mjs → plugin-C_5DTxz9.mjs} +142 -6
- package/dist/{plugin-cY7VLpmN.cjs → plugin-otL5yA8s.cjs} +141 -5
- package/dist/test-utils.cjs +1 -1
- package/dist/test-utils.mjs +1 -1
- package/package.json +5 -4
package/dist/cli.cjs
CHANGED
|
@@ -1500,6 +1500,132 @@ const QUERY_OP_MAP = {
|
|
|
1500
1500
|
"not exists": "$exists"
|
|
1501
1501
|
};
|
|
1502
1502
|
var JsRenderer = class extends BaseRenderer {
|
|
1503
|
+
/**
|
|
1504
|
+
* Override base `unused` to subtract symbols that the JS output references
|
|
1505
|
+
* transitively through `extends`-resolved parent prop trees. Without this,
|
|
1506
|
+
* cross-file `extends` strips the imports needed by inherited `.refTo()` calls.
|
|
1507
|
+
*/ get unused() {
|
|
1508
|
+
if (this._unusedJs) return this._unusedJs;
|
|
1509
|
+
const base = new Set(this.doc.getUnusedTokens().map((t) => t.text));
|
|
1510
|
+
for (const ref of this.getExtendsRefs().keys()) if (ref.id) base.delete(ref.id);
|
|
1511
|
+
return this._unusedJs = base;
|
|
1512
|
+
}
|
|
1513
|
+
getExtendsRefs() {
|
|
1514
|
+
if (this._extendsRefs) return this._extendsRefs;
|
|
1515
|
+
const out = new Map();
|
|
1516
|
+
const visitedInterfaces = new Set();
|
|
1517
|
+
for (const node of this.doc.nodes) if ((0, __atscript_core.isInterface)(node) && node.hasExtends) this.walkExtendsParents(node, this.doc, out, visitedInterfaces);
|
|
1518
|
+
return this._extendsRefs = out;
|
|
1519
|
+
}
|
|
1520
|
+
walkRefs(node, visited, visit) {
|
|
1521
|
+
if (!node || visited.has(node)) return;
|
|
1522
|
+
visited.add(node);
|
|
1523
|
+
if ((0, __atscript_core.isRef)(node)) {
|
|
1524
|
+
visit(node);
|
|
1525
|
+
return;
|
|
1526
|
+
}
|
|
1527
|
+
if ((0, __atscript_core.isGroup)(node)) {
|
|
1528
|
+
for (const item of node.unwrap()) this.walkRefs(item, visited, visit);
|
|
1529
|
+
return;
|
|
1530
|
+
}
|
|
1531
|
+
if ((0, __atscript_core.isArray)(node) || (0, __atscript_core.isProp)(node)) this.walkRefs(node.getDefinition(), visited, visit);
|
|
1532
|
+
}
|
|
1533
|
+
walkExtendsParents(iface, doc, out, visited) {
|
|
1534
|
+
if (visited.has(iface)) return;
|
|
1535
|
+
visited.add(iface);
|
|
1536
|
+
const visitedNodes = new Set();
|
|
1537
|
+
for (const token of iface.extendsTokens) {
|
|
1538
|
+
const unwound = doc.unwindType(token.text);
|
|
1539
|
+
if (!unwound?.def || !(0, __atscript_core.isInterface)(unwound.def)) continue;
|
|
1540
|
+
const parentInterface = unwound.def;
|
|
1541
|
+
const parentDoc = unwound.doc;
|
|
1542
|
+
this.walkRefs(parentInterface.getDefinition(), visitedNodes, (ref) => {
|
|
1543
|
+
if (!out.has(ref)) out.set(ref, parentDoc);
|
|
1544
|
+
});
|
|
1545
|
+
if (parentInterface.hasExtends) this.walkExtendsParents(parentInterface, parentDoc, out, visited);
|
|
1546
|
+
}
|
|
1547
|
+
}
|
|
1548
|
+
computeSynthesizedImports() {
|
|
1549
|
+
if (this._synthComputed) return;
|
|
1550
|
+
this._synthComputed = true;
|
|
1551
|
+
const refToOriginDoc = this.getExtendsRefs();
|
|
1552
|
+
if (refToOriginDoc.size === 0) return;
|
|
1553
|
+
const taken = new Set(this.doc.registry.definitions.keys());
|
|
1554
|
+
const allocated = new Map();
|
|
1555
|
+
const synthPathCache = new Map();
|
|
1556
|
+
for (const [refNode, originDoc] of refToOriginDoc) {
|
|
1557
|
+
const refId = refNode.id;
|
|
1558
|
+
if (!refId) continue;
|
|
1559
|
+
const ownerInfo = this.resolveOwner(originDoc, refId);
|
|
1560
|
+
if (!ownerInfo?.doc || ownerInfo.doc === this.doc) continue;
|
|
1561
|
+
if (ownerInfo.node && (0, __atscript_core.isPrimitive)(ownerInfo.node)) continue;
|
|
1562
|
+
const ownerDoc = ownerInfo.doc;
|
|
1563
|
+
let synthPath;
|
|
1564
|
+
if (synthPathCache.has(ownerDoc)) synthPath = synthPathCache.get(ownerDoc);
|
|
1565
|
+
else {
|
|
1566
|
+
synthPath = this.computeSynthPath(ownerDoc);
|
|
1567
|
+
synthPathCache.set(ownerDoc, synthPath);
|
|
1568
|
+
}
|
|
1569
|
+
if (!synthPath) continue;
|
|
1570
|
+
const allocKey = `${synthPath}::${refId}`;
|
|
1571
|
+
let info = allocated.get(allocKey);
|
|
1572
|
+
if (!info) {
|
|
1573
|
+
info = this.allocateSynthInfo(refId, synthPath, ownerInfo, taken);
|
|
1574
|
+
allocated.set(allocKey, info);
|
|
1575
|
+
}
|
|
1576
|
+
this._refSynthInfo.set(refNode, info);
|
|
1577
|
+
}
|
|
1578
|
+
}
|
|
1579
|
+
resolveOwner(fromDoc, refId) {
|
|
1580
|
+
const key = `${fromDoc.id}::${refId}`;
|
|
1581
|
+
let v = this._ownerCache.get(key);
|
|
1582
|
+
if (v === undefined && !this._ownerCache.has(key)) {
|
|
1583
|
+
v = fromDoc.getDeclarationOwnerNode(refId);
|
|
1584
|
+
this._ownerCache.set(key, v);
|
|
1585
|
+
}
|
|
1586
|
+
return v;
|
|
1587
|
+
}
|
|
1588
|
+
allocateSynthInfo(refId, synthPath, ownerInfo, taken) {
|
|
1589
|
+
const ownerDoc = ownerInfo.doc;
|
|
1590
|
+
const ownerNode = ownerInfo.node;
|
|
1591
|
+
const existing = this.doc.importedDefs.get(refId);
|
|
1592
|
+
if (existing?.text === synthPath) return {
|
|
1593
|
+
alias: refId,
|
|
1594
|
+
ownerDoc,
|
|
1595
|
+
ownerNode
|
|
1596
|
+
};
|
|
1597
|
+
const alias = this.allocAlias(refId, taken);
|
|
1598
|
+
let group = this._synthImports.get(synthPath);
|
|
1599
|
+
if (!group) {
|
|
1600
|
+
group = [];
|
|
1601
|
+
this._synthImports.set(synthPath, group);
|
|
1602
|
+
}
|
|
1603
|
+
group.push({
|
|
1604
|
+
name: refId,
|
|
1605
|
+
alias
|
|
1606
|
+
});
|
|
1607
|
+
return {
|
|
1608
|
+
alias,
|
|
1609
|
+
ownerDoc,
|
|
1610
|
+
ownerNode
|
|
1611
|
+
};
|
|
1612
|
+
}
|
|
1613
|
+
allocAlias(name, taken) {
|
|
1614
|
+
if (!taken.has(name)) {
|
|
1615
|
+
taken.add(name);
|
|
1616
|
+
return name;
|
|
1617
|
+
}
|
|
1618
|
+
let n = 1;
|
|
1619
|
+
while (taken.has(`${name}_${n}`)) n++;
|
|
1620
|
+
const alias = `${name}_${n}`;
|
|
1621
|
+
taken.add(alias);
|
|
1622
|
+
return alias;
|
|
1623
|
+
}
|
|
1624
|
+
computeSynthPath(ownerDoc) {
|
|
1625
|
+
if ((0, __atscript_core.isBareId)(ownerDoc.id)) return ownerDoc.id.slice("bare:".length, -".as".length);
|
|
1626
|
+
if (!ownerDoc.id.startsWith("file://")) return undefined;
|
|
1627
|
+
return (0, __atscript_core.getRelPath)(this.doc.id, ownerDoc.id);
|
|
1628
|
+
}
|
|
1503
1629
|
pre() {
|
|
1504
1630
|
this.writeln("// prettier-ignore-start");
|
|
1505
1631
|
this.writeln("/* eslint-disable */");
|
|
@@ -1523,6 +1649,11 @@ else for (let i = 0; i < nodes.length; i++) this.typeIds.set(nodes[i], `${name}_
|
|
|
1523
1649
|
if (this.opts?.exampleData) imports.push("createDataFromAnnotatedType as $e");
|
|
1524
1650
|
if (jsonSchemaMode === false) imports.push("throwFeatureDisabled as $d");
|
|
1525
1651
|
this.writeln(`import { ${imports.join(", ")} } from "@atscript/typescript/utils"`);
|
|
1652
|
+
this.computeSynthesizedImports();
|
|
1653
|
+
for (const [synthPath, names] of this._synthImports) {
|
|
1654
|
+
const list = names.map((n) => n.alias === n.name ? n.name : `${n.name} as ${n.alias}`).join(", ");
|
|
1655
|
+
this.writeln(`import { ${list} } from "${this.transformFromPath(synthPath)}"`);
|
|
1656
|
+
}
|
|
1526
1657
|
}
|
|
1527
1658
|
buildAdHocMap(annotateNodes) {
|
|
1528
1659
|
const map = new Map();
|
|
@@ -1801,7 +1932,7 @@ else handle.prop(prop.id, propHandle.$type);
|
|
|
1801
1932
|
const ref = node;
|
|
1802
1933
|
const decl = this.doc.unwindType(ref.id, ref.chain)?.def;
|
|
1803
1934
|
if ((0, __atscript_core.isPrimitive)(decl)) {
|
|
1804
|
-
const ownerDecl$1 = this.doc
|
|
1935
|
+
const ownerDecl$1 = this.resolveOwner(this.doc, ref.id);
|
|
1805
1936
|
if (!ownerDecl$1?.node || ownerDecl$1.node.entity !== "type" && ownerDecl$1.node.entity !== "interface") {
|
|
1806
1937
|
this.annotateType(decl, name);
|
|
1807
1938
|
return this;
|
|
@@ -1816,9 +1947,14 @@ else handle.prop(prop.id, propHandle.$type);
|
|
|
1816
1947
|
}
|
|
1817
1948
|
}
|
|
1818
1949
|
const chain = ref.hasChain ? `, [${ref.chain.map((c) => `"${escapeQuotes(c.text)}"`).join(", ")}]` : "";
|
|
1819
|
-
const
|
|
1820
|
-
const
|
|
1821
|
-
|
|
1950
|
+
const synth = this._refSynthInfo.get(ref);
|
|
1951
|
+
const ownerDecl = synth ? {
|
|
1952
|
+
doc: synth.ownerDoc,
|
|
1953
|
+
node: synth.ownerNode
|
|
1954
|
+
} : this.resolveOwner(this.doc, ref.id);
|
|
1955
|
+
const refName = synth?.alias ?? ref.id;
|
|
1956
|
+
const isImported = !!synth || (ownerDecl ? ownerDecl.doc !== this.doc : false);
|
|
1957
|
+
const refExpr = isImported ? `() => ${refName}` : refName;
|
|
1822
1958
|
this.writeln(`$(${name ? `"", ${name}` : ""})`).indent().writeln(`.refTo(${refExpr}${chain})`);
|
|
1823
1959
|
if (!ref.hasChain) {
|
|
1824
1960
|
if (ownerDecl?.node) {
|
|
@@ -2233,7 +2369,7 @@ else {
|
|
|
2233
2369
|
return [];
|
|
2234
2370
|
}
|
|
2235
2371
|
constructor(doc, opts) {
|
|
2236
|
-
super(doc), _define_property$3(this, "opts", void 0), _define_property$3(this, "postAnnotate", void 0), _define_property$3(this, "_adHocAnnotations", void 0), _define_property$3(this, "_propPath", void 0), _define_property$3(this, "typeIds", void 0), this.opts = opts, this.postAnnotate = [], this._adHocAnnotations = null, this._propPath = [], this.typeIds = new Map();
|
|
2372
|
+
super(doc), _define_property$3(this, "opts", void 0), _define_property$3(this, "postAnnotate", void 0), _define_property$3(this, "_adHocAnnotations", void 0), _define_property$3(this, "_propPath", void 0), _define_property$3(this, "typeIds", void 0), _define_property$3(this, "_unusedJs", void 0), _define_property$3(this, "_extendsRefs", void 0), _define_property$3(this, "_refSynthInfo", void 0), _define_property$3(this, "_synthImports", void 0), _define_property$3(this, "_synthComputed", void 0), _define_property$3(this, "_ownerCache", void 0), this.opts = opts, this.postAnnotate = [], this._adHocAnnotations = null, this._propPath = [], this.typeIds = new Map(), this._refSynthInfo = new Map(), this._synthImports = new Map(), this._synthComputed = false, this._ownerCache = new Map();
|
|
2237
2373
|
}
|
|
2238
2374
|
};
|
|
2239
2375
|
|
package/dist/index.cjs
CHANGED
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { buildJsonSchema, defineAnnotatedType } from "./json-schema-DrJMwvm1.mjs";
|
|
2
2
|
import path from "path";
|
|
3
|
-
import { DEFAULT_FORMAT, flattenInterfaceNode, hasNavPropAnnotation, isArray, isConst, isGroup, isInterface, isPrimitive, isQueryLogical, isRef, isStructure } from "@atscript/core";
|
|
3
|
+
import { DEFAULT_FORMAT, flattenInterfaceNode, getRelPath, hasNavPropAnnotation, isArray, isBareId, isConst, isGroup, isInterface, isPrimitive, isProp, isQueryLogical, isRef, isStructure } from "@atscript/core";
|
|
4
4
|
|
|
5
5
|
//#region packages/typescript/src/codegen/code-printer.ts
|
|
6
6
|
function _define_property$3(obj, key, value) {
|
|
@@ -671,6 +671,132 @@ const QUERY_OP_MAP = {
|
|
|
671
671
|
"not exists": "$exists"
|
|
672
672
|
};
|
|
673
673
|
var JsRenderer = class extends BaseRenderer {
|
|
674
|
+
/**
|
|
675
|
+
* Override base `unused` to subtract symbols that the JS output references
|
|
676
|
+
* transitively through `extends`-resolved parent prop trees. Without this,
|
|
677
|
+
* cross-file `extends` strips the imports needed by inherited `.refTo()` calls.
|
|
678
|
+
*/ get unused() {
|
|
679
|
+
if (this._unusedJs) return this._unusedJs;
|
|
680
|
+
const base = new Set(this.doc.getUnusedTokens().map((t) => t.text));
|
|
681
|
+
for (const ref of this.getExtendsRefs().keys()) if (ref.id) base.delete(ref.id);
|
|
682
|
+
return this._unusedJs = base;
|
|
683
|
+
}
|
|
684
|
+
getExtendsRefs() {
|
|
685
|
+
if (this._extendsRefs) return this._extendsRefs;
|
|
686
|
+
const out = new Map();
|
|
687
|
+
const visitedInterfaces = new Set();
|
|
688
|
+
for (const node of this.doc.nodes) if (isInterface(node) && node.hasExtends) this.walkExtendsParents(node, this.doc, out, visitedInterfaces);
|
|
689
|
+
return this._extendsRefs = out;
|
|
690
|
+
}
|
|
691
|
+
walkRefs(node, visited, visit) {
|
|
692
|
+
if (!node || visited.has(node)) return;
|
|
693
|
+
visited.add(node);
|
|
694
|
+
if (isRef(node)) {
|
|
695
|
+
visit(node);
|
|
696
|
+
return;
|
|
697
|
+
}
|
|
698
|
+
if (isGroup(node)) {
|
|
699
|
+
for (const item of node.unwrap()) this.walkRefs(item, visited, visit);
|
|
700
|
+
return;
|
|
701
|
+
}
|
|
702
|
+
if (isArray(node) || isProp(node)) this.walkRefs(node.getDefinition(), visited, visit);
|
|
703
|
+
}
|
|
704
|
+
walkExtendsParents(iface, doc, out, visited) {
|
|
705
|
+
if (visited.has(iface)) return;
|
|
706
|
+
visited.add(iface);
|
|
707
|
+
const visitedNodes = new Set();
|
|
708
|
+
for (const token of iface.extendsTokens) {
|
|
709
|
+
const unwound = doc.unwindType(token.text);
|
|
710
|
+
if (!unwound?.def || !isInterface(unwound.def)) continue;
|
|
711
|
+
const parentInterface = unwound.def;
|
|
712
|
+
const parentDoc = unwound.doc;
|
|
713
|
+
this.walkRefs(parentInterface.getDefinition(), visitedNodes, (ref) => {
|
|
714
|
+
if (!out.has(ref)) out.set(ref, parentDoc);
|
|
715
|
+
});
|
|
716
|
+
if (parentInterface.hasExtends) this.walkExtendsParents(parentInterface, parentDoc, out, visited);
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
computeSynthesizedImports() {
|
|
720
|
+
if (this._synthComputed) return;
|
|
721
|
+
this._synthComputed = true;
|
|
722
|
+
const refToOriginDoc = this.getExtendsRefs();
|
|
723
|
+
if (refToOriginDoc.size === 0) return;
|
|
724
|
+
const taken = new Set(this.doc.registry.definitions.keys());
|
|
725
|
+
const allocated = new Map();
|
|
726
|
+
const synthPathCache = new Map();
|
|
727
|
+
for (const [refNode, originDoc] of refToOriginDoc) {
|
|
728
|
+
const refId = refNode.id;
|
|
729
|
+
if (!refId) continue;
|
|
730
|
+
const ownerInfo = this.resolveOwner(originDoc, refId);
|
|
731
|
+
if (!ownerInfo?.doc || ownerInfo.doc === this.doc) continue;
|
|
732
|
+
if (ownerInfo.node && isPrimitive(ownerInfo.node)) continue;
|
|
733
|
+
const ownerDoc = ownerInfo.doc;
|
|
734
|
+
let synthPath;
|
|
735
|
+
if (synthPathCache.has(ownerDoc)) synthPath = synthPathCache.get(ownerDoc);
|
|
736
|
+
else {
|
|
737
|
+
synthPath = this.computeSynthPath(ownerDoc);
|
|
738
|
+
synthPathCache.set(ownerDoc, synthPath);
|
|
739
|
+
}
|
|
740
|
+
if (!synthPath) continue;
|
|
741
|
+
const allocKey = `${synthPath}::${refId}`;
|
|
742
|
+
let info = allocated.get(allocKey);
|
|
743
|
+
if (!info) {
|
|
744
|
+
info = this.allocateSynthInfo(refId, synthPath, ownerInfo, taken);
|
|
745
|
+
allocated.set(allocKey, info);
|
|
746
|
+
}
|
|
747
|
+
this._refSynthInfo.set(refNode, info);
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
resolveOwner(fromDoc, refId) {
|
|
751
|
+
const key = `${fromDoc.id}::${refId}`;
|
|
752
|
+
let v = this._ownerCache.get(key);
|
|
753
|
+
if (v === undefined && !this._ownerCache.has(key)) {
|
|
754
|
+
v = fromDoc.getDeclarationOwnerNode(refId);
|
|
755
|
+
this._ownerCache.set(key, v);
|
|
756
|
+
}
|
|
757
|
+
return v;
|
|
758
|
+
}
|
|
759
|
+
allocateSynthInfo(refId, synthPath, ownerInfo, taken) {
|
|
760
|
+
const ownerDoc = ownerInfo.doc;
|
|
761
|
+
const ownerNode = ownerInfo.node;
|
|
762
|
+
const existing = this.doc.importedDefs.get(refId);
|
|
763
|
+
if (existing?.text === synthPath) return {
|
|
764
|
+
alias: refId,
|
|
765
|
+
ownerDoc,
|
|
766
|
+
ownerNode
|
|
767
|
+
};
|
|
768
|
+
const alias = this.allocAlias(refId, taken);
|
|
769
|
+
let group = this._synthImports.get(synthPath);
|
|
770
|
+
if (!group) {
|
|
771
|
+
group = [];
|
|
772
|
+
this._synthImports.set(synthPath, group);
|
|
773
|
+
}
|
|
774
|
+
group.push({
|
|
775
|
+
name: refId,
|
|
776
|
+
alias
|
|
777
|
+
});
|
|
778
|
+
return {
|
|
779
|
+
alias,
|
|
780
|
+
ownerDoc,
|
|
781
|
+
ownerNode
|
|
782
|
+
};
|
|
783
|
+
}
|
|
784
|
+
allocAlias(name, taken) {
|
|
785
|
+
if (!taken.has(name)) {
|
|
786
|
+
taken.add(name);
|
|
787
|
+
return name;
|
|
788
|
+
}
|
|
789
|
+
let n = 1;
|
|
790
|
+
while (taken.has(`${name}_${n}`)) n++;
|
|
791
|
+
const alias = `${name}_${n}`;
|
|
792
|
+
taken.add(alias);
|
|
793
|
+
return alias;
|
|
794
|
+
}
|
|
795
|
+
computeSynthPath(ownerDoc) {
|
|
796
|
+
if (isBareId(ownerDoc.id)) return ownerDoc.id.slice("bare:".length, -".as".length);
|
|
797
|
+
if (!ownerDoc.id.startsWith("file://")) return undefined;
|
|
798
|
+
return getRelPath(this.doc.id, ownerDoc.id);
|
|
799
|
+
}
|
|
674
800
|
pre() {
|
|
675
801
|
this.writeln("// prettier-ignore-start");
|
|
676
802
|
this.writeln("/* eslint-disable */");
|
|
@@ -694,6 +820,11 @@ else for (let i = 0; i < nodes.length; i++) this.typeIds.set(nodes[i], `${name}_
|
|
|
694
820
|
if (this.opts?.exampleData) imports.push("createDataFromAnnotatedType as $e");
|
|
695
821
|
if (jsonSchemaMode === false) imports.push("throwFeatureDisabled as $d");
|
|
696
822
|
this.writeln(`import { ${imports.join(", ")} } from "@atscript/typescript/utils"`);
|
|
823
|
+
this.computeSynthesizedImports();
|
|
824
|
+
for (const [synthPath, names] of this._synthImports) {
|
|
825
|
+
const list = names.map((n) => n.alias === n.name ? n.name : `${n.name} as ${n.alias}`).join(", ");
|
|
826
|
+
this.writeln(`import { ${list} } from "${this.transformFromPath(synthPath)}"`);
|
|
827
|
+
}
|
|
697
828
|
}
|
|
698
829
|
buildAdHocMap(annotateNodes) {
|
|
699
830
|
const map = new Map();
|
|
@@ -972,7 +1103,7 @@ else handle.prop(prop.id, propHandle.$type);
|
|
|
972
1103
|
const ref = node;
|
|
973
1104
|
const decl = this.doc.unwindType(ref.id, ref.chain)?.def;
|
|
974
1105
|
if (isPrimitive(decl)) {
|
|
975
|
-
const ownerDecl$1 = this.doc
|
|
1106
|
+
const ownerDecl$1 = this.resolveOwner(this.doc, ref.id);
|
|
976
1107
|
if (!ownerDecl$1?.node || ownerDecl$1.node.entity !== "type" && ownerDecl$1.node.entity !== "interface") {
|
|
977
1108
|
this.annotateType(decl, name);
|
|
978
1109
|
return this;
|
|
@@ -987,9 +1118,14 @@ else handle.prop(prop.id, propHandle.$type);
|
|
|
987
1118
|
}
|
|
988
1119
|
}
|
|
989
1120
|
const chain = ref.hasChain ? `, [${ref.chain.map((c) => `"${escapeQuotes(c.text)}"`).join(", ")}]` : "";
|
|
990
|
-
const
|
|
991
|
-
const
|
|
992
|
-
|
|
1121
|
+
const synth = this._refSynthInfo.get(ref);
|
|
1122
|
+
const ownerDecl = synth ? {
|
|
1123
|
+
doc: synth.ownerDoc,
|
|
1124
|
+
node: synth.ownerNode
|
|
1125
|
+
} : this.resolveOwner(this.doc, ref.id);
|
|
1126
|
+
const refName = synth?.alias ?? ref.id;
|
|
1127
|
+
const isImported = !!synth || (ownerDecl ? ownerDecl.doc !== this.doc : false);
|
|
1128
|
+
const refExpr = isImported ? `() => ${refName}` : refName;
|
|
993
1129
|
this.writeln(`$(${name ? `"", ${name}` : ""})`).indent().writeln(`.refTo(${refExpr}${chain})`);
|
|
994
1130
|
if (!ref.hasChain) {
|
|
995
1131
|
if (ownerDecl?.node) {
|
|
@@ -1404,7 +1540,7 @@ else {
|
|
|
1404
1540
|
return [];
|
|
1405
1541
|
}
|
|
1406
1542
|
constructor(doc, opts) {
|
|
1407
|
-
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), _define_property(this, "typeIds", void 0), this.opts = opts, this.postAnnotate = [], this._adHocAnnotations = null, this._propPath = [], this.typeIds = new Map();
|
|
1543
|
+
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), _define_property(this, "typeIds", void 0), _define_property(this, "_unusedJs", void 0), _define_property(this, "_extendsRefs", void 0), _define_property(this, "_refSynthInfo", void 0), _define_property(this, "_synthImports", void 0), _define_property(this, "_synthComputed", void 0), _define_property(this, "_ownerCache", void 0), this.opts = opts, this.postAnnotate = [], this._adHocAnnotations = null, this._propPath = [], this.typeIds = new Map(), this._refSynthInfo = new Map(), this._synthImports = new Map(), this._synthComputed = false, this._ownerCache = new Map();
|
|
1408
1544
|
}
|
|
1409
1545
|
};
|
|
1410
1546
|
|
|
@@ -695,6 +695,132 @@ const QUERY_OP_MAP = {
|
|
|
695
695
|
"not exists": "$exists"
|
|
696
696
|
};
|
|
697
697
|
var JsRenderer = class extends BaseRenderer {
|
|
698
|
+
/**
|
|
699
|
+
* Override base `unused` to subtract symbols that the JS output references
|
|
700
|
+
* transitively through `extends`-resolved parent prop trees. Without this,
|
|
701
|
+
* cross-file `extends` strips the imports needed by inherited `.refTo()` calls.
|
|
702
|
+
*/ get unused() {
|
|
703
|
+
if (this._unusedJs) return this._unusedJs;
|
|
704
|
+
const base = new Set(this.doc.getUnusedTokens().map((t) => t.text));
|
|
705
|
+
for (const ref of this.getExtendsRefs().keys()) if (ref.id) base.delete(ref.id);
|
|
706
|
+
return this._unusedJs = base;
|
|
707
|
+
}
|
|
708
|
+
getExtendsRefs() {
|
|
709
|
+
if (this._extendsRefs) return this._extendsRefs;
|
|
710
|
+
const out = new Map();
|
|
711
|
+
const visitedInterfaces = new Set();
|
|
712
|
+
for (const node of this.doc.nodes) if ((0, __atscript_core.isInterface)(node) && node.hasExtends) this.walkExtendsParents(node, this.doc, out, visitedInterfaces);
|
|
713
|
+
return this._extendsRefs = out;
|
|
714
|
+
}
|
|
715
|
+
walkRefs(node, visited, visit) {
|
|
716
|
+
if (!node || visited.has(node)) return;
|
|
717
|
+
visited.add(node);
|
|
718
|
+
if ((0, __atscript_core.isRef)(node)) {
|
|
719
|
+
visit(node);
|
|
720
|
+
return;
|
|
721
|
+
}
|
|
722
|
+
if ((0, __atscript_core.isGroup)(node)) {
|
|
723
|
+
for (const item of node.unwrap()) this.walkRefs(item, visited, visit);
|
|
724
|
+
return;
|
|
725
|
+
}
|
|
726
|
+
if ((0, __atscript_core.isArray)(node) || (0, __atscript_core.isProp)(node)) this.walkRefs(node.getDefinition(), visited, visit);
|
|
727
|
+
}
|
|
728
|
+
walkExtendsParents(iface, doc, out, visited) {
|
|
729
|
+
if (visited.has(iface)) return;
|
|
730
|
+
visited.add(iface);
|
|
731
|
+
const visitedNodes = new Set();
|
|
732
|
+
for (const token of iface.extendsTokens) {
|
|
733
|
+
const unwound = doc.unwindType(token.text);
|
|
734
|
+
if (!unwound?.def || !(0, __atscript_core.isInterface)(unwound.def)) continue;
|
|
735
|
+
const parentInterface = unwound.def;
|
|
736
|
+
const parentDoc = unwound.doc;
|
|
737
|
+
this.walkRefs(parentInterface.getDefinition(), visitedNodes, (ref) => {
|
|
738
|
+
if (!out.has(ref)) out.set(ref, parentDoc);
|
|
739
|
+
});
|
|
740
|
+
if (parentInterface.hasExtends) this.walkExtendsParents(parentInterface, parentDoc, out, visited);
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
computeSynthesizedImports() {
|
|
744
|
+
if (this._synthComputed) return;
|
|
745
|
+
this._synthComputed = true;
|
|
746
|
+
const refToOriginDoc = this.getExtendsRefs();
|
|
747
|
+
if (refToOriginDoc.size === 0) return;
|
|
748
|
+
const taken = new Set(this.doc.registry.definitions.keys());
|
|
749
|
+
const allocated = new Map();
|
|
750
|
+
const synthPathCache = new Map();
|
|
751
|
+
for (const [refNode, originDoc] of refToOriginDoc) {
|
|
752
|
+
const refId = refNode.id;
|
|
753
|
+
if (!refId) continue;
|
|
754
|
+
const ownerInfo = this.resolveOwner(originDoc, refId);
|
|
755
|
+
if (!ownerInfo?.doc || ownerInfo.doc === this.doc) continue;
|
|
756
|
+
if (ownerInfo.node && (0, __atscript_core.isPrimitive)(ownerInfo.node)) continue;
|
|
757
|
+
const ownerDoc = ownerInfo.doc;
|
|
758
|
+
let synthPath;
|
|
759
|
+
if (synthPathCache.has(ownerDoc)) synthPath = synthPathCache.get(ownerDoc);
|
|
760
|
+
else {
|
|
761
|
+
synthPath = this.computeSynthPath(ownerDoc);
|
|
762
|
+
synthPathCache.set(ownerDoc, synthPath);
|
|
763
|
+
}
|
|
764
|
+
if (!synthPath) continue;
|
|
765
|
+
const allocKey = `${synthPath}::${refId}`;
|
|
766
|
+
let info = allocated.get(allocKey);
|
|
767
|
+
if (!info) {
|
|
768
|
+
info = this.allocateSynthInfo(refId, synthPath, ownerInfo, taken);
|
|
769
|
+
allocated.set(allocKey, info);
|
|
770
|
+
}
|
|
771
|
+
this._refSynthInfo.set(refNode, info);
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
resolveOwner(fromDoc, refId) {
|
|
775
|
+
const key = `${fromDoc.id}::${refId}`;
|
|
776
|
+
let v = this._ownerCache.get(key);
|
|
777
|
+
if (v === undefined && !this._ownerCache.has(key)) {
|
|
778
|
+
v = fromDoc.getDeclarationOwnerNode(refId);
|
|
779
|
+
this._ownerCache.set(key, v);
|
|
780
|
+
}
|
|
781
|
+
return v;
|
|
782
|
+
}
|
|
783
|
+
allocateSynthInfo(refId, synthPath, ownerInfo, taken) {
|
|
784
|
+
const ownerDoc = ownerInfo.doc;
|
|
785
|
+
const ownerNode = ownerInfo.node;
|
|
786
|
+
const existing = this.doc.importedDefs.get(refId);
|
|
787
|
+
if (existing?.text === synthPath) return {
|
|
788
|
+
alias: refId,
|
|
789
|
+
ownerDoc,
|
|
790
|
+
ownerNode
|
|
791
|
+
};
|
|
792
|
+
const alias = this.allocAlias(refId, taken);
|
|
793
|
+
let group = this._synthImports.get(synthPath);
|
|
794
|
+
if (!group) {
|
|
795
|
+
group = [];
|
|
796
|
+
this._synthImports.set(synthPath, group);
|
|
797
|
+
}
|
|
798
|
+
group.push({
|
|
799
|
+
name: refId,
|
|
800
|
+
alias
|
|
801
|
+
});
|
|
802
|
+
return {
|
|
803
|
+
alias,
|
|
804
|
+
ownerDoc,
|
|
805
|
+
ownerNode
|
|
806
|
+
};
|
|
807
|
+
}
|
|
808
|
+
allocAlias(name, taken) {
|
|
809
|
+
if (!taken.has(name)) {
|
|
810
|
+
taken.add(name);
|
|
811
|
+
return name;
|
|
812
|
+
}
|
|
813
|
+
let n = 1;
|
|
814
|
+
while (taken.has(`${name}_${n}`)) n++;
|
|
815
|
+
const alias = `${name}_${n}`;
|
|
816
|
+
taken.add(alias);
|
|
817
|
+
return alias;
|
|
818
|
+
}
|
|
819
|
+
computeSynthPath(ownerDoc) {
|
|
820
|
+
if ((0, __atscript_core.isBareId)(ownerDoc.id)) return ownerDoc.id.slice("bare:".length, -".as".length);
|
|
821
|
+
if (!ownerDoc.id.startsWith("file://")) return undefined;
|
|
822
|
+
return (0, __atscript_core.getRelPath)(this.doc.id, ownerDoc.id);
|
|
823
|
+
}
|
|
698
824
|
pre() {
|
|
699
825
|
this.writeln("// prettier-ignore-start");
|
|
700
826
|
this.writeln("/* eslint-disable */");
|
|
@@ -718,6 +844,11 @@ else for (let i = 0; i < nodes.length; i++) this.typeIds.set(nodes[i], `${name}_
|
|
|
718
844
|
if (this.opts?.exampleData) imports.push("createDataFromAnnotatedType as $e");
|
|
719
845
|
if (jsonSchemaMode === false) imports.push("throwFeatureDisabled as $d");
|
|
720
846
|
this.writeln(`import { ${imports.join(", ")} } from "@atscript/typescript/utils"`);
|
|
847
|
+
this.computeSynthesizedImports();
|
|
848
|
+
for (const [synthPath, names] of this._synthImports) {
|
|
849
|
+
const list = names.map((n) => n.alias === n.name ? n.name : `${n.name} as ${n.alias}`).join(", ");
|
|
850
|
+
this.writeln(`import { ${list} } from "${this.transformFromPath(synthPath)}"`);
|
|
851
|
+
}
|
|
721
852
|
}
|
|
722
853
|
buildAdHocMap(annotateNodes) {
|
|
723
854
|
const map = new Map();
|
|
@@ -996,7 +1127,7 @@ else handle.prop(prop.id, propHandle.$type);
|
|
|
996
1127
|
const ref = node;
|
|
997
1128
|
const decl = this.doc.unwindType(ref.id, ref.chain)?.def;
|
|
998
1129
|
if ((0, __atscript_core.isPrimitive)(decl)) {
|
|
999
|
-
const ownerDecl$1 = this.doc
|
|
1130
|
+
const ownerDecl$1 = this.resolveOwner(this.doc, ref.id);
|
|
1000
1131
|
if (!ownerDecl$1?.node || ownerDecl$1.node.entity !== "type" && ownerDecl$1.node.entity !== "interface") {
|
|
1001
1132
|
this.annotateType(decl, name);
|
|
1002
1133
|
return this;
|
|
@@ -1011,9 +1142,14 @@ else handle.prop(prop.id, propHandle.$type);
|
|
|
1011
1142
|
}
|
|
1012
1143
|
}
|
|
1013
1144
|
const chain = ref.hasChain ? `, [${ref.chain.map((c) => `"${escapeQuotes(c.text)}"`).join(", ")}]` : "";
|
|
1014
|
-
const
|
|
1015
|
-
const
|
|
1016
|
-
|
|
1145
|
+
const synth = this._refSynthInfo.get(ref);
|
|
1146
|
+
const ownerDecl = synth ? {
|
|
1147
|
+
doc: synth.ownerDoc,
|
|
1148
|
+
node: synth.ownerNode
|
|
1149
|
+
} : this.resolveOwner(this.doc, ref.id);
|
|
1150
|
+
const refName = synth?.alias ?? ref.id;
|
|
1151
|
+
const isImported = !!synth || (ownerDecl ? ownerDecl.doc !== this.doc : false);
|
|
1152
|
+
const refExpr = isImported ? `() => ${refName}` : refName;
|
|
1017
1153
|
this.writeln(`$(${name ? `"", ${name}` : ""})`).indent().writeln(`.refTo(${refExpr}${chain})`);
|
|
1018
1154
|
if (!ref.hasChain) {
|
|
1019
1155
|
if (ownerDecl?.node) {
|
|
@@ -1428,7 +1564,7 @@ else {
|
|
|
1428
1564
|
return [];
|
|
1429
1565
|
}
|
|
1430
1566
|
constructor(doc, opts) {
|
|
1431
|
-
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), _define_property(this, "typeIds", void 0), this.opts = opts, this.postAnnotate = [], this._adHocAnnotations = null, this._propPath = [], this.typeIds = new Map();
|
|
1567
|
+
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), _define_property(this, "typeIds", void 0), _define_property(this, "_unusedJs", void 0), _define_property(this, "_extendsRefs", void 0), _define_property(this, "_refSynthInfo", void 0), _define_property(this, "_synthImports", void 0), _define_property(this, "_synthComputed", void 0), _define_property(this, "_ownerCache", void 0), this.opts = opts, this.postAnnotate = [], this._adHocAnnotations = null, this._propPath = [], this.typeIds = new Map(), this._refSynthInfo = new Map(), this._synthImports = new Map(), this._synthComputed = false, this._ownerCache = new Map();
|
|
1432
1568
|
}
|
|
1433
1569
|
};
|
|
1434
1570
|
|
package/dist/test-utils.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
const require_plugin = require('./plugin-
|
|
2
|
+
const require_plugin = require('./plugin-otL5yA8s.cjs');
|
|
3
3
|
require('./json-schema-BgW_S2sP.cjs');
|
|
4
4
|
const path = require_plugin.__toESM(require("path"));
|
|
5
5
|
const __atscript_core = require_plugin.__toESM(require("@atscript/core"));
|
package/dist/test-utils.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atscript/typescript",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.52",
|
|
4
4
|
"description": "Atscript: typescript-gen support.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"annotations",
|
|
@@ -63,16 +63,17 @@
|
|
|
63
63
|
"./package.json": "./package.json"
|
|
64
64
|
},
|
|
65
65
|
"dependencies": {
|
|
66
|
-
"@moostjs/event-cli": "^0.6.
|
|
67
|
-
"moost": "^0.6.
|
|
66
|
+
"@moostjs/event-cli": "^0.6.9",
|
|
67
|
+
"moost": "^0.6.9"
|
|
68
68
|
},
|
|
69
69
|
"devDependencies": {
|
|
70
70
|
"@atscript/db": "^0.1.48",
|
|
71
|
+
"@uniqu/core": "^0.1.6",
|
|
71
72
|
"vitest": "3.2.4"
|
|
72
73
|
},
|
|
73
74
|
"peerDependencies": {
|
|
74
75
|
"@atscript/db": "^0.1.48",
|
|
75
|
-
"@atscript/core": "^0.1.
|
|
76
|
+
"@atscript/core": "^0.1.52"
|
|
76
77
|
},
|
|
77
78
|
"peerDependenciesMeta": {
|
|
78
79
|
"@atscript/db": {
|