@dunx/transform 2.5.0 → 3.0.1
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/ast.d.ts +22 -3
- package/dist/{chunk-41at0m5d.js → chunk-cfmpj4s2.js} +36 -15
- package/dist/edits.d.ts +3 -2
- package/dist/index.js +1 -1
- package/dist/preload.js +1 -1
- package/package.json +1 -1
package/dist/ast.d.ts
CHANGED
|
@@ -47,16 +47,30 @@ export interface ImportDeclaration extends Node {
|
|
|
47
47
|
readonly specifiers: readonly Node[];
|
|
48
48
|
readonly importKind: 'value' | 'type';
|
|
49
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* `ImportSpecifier`, `ImportDefaultSpecifier` and `ImportNamespaceSpecifier`.
|
|
52
|
+
* Only the first carries its own `importKind`; all three carry `local`, which is
|
|
53
|
+
* the name the file binds and the only field the erasure map needs.
|
|
54
|
+
*/
|
|
50
55
|
export interface ImportSpecifier extends Node {
|
|
51
|
-
readonly type: 'ImportSpecifier';
|
|
52
56
|
readonly local: Identifier;
|
|
53
|
-
readonly importKind
|
|
57
|
+
readonly importKind?: 'value' | 'type';
|
|
58
|
+
}
|
|
59
|
+
export interface TSQualifiedName extends Node {
|
|
60
|
+
readonly type: 'TSQualifiedName';
|
|
61
|
+
readonly left: Node;
|
|
62
|
+
readonly right: Identifier;
|
|
63
|
+
}
|
|
64
|
+
export interface AssignmentPattern extends Node {
|
|
65
|
+
readonly type: 'AssignmentPattern';
|
|
66
|
+
readonly left: Node;
|
|
54
67
|
}
|
|
55
68
|
export declare const isIdentifier: (node: Node | null | undefined) => node is Identifier;
|
|
56
69
|
export declare const isMethodDefinition: (node: Node | null | undefined) => node is MethodDefinition;
|
|
57
70
|
export declare const isTypeReference: (node: Node | null | undefined) => node is TSTypeReference;
|
|
58
71
|
export declare const isImportDeclaration: (node: Node | null | undefined) => node is ImportDeclaration;
|
|
59
|
-
export declare const
|
|
72
|
+
export declare const isQualifiedName: (node: Node | null | undefined) => node is TSQualifiedName;
|
|
73
|
+
export declare const isAssignmentPattern: (node: Node | null | undefined) => node is AssignmentPattern;
|
|
60
74
|
export declare const isParameterProperty: (node: Node | null | undefined) => node is TSParameterProperty;
|
|
61
75
|
/**
|
|
62
76
|
* Declarations only. A `ClassExpression`'s own name is bound inside the class
|
|
@@ -71,3 +85,8 @@ export declare const isClassDeclaration: (node: Node) => node is ClassNode;
|
|
|
71
85
|
*/
|
|
72
86
|
export declare const walk: (root: unknown, visit: (node: Node) => void) => void;
|
|
73
87
|
export declare const nameOf: (node: Node | null | undefined) => string | undefined;
|
|
88
|
+
/**
|
|
89
|
+
* The leftmost identifier of a type name. In `a.b.C` only `a` has to exist at
|
|
90
|
+
* runtime, so it is the only part the erasure map can answer for.
|
|
91
|
+
*/
|
|
92
|
+
export declare const rootOfTypeName: (node: Node) => Node;
|
|
@@ -23,7 +23,8 @@ var isIdentifier = guard("Identifier");
|
|
|
23
23
|
var isMethodDefinition = guard("MethodDefinition");
|
|
24
24
|
var isTypeReference = guard("TSTypeReference");
|
|
25
25
|
var isImportDeclaration = guard("ImportDeclaration");
|
|
26
|
-
var
|
|
26
|
+
var isQualifiedName = guard("TSQualifiedName");
|
|
27
|
+
var isAssignmentPattern = guard("AssignmentPattern");
|
|
27
28
|
var isParameterProperty = guard("TSParameterProperty");
|
|
28
29
|
var isClassDeclaration = (node) => node.type === "ClassDeclaration";
|
|
29
30
|
var walk = (root, visit) => {
|
|
@@ -42,18 +43,33 @@ var walk = (root, visit) => {
|
|
|
42
43
|
walk(child, visit);
|
|
43
44
|
};
|
|
44
45
|
var nameOf = (node) => isIdentifier(node) ? node.name : undefined;
|
|
46
|
+
var rootOfTypeName = (node) => isQualifiedName(node) ? rootOfTypeName(node.left) : node;
|
|
45
47
|
|
|
46
48
|
// src/erased.ts
|
|
49
|
+
var mergedClassNames = (program) => {
|
|
50
|
+
const body = program.body ?? [];
|
|
51
|
+
const names = new Set;
|
|
52
|
+
for (const statement of body) {
|
|
53
|
+
const declaration = statement.declaration ?? statement;
|
|
54
|
+
if (!isClassDeclaration(declaration))
|
|
55
|
+
continue;
|
|
56
|
+
const name = declaration.id?.name;
|
|
57
|
+
if (name !== undefined)
|
|
58
|
+
names.add(name);
|
|
59
|
+
}
|
|
60
|
+
return names;
|
|
61
|
+
};
|
|
47
62
|
var collectTypeOnlyNames = (program) => {
|
|
48
63
|
const names = new Map;
|
|
49
64
|
walk(program, (node) => {
|
|
50
65
|
if (isImportDeclaration(node)) {
|
|
51
66
|
for (const specifier of node.specifiers) {
|
|
52
|
-
|
|
67
|
+
const { local, importKind } = specifier;
|
|
68
|
+
if (node.importKind !== "type" && importKind !== "type")
|
|
53
69
|
continue;
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
70
|
+
const name = nameOf(local);
|
|
71
|
+
if (name !== undefined)
|
|
72
|
+
names.set(name, "import-type");
|
|
57
73
|
}
|
|
58
74
|
return;
|
|
59
75
|
}
|
|
@@ -64,6 +80,8 @@ var collectTypeOnlyNames = (program) => {
|
|
|
64
80
|
names.set(name, "declared-type");
|
|
65
81
|
}
|
|
66
82
|
});
|
|
83
|
+
for (const name of mergedClassNames(program))
|
|
84
|
+
names.delete(name);
|
|
67
85
|
return names;
|
|
68
86
|
};
|
|
69
87
|
var collectTypeParameters = (klass) => {
|
|
@@ -91,23 +109,29 @@ var constructorParams = (klass) => {
|
|
|
91
109
|
const found = klass.body.body.find((member) => isMethodDefinition(member) && nameOf(member.key) === "constructor");
|
|
92
110
|
return isMethodDefinition(found) ? found.value.params : [];
|
|
93
111
|
};
|
|
112
|
+
var bindingOf = (param) => {
|
|
113
|
+
const named = isParameterProperty(param) ? param.parameter : param;
|
|
114
|
+
return isAssignmentPattern(named) ? named.left : named;
|
|
115
|
+
};
|
|
94
116
|
var annotationOf = (param) => {
|
|
95
|
-
const inner =
|
|
117
|
+
const inner = bindingOf(param);
|
|
96
118
|
if (!isIdentifier(inner))
|
|
97
119
|
return;
|
|
98
120
|
return inner.typeAnnotation?.typeAnnotation;
|
|
99
121
|
};
|
|
122
|
+
var hasDefault = (param) => isAssignmentPattern(isParameterProperty(param) ? param.parameter : param);
|
|
100
123
|
var entryFor = (source, param, erased) => {
|
|
101
124
|
const text = JSON.stringify(slice(source, param));
|
|
102
|
-
const
|
|
125
|
+
const optional = hasDefault(param) ? ", optional: true" : "";
|
|
126
|
+
const unresolved = `{ unresolved: ${text}${optional} }`;
|
|
103
127
|
const annotation = annotationOf(param);
|
|
104
128
|
if (!annotation || !isTypeReference(annotation))
|
|
105
129
|
return unresolved;
|
|
106
|
-
const
|
|
107
|
-
const cause = erased.get(
|
|
130
|
+
const root = nameOf(rootOfTypeName(annotation.typeName));
|
|
131
|
+
const cause = root === undefined ? undefined : erased.get(root);
|
|
108
132
|
if (cause === undefined)
|
|
109
|
-
return
|
|
110
|
-
return cause === "import-type" ? `{ unresolved: ${text}, typeOnly: ${JSON.stringify(
|
|
133
|
+
return slice(source, annotation.typeName);
|
|
134
|
+
return cause === "import-type" ? `{ unresolved: ${text}${optional}, typeOnly: ${JSON.stringify(root)} }` : unresolved;
|
|
111
135
|
};
|
|
112
136
|
var transform = (source, filename = "input.ts") => {
|
|
113
137
|
const parsed = parseSync(filename, source);
|
|
@@ -133,10 +157,7 @@ var transform = (source, filename = "input.ts") => {
|
|
|
133
157
|
edits.push({
|
|
134
158
|
start: node.end,
|
|
135
159
|
end: node.end,
|
|
136
|
-
text: `
|
|
137
|
-
Object.defineProperty(${name}, ${DEPS_KEY}, {
|
|
138
|
-
` + ` value: () => [${entries.join(", ")}],
|
|
139
|
-
});`
|
|
160
|
+
text: `;Object.defineProperty(${name}, ${DEPS_KEY}, ` + `{ value: () => [${entries.join(", ")}] });`
|
|
140
161
|
});
|
|
141
162
|
}
|
|
142
163
|
});
|
package/dist/edits.d.ts
CHANGED
|
@@ -5,7 +5,8 @@ export interface Edit {
|
|
|
5
5
|
}
|
|
6
6
|
/**
|
|
7
7
|
* Splices edits into the original text rather than reprinting the AST, so
|
|
8
|
-
* everything untouched keeps its exact bytes
|
|
9
|
-
* line
|
|
8
|
+
* everything untouched keeps its exact bytes. Line numbers survive too, but only
|
|
9
|
+
* because every edit this transform makes is a single line appended to one that
|
|
10
|
+
* already exists - splicing alone does not guarantee it.
|
|
10
11
|
*/
|
|
11
12
|
export declare const applyEdits: (source: string, edits: readonly Edit[]) => string;
|
package/dist/index.js
CHANGED
package/dist/preload.js
CHANGED