Skip to content

Commit 88b6001

Browse files
hedwigggggdanielpza
andcommitted
fix: add support for dynamic imports (#46)
* ADDED: failing test, dynamic import * ADDED: unpath for ImportTypeNode * FIXED: prettier error * ADDED: async import tests * ADDED: unpather for async import REFACTORED: DRY * some improvements Co-authored-by: Daniel Perez Alvarez <danielpza@protonmail.com>
1 parent f47f854 commit 88b6001

File tree

4 files changed

+101
-16
lines changed

4 files changed

+101
-16
lines changed

src/index.ts

+65-16
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ const transformer = (_: ts.Program) => (context: ts.TransformationContext) => (
6565
// if it's relative path do not transform
6666
return moduleName;
6767
}
68+
6869
for (const { regexp, path } of binds) {
6970
const match = regexp.exec(moduleName);
7071
if (match) {
@@ -81,6 +82,19 @@ const transformer = (_: ts.Program) => (context: ts.TransformationContext) => (
8182
return undefined;
8283
}
8384

85+
const isRequire = (node: ts.Node): node is ts.CallExpression =>
86+
ts.isCallExpression(node) &&
87+
ts.isIdentifier(node.expression) &&
88+
node.expression.text === "require" &&
89+
ts.isStringLiteral(node.arguments[0]) &&
90+
node.arguments.length === 1;
91+
92+
const isAsyncImport = (node: ts.Node): node is ts.CallExpression =>
93+
ts.isCallExpression(node) &&
94+
node.expression.kind === ts.SyntaxKind.ImportKeyword &&
95+
ts.isStringLiteral(node.arguments[0]) &&
96+
node.arguments.length === 1;
97+
8498
function visit(node: ts.Node): ts.VisitResult<ts.Node> {
8599
if (
86100
!isDeclarationFile &&
@@ -92,36 +106,71 @@ const transformer = (_: ts.Program) => (context: ts.TransformationContext) => (
92106
) {
93107
return undefined;
94108
}
95-
if (
96-
ts.isCallExpression(node) &&
97-
ts.isIdentifier(node.expression) &&
98-
node.expression.text === "require" &&
99-
ts.isStringLiteral(node.arguments[0]) &&
100-
node.arguments.length === 1
101-
) {
102-
const firstArg = node.arguments[0] as ts.StringLiteral;
103-
const file = bindModuleToFile(firstArg.text);
104-
if (!file) {
105-
return node;
106-
}
107-
const fileLiteral = ts.createLiteral(file);
108-
return ts.updateCall(node, node.expression, node.typeArguments, [
109-
fileLiteral
110-
]);
109+
110+
if (isRequire(node) || isAsyncImport(node)) {
111+
return unpathRequireAndAsyncImport(node);
111112
}
113+
112114
if (ts.isExternalModuleReference(node)) {
113115
return unpathImportEqualsDeclaration(node);
114116
}
117+
115118
if (ts.isImportDeclaration(node)) {
116119
return unpathImportDeclaration(node);
117120
}
121+
118122
if (ts.isExportDeclaration(node)) {
119123
return unpathExportDeclaration(node);
120124
}
121125

126+
if (ts.isImportTypeNode(node)) {
127+
return unpathImportTypeNode(node);
128+
}
129+
122130
return ts.visitEachChild(node, visit, context);
123131
}
124132

133+
function unpathRequireAndAsyncImport(node: ts.CallExpression) {
134+
const firstArg = node.arguments[0] as ts.StringLiteral;
135+
const file = bindModuleToFile(firstArg.text);
136+
137+
if (!file) {
138+
return node;
139+
}
140+
141+
const fileLiteral = ts.createLiteral(file);
142+
143+
return ts.updateCall(node, node.expression, node.typeArguments, [
144+
fileLiteral
145+
]);
146+
}
147+
148+
function unpathImportTypeNode(node: ts.ImportTypeNode) {
149+
const argument = node.argument as ts.LiteralTypeNode;
150+
const literal = argument.literal;
151+
152+
if (!ts.isStringLiteral(literal)) {
153+
return node;
154+
}
155+
156+
const file = bindModuleToFile(literal.text);
157+
158+
if (!file) {
159+
return node;
160+
}
161+
162+
const fileLiteral = ts.createLiteral(file);
163+
const fileArgument = ts.updateLiteralTypeNode(argument, fileLiteral);
164+
165+
return ts.updateImportTypeNode(
166+
node,
167+
fileArgument,
168+
node.qualifier,
169+
node.typeArguments,
170+
node.isTypeOf
171+
);
172+
}
173+
125174
function unpathImportEqualsDeclaration(node: ts.ExternalModuleReference) {
126175
if (!ts.isStringLiteral(node.expression)) {
127176
return node;

tests/__fixtures/with-path/core/index.ts

+17
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,20 @@ const n: NoRuntimecodeHere = null as any;
2020

2121
subs(2, 3);
2222
const a = new A("");
23+
24+
(async function() {
25+
const Logger = await (await import("@dynamic/logger")).Logger;
26+
const logger = new Logger();
27+
28+
logger.log('hi');
29+
})();
30+
31+
(async function() {
32+
const Tester = (await import("@dynamic/tester")).Tester;
33+
34+
const testerConst = (await import("@dynamic/tester")).tester;
35+
const testerClass = new Tester();
36+
37+
testerClass.test(12);
38+
testerConst.test("12");
39+
})();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
type Tester = import("@dynamic/tester").Tester;
2+
3+
export class Logger {
4+
level: string = 'hi';
5+
tester: Tester;
6+
7+
public log (x: string): void {
8+
console.log(x);
9+
};
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export class Tester {
2+
public test (x: number): void {
3+
console.log(x);
4+
};
5+
}
6+
7+
export const tester = {
8+
test: (x: string) => console.log(x),
9+
};

0 commit comments

Comments
 (0)