susee 0.1.3 → 0.1.4
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/README.md +20 -5
- package/dist/index.cjs +1 -1984
- package/dist/index.cjs.map +1 -8
- package/dist/index.d.cts +8 -14
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +8 -14
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -1946
- package/dist/index.mjs.map +1 -8
- package/package.json +7 -8
package/dist/index.mjs
CHANGED
|
@@ -5,1949 +5,4 @@ Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
|
|
5
5
|
this file except in compliance with the License. You may obtain a copy of the
|
|
6
6
|
License at http://www.apache.org/licenses/LICENSE-2.0
|
|
7
7
|
***************************************************************************** */
|
|
8
|
-
import TsConfig from "@suseejs/tsconfig";
|
|
9
|
-
import dependencies from "@suseejs/dependencies";
|
|
10
|
-
import fs from "node:fs";
|
|
11
|
-
import path from "node:path";
|
|
12
|
-
import resolves from "@phothinmaung/resolves";
|
|
13
|
-
import tcolor from "@suseejs/tcolor";
|
|
14
|
-
import transformFunction from "@suseejs/transformer";
|
|
15
|
-
import ts from "typescript";
|
|
16
|
-
import utilities from "@suseejs/utils";
|
|
17
|
-
import { Buffer } from "node:buffer";
|
|
18
|
-
//src/lib/bundle/bundleCreator.ts
|
|
19
|
-
/**
|
|
20
|
-
* Creates a BundleCreator function that transforms a DepsFile with a given BundleVisitor and typescript compiler options.
|
|
21
|
-
* @param {BundleVisitor} bundleVisitor - a BundleVisitor function that takes a context, depsTree, sourceFile, and any number of arguments.
|
|
22
|
-
* @param {ts.CompilerOptions} compilerOptions - typescript compiler options.
|
|
23
|
-
* @param {...any} args - any number of arguments to pass to the BundleVisitor function.
|
|
24
|
-
* @returns {BundleCreator} a BundleCreator function that takes a DepsFile and returns a transformed DepsFile.
|
|
25
|
-
*/
|
|
26
|
-
const bundleCreator = (bundleVisitor, compilerOptions, ...args) => {
|
|
27
|
-
return (depsTree) => {
|
|
28
|
-
const sourceFile = ts.createSourceFile(depsTree.file, depsTree.content, ts.ScriptTarget.Latest, true);
|
|
29
|
-
const transformer = (context) => {
|
|
30
|
-
const visitor = bundleVisitor(context, depsTree, sourceFile, ...args);
|
|
31
|
-
return (rootNode) => ts.visitNode(rootNode, visitor);
|
|
32
|
-
};
|
|
33
|
-
let _content = transformFunction(transformer, sourceFile, compilerOptions);
|
|
34
|
-
_content = _content.replace(/^s*;\s*$/gm, "").trim();
|
|
35
|
-
const { content, ...rest } = depsTree;
|
|
36
|
-
return { content: _content, ...rest };
|
|
37
|
-
};
|
|
38
|
-
};
|
|
39
|
-
//src/lib/bundle/mergeImportsStatement.ts
|
|
40
|
-
function mergeImportsStatement(imports) {
|
|
41
|
-
const importMap = new Map();
|
|
42
|
-
const typeImportMap = new Map();
|
|
43
|
-
const defaultImports = new Map();
|
|
44
|
-
const typeDefaultImports = new Map();
|
|
45
|
-
const namespaceImports = new Map();
|
|
46
|
-
// Parse each import statement
|
|
47
|
-
for (const importStr of imports) {
|
|
48
|
-
const importMatch = importStr.match(/import\s+(?:type\s+)?(?:(.*?)\s+from\s+)?["']([^"']+)["'];?/);
|
|
49
|
-
if (!importMatch)
|
|
50
|
-
continue;
|
|
51
|
-
const [, importClause, _modulePath] = importMatch;
|
|
52
|
-
const isTypeImport = importStr.includes("import type");
|
|
53
|
-
const modulePath = _modulePath;
|
|
54
|
-
if (!importClause) {
|
|
55
|
-
// Default import or side-effect import
|
|
56
|
-
const defaultMatch = importStr.match(/import\s+(?:type\s+)?(\w+)/);
|
|
57
|
-
if (defaultMatch) {
|
|
58
|
-
const importName = defaultMatch[1];
|
|
59
|
-
const targetMap = isTypeImport ? typeDefaultImports : defaultImports;
|
|
60
|
-
if (!targetMap.has(modulePath))
|
|
61
|
-
targetMap.set(modulePath, new Set());
|
|
62
|
-
targetMap.get(modulePath)?.add(importName);
|
|
63
|
-
}
|
|
64
|
-
continue;
|
|
65
|
-
}
|
|
66
|
-
if (importClause.startsWith("{")) {
|
|
67
|
-
// Named imports: import { a, b } from 'module'
|
|
68
|
-
const targetMap = isTypeImport ? typeImportMap : importMap;
|
|
69
|
-
if (!targetMap.has(modulePath))
|
|
70
|
-
targetMap.set(modulePath, new Set());
|
|
71
|
-
const names = importClause
|
|
72
|
-
.replace(/[{}]/g, "")
|
|
73
|
-
.split(",")
|
|
74
|
-
.map((s) => s.trim())
|
|
75
|
-
.filter(Boolean);
|
|
76
|
-
// biome-ignore lint/suspicious/useIterableCallbackReturn : just add name for names each
|
|
77
|
-
names.forEach((name) => targetMap.get(modulePath)?.add(name));
|
|
78
|
-
}
|
|
79
|
-
else if (importClause.startsWith("* as")) {
|
|
80
|
-
// Namespace import: import * as name from 'module'
|
|
81
|
-
const namespaceMatch = importClause.match(/\*\s+as\s+(\w+)/);
|
|
82
|
-
if (namespaceMatch) {
|
|
83
|
-
const namespaceName = namespaceMatch[1];
|
|
84
|
-
if (!namespaceImports.has(modulePath))
|
|
85
|
-
namespaceImports.set(modulePath, new Set());
|
|
86
|
-
namespaceImports.get(modulePath)?.add(namespaceName);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
else {
|
|
90
|
-
// Default import: import name from 'module'
|
|
91
|
-
const targetMap = isTypeImport ? typeDefaultImports : defaultImports;
|
|
92
|
-
if (!targetMap.has(modulePath))
|
|
93
|
-
targetMap.set(modulePath, new Set());
|
|
94
|
-
targetMap.get(modulePath)?.add(importClause.trim());
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
const mergedImports = [];
|
|
98
|
-
// Process named imports - remove type imports that have regular imports
|
|
99
|
-
for (const [modulePath, regularNames] of importMap) {
|
|
100
|
-
const typeNames = typeImportMap.get(modulePath) || new Set();
|
|
101
|
-
// Only include type names that don't have regular imports
|
|
102
|
-
const finalNames = new Set([...regularNames]);
|
|
103
|
-
for (const typeName of typeNames) {
|
|
104
|
-
if (!regularNames.has(typeName)) {
|
|
105
|
-
finalNames.add(typeName);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
if (finalNames.size > 0) {
|
|
109
|
-
const importNames = Array.from(finalNames).sort().join(", ");
|
|
110
|
-
mergedImports.push(`import { ${importNames} } from "${modulePath}";`);
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
// Add remaining type-only imports (where no regular imports exist for the module)
|
|
114
|
-
for (const [modulePath, typeNames] of typeImportMap) {
|
|
115
|
-
if (!importMap.has(modulePath) && typeNames.size > 0) {
|
|
116
|
-
const importNames = Array.from(typeNames).sort().join(", ");
|
|
117
|
-
mergedImports.push(`import type { ${importNames} } from "${modulePath}";`);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
// Process default imports - remove type default imports that have regular default imports
|
|
121
|
-
for (const [modulePath, regularDefaultNames] of defaultImports) {
|
|
122
|
-
const typeDefaultNames = typeDefaultImports.get(modulePath) || new Set();
|
|
123
|
-
// Only include type default names that don't have regular default imports
|
|
124
|
-
const finalNames = new Set([...regularDefaultNames]);
|
|
125
|
-
for (const typeName of typeDefaultNames) {
|
|
126
|
-
if (!regularDefaultNames.has(typeName)) {
|
|
127
|
-
finalNames.add(typeName);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
if (finalNames.size > 0) {
|
|
131
|
-
const importNames = Array.from(finalNames).join(", ");
|
|
132
|
-
mergedImports.push(`import ${importNames} from "${modulePath}";`);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
// Add remaining type-only default imports
|
|
136
|
-
for (const [modulePath, typeDefaultNames] of typeDefaultImports) {
|
|
137
|
-
if (!defaultImports.has(modulePath) && typeDefaultNames.size > 0) {
|
|
138
|
-
const importNames = Array.from(typeDefaultNames).join(", ");
|
|
139
|
-
mergedImports.push(`import type ${importNames} from "${modulePath}";`);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
// Process namespace imports
|
|
143
|
-
for (const [modulePath, names] of namespaceImports) {
|
|
144
|
-
if (names.size > 0) {
|
|
145
|
-
const importNames = Array.from(names).join(", ");
|
|
146
|
-
mergedImports.push(`import * as ${importNames} from "${modulePath}";`);
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
return mergedImports.sort();
|
|
150
|
-
}
|
|
151
|
-
//src/lib/bundle/visitors/anonymousCallExpression.ts
|
|
152
|
-
/**
|
|
153
|
-
* A BundleVisitor that updates the call expression, property access expression, and new expression
|
|
154
|
-
* with the anonymous default import name.
|
|
155
|
-
*/
|
|
156
|
-
const anonymousCallExpressionVisitor = (context, depsTree, _sourceFile, exportDefaultImportNameMap) => {
|
|
157
|
-
const { factory } = context;
|
|
158
|
-
const visit = (node) => {
|
|
159
|
-
if (ts.isCallExpression(node)) {
|
|
160
|
-
if (ts.isIdentifier(node.expression)) {
|
|
161
|
-
const base = node.expression.text;
|
|
162
|
-
const mapping = exportDefaultImportNameMap.find((m) => m.base === base && m.file === depsTree.file);
|
|
163
|
-
if (mapping) {
|
|
164
|
-
return factory.updateCallExpression(node, factory.createIdentifier(mapping.newName), node.typeArguments, node.arguments);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
else if (ts.isPropertyAccessExpression(node)) {
|
|
169
|
-
if (ts.isIdentifier(node.expression)) {
|
|
170
|
-
const base = node.expression.text;
|
|
171
|
-
const mapping = exportDefaultImportNameMap.find((m) => m.base === base && m.file === depsTree.file);
|
|
172
|
-
if (mapping) {
|
|
173
|
-
return factory.updatePropertyAccessExpression(node, factory.createIdentifier(mapping.newName), node.name);
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
else if (ts.isNewExpression(node)) {
|
|
178
|
-
if (ts.isIdentifier(node.expression)) {
|
|
179
|
-
const base = node.expression.text;
|
|
180
|
-
const mapping = exportDefaultImportNameMap.find((m) => m.base === base && m.file === depsTree.file);
|
|
181
|
-
if (mapping) {
|
|
182
|
-
return factory.updateNewExpression(node, factory.createIdentifier(mapping.newName), node.typeArguments, node.arguments);
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
// for export specifier it is focus on entry file
|
|
186
|
-
}
|
|
187
|
-
else if (ts.isExportSpecifier(node)) {
|
|
188
|
-
if (ts.isIdentifier(node.name)) {
|
|
189
|
-
const base = node.name.text;
|
|
190
|
-
const mapping = exportDefaultImportNameMap.find((m) => m.base === base && m.file === depsTree.file);
|
|
191
|
-
if (mapping) {
|
|
192
|
-
return factory.updateExportSpecifier(node, node.isTypeOnly, node.propertyName, factory.createIdentifier(mapping.newName));
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
return ts.visitEachChild(node, visit, context);
|
|
197
|
-
};
|
|
198
|
-
return visit;
|
|
199
|
-
};
|
|
200
|
-
//src/lib/bundle/visitors/visitorHelpers.ts
|
|
201
|
-
const normalizePathKey = (filePath) => {
|
|
202
|
-
const parsed = path.parse(filePath);
|
|
203
|
-
let noExt = path.join(parsed.dir, parsed.name);
|
|
204
|
-
if (parsed.name === "index") {
|
|
205
|
-
noExt = parsed.dir;
|
|
206
|
-
}
|
|
207
|
-
return path.normalize(noExt);
|
|
208
|
-
};
|
|
209
|
-
const getFileKey = (filePath) => normalizePathKey(filePath);
|
|
210
|
-
const getModuleKeyFromSpecifier = (moduleSpecifier, sourceFile, containingFile) => {
|
|
211
|
-
let spec = "";
|
|
212
|
-
if (ts.isStringLiteral(moduleSpecifier)) {
|
|
213
|
-
spec = moduleSpecifier.text;
|
|
214
|
-
}
|
|
215
|
-
else {
|
|
216
|
-
spec = moduleSpecifier.getText(sourceFile).replace(/^['"]|['"]$/g, "");
|
|
217
|
-
}
|
|
218
|
-
if (spec.startsWith(".") || spec.startsWith("/")) {
|
|
219
|
-
const baseDir = path.dirname(containingFile);
|
|
220
|
-
return normalizePathKey(path.resolve(baseDir, spec));
|
|
221
|
-
}
|
|
222
|
-
return spec;
|
|
223
|
-
};
|
|
224
|
-
function uniqueName() {
|
|
225
|
-
const storedPrefix = new Map();
|
|
226
|
-
const obj = {
|
|
227
|
-
setPrefix({ key, value }) {
|
|
228
|
-
const names = [];
|
|
229
|
-
let _fix;
|
|
230
|
-
if (storedPrefix.has(key)) {
|
|
231
|
-
console.warn(`${key} already exist`);
|
|
232
|
-
throw new Error();
|
|
233
|
-
}
|
|
234
|
-
else {
|
|
235
|
-
_fix = value;
|
|
236
|
-
storedPrefix.set(key, value);
|
|
237
|
-
}
|
|
238
|
-
function getName(input) {
|
|
239
|
-
const length = names.length;
|
|
240
|
-
const _name = _fix
|
|
241
|
-
? `${_fix}${input}_${length + 1}`
|
|
242
|
-
: `$nyein${input}_${length + 1}`;
|
|
243
|
-
names.push(_name);
|
|
244
|
-
return _name;
|
|
245
|
-
}
|
|
246
|
-
return { getName };
|
|
247
|
-
},
|
|
248
|
-
getPrefix(key) {
|
|
249
|
-
if (storedPrefix.has(key)) {
|
|
250
|
-
return storedPrefix.get(key);
|
|
251
|
-
}
|
|
252
|
-
},
|
|
253
|
-
};
|
|
254
|
-
return obj;
|
|
255
|
-
}
|
|
256
|
-
//src/lib/bundle/visitors/anonymousExport.ts
|
|
257
|
-
const prefixKey = "AnonymousName";
|
|
258
|
-
const genName = uniqueName().setPrefix({ key: prefixKey, value: "a_" });
|
|
259
|
-
/**
|
|
260
|
-
* A BundleVisitor that updates the call expression, property access expression, and new expression
|
|
261
|
-
* with the anonymous default import name.
|
|
262
|
-
*/
|
|
263
|
-
const anonymousExportVisitor = (context, depsTree, sourceFile, exportDefaultExportNameMap) => {
|
|
264
|
-
const { factory } = context;
|
|
265
|
-
const visit = (node) => {
|
|
266
|
-
const fileName = path.basename(depsTree.file).split(".")[0];
|
|
267
|
-
if ((ts.isFunctionDeclaration(node) || ts.isClassDeclaration(node)) &&
|
|
268
|
-
node.name === undefined) {
|
|
269
|
-
let exp = false;
|
|
270
|
-
let def = false;
|
|
271
|
-
node.modifiers?.forEach((mod) => {
|
|
272
|
-
if (mod.kind === ts.SyntaxKind.ExportKeyword) {
|
|
273
|
-
exp = true;
|
|
274
|
-
}
|
|
275
|
-
if (mod.kind === ts.SyntaxKind.DefaultKeyword) {
|
|
276
|
-
def = true;
|
|
277
|
-
}
|
|
278
|
-
});
|
|
279
|
-
if (exp && def) {
|
|
280
|
-
const base = genName.getName(fileName);
|
|
281
|
-
exportDefaultExportNameMap.push({
|
|
282
|
-
base,
|
|
283
|
-
file: fileName,
|
|
284
|
-
newName: base,
|
|
285
|
-
isEd: true,
|
|
286
|
-
});
|
|
287
|
-
if (ts.isFunctionDeclaration(node)) {
|
|
288
|
-
return factory.updateFunctionDeclaration(node, node.modifiers, node.asteriskToken, factory.createIdentifier(base), node.typeParameters, node.parameters, node.type, node.body);
|
|
289
|
-
}
|
|
290
|
-
else if (ts.isClassDeclaration(node)) {
|
|
291
|
-
return factory.updateClassDeclaration(node, node.modifiers, factory.createIdentifier(base), node.typeParameters, node.heritageClauses, node.members);
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
else if (ts.isExportAssignment(node) &&
|
|
296
|
-
!node.name &&
|
|
297
|
-
!node.isExportEquals) {
|
|
298
|
-
if (ts.isArrowFunction(node.expression)) {
|
|
299
|
-
const base = genName.getName(fileName);
|
|
300
|
-
const arrowFunctionNode = factory.createArrowFunction(node.expression.modifiers, node.expression.typeParameters, node.expression.parameters, node.expression.type, node.expression.equalsGreaterThanToken, node.expression.body);
|
|
301
|
-
const variableDeclarationNode = factory.createVariableDeclaration(factory.createIdentifier(base), node.expression.exclamationToken, node.expression.type, arrowFunctionNode);
|
|
302
|
-
const variableDeclarationListNode = factory.createVariableDeclarationList([variableDeclarationNode], ts.NodeFlags.Const);
|
|
303
|
-
const variableStatementNode = factory.createVariableStatement(node.expression.modifiers, variableDeclarationListNode);
|
|
304
|
-
const exportAssignmentNode = factory.createExportAssignment(undefined, undefined, factory.createIdentifier(base));
|
|
305
|
-
exportDefaultExportNameMap.push({
|
|
306
|
-
base,
|
|
307
|
-
file: fileName,
|
|
308
|
-
newName: base,
|
|
309
|
-
isEd: true,
|
|
310
|
-
});
|
|
311
|
-
return factory.updateSourceFile(sourceFile, [variableStatementNode, exportAssignmentNode], sourceFile.isDeclarationFile, sourceFile.referencedFiles, sourceFile.typeReferenceDirectives, sourceFile.hasNoDefaultLib, sourceFile.libReferenceDirectives);
|
|
312
|
-
}
|
|
313
|
-
else if (ts.isObjectLiteralExpression(node.expression)) {
|
|
314
|
-
const base = genName.getName(fileName);
|
|
315
|
-
const variableDeclarationNode = factory.createVariableDeclaration(factory.createIdentifier(base), undefined, undefined, node.expression);
|
|
316
|
-
const variableDeclarationListNode = factory.createVariableDeclarationList([variableDeclarationNode], ts.NodeFlags.Const);
|
|
317
|
-
const variableStatementNode = factory.createVariableStatement(undefined, variableDeclarationListNode);
|
|
318
|
-
const exportAssignmentNode = factory.createExportAssignment(undefined, undefined, factory.createIdentifier(base));
|
|
319
|
-
exportDefaultExportNameMap.push({
|
|
320
|
-
base,
|
|
321
|
-
file: fileName,
|
|
322
|
-
newName: base,
|
|
323
|
-
isEd: true,
|
|
324
|
-
});
|
|
325
|
-
return factory.updateSourceFile(sourceFile, [variableStatementNode, exportAssignmentNode], sourceFile.isDeclarationFile, sourceFile.referencedFiles, sourceFile.typeReferenceDirectives, sourceFile.hasNoDefaultLib, sourceFile.libReferenceDirectives);
|
|
326
|
-
}
|
|
327
|
-
else if (ts.isArrayLiteralExpression(node.expression)) {
|
|
328
|
-
const base = genName.getName(fileName);
|
|
329
|
-
const arrayLiteralExpressionNode = factory.createArrayLiteralExpression(node.expression.elements, true);
|
|
330
|
-
const variableDeclarationNode = factory.createVariableDeclaration(factory.createIdentifier(base), undefined, undefined, arrayLiteralExpressionNode);
|
|
331
|
-
const variableDeclarationListNode = factory.createVariableDeclarationList([variableDeclarationNode], ts.NodeFlags.Const);
|
|
332
|
-
const variableStatementNode = factory.createVariableStatement(undefined, variableDeclarationListNode);
|
|
333
|
-
const exportAssignmentNode = factory.createExportAssignment(undefined, undefined, factory.createIdentifier(base));
|
|
334
|
-
exportDefaultExportNameMap.push({
|
|
335
|
-
base,
|
|
336
|
-
file: fileName,
|
|
337
|
-
newName: base,
|
|
338
|
-
isEd: true,
|
|
339
|
-
});
|
|
340
|
-
return factory.updateSourceFile(sourceFile, [variableStatementNode, exportAssignmentNode], sourceFile.isDeclarationFile, sourceFile.referencedFiles, sourceFile.typeReferenceDirectives, sourceFile.hasNoDefaultLib, sourceFile.libReferenceDirectives);
|
|
341
|
-
}
|
|
342
|
-
else if (ts.isStringLiteral(node.expression)) {
|
|
343
|
-
const base = genName.getName(fileName);
|
|
344
|
-
const stringLiteralNode = factory.createStringLiteral(node.expression.text);
|
|
345
|
-
const variableDeclarationNode = factory.createVariableDeclaration(factory.createIdentifier(base), undefined, undefined, stringLiteralNode);
|
|
346
|
-
const variableDeclarationListNode = factory.createVariableDeclarationList([variableDeclarationNode], ts.NodeFlags.Const);
|
|
347
|
-
const variableStatementNode = factory.createVariableStatement(undefined, variableDeclarationListNode);
|
|
348
|
-
const exportAssignmentNode = factory.createExportAssignment(undefined, undefined, factory.createIdentifier(base));
|
|
349
|
-
exportDefaultExportNameMap.push({
|
|
350
|
-
base,
|
|
351
|
-
file: fileName,
|
|
352
|
-
newName: base,
|
|
353
|
-
isEd: true,
|
|
354
|
-
});
|
|
355
|
-
return factory.updateSourceFile(sourceFile, [variableStatementNode, exportAssignmentNode], sourceFile.isDeclarationFile, sourceFile.referencedFiles, sourceFile.typeReferenceDirectives, sourceFile.hasNoDefaultLib, sourceFile.libReferenceDirectives);
|
|
356
|
-
}
|
|
357
|
-
else if (ts.isNumericLiteral(node.expression)) {
|
|
358
|
-
const base = genName.getName(fileName);
|
|
359
|
-
const numericLiteralNode = factory.createNumericLiteral(node.expression.text);
|
|
360
|
-
const variableDeclarationNode = factory.createVariableDeclaration(factory.createIdentifier(base), undefined, undefined, numericLiteralNode);
|
|
361
|
-
const variableDeclarationListNode = factory.createVariableDeclarationList([variableDeclarationNode], ts.NodeFlags.Const);
|
|
362
|
-
const variableStatementNode = factory.createVariableStatement(undefined, variableDeclarationListNode);
|
|
363
|
-
const exportAssignmentNode = factory.createExportAssignment(undefined, undefined, factory.createIdentifier(base));
|
|
364
|
-
exportDefaultExportNameMap.push({
|
|
365
|
-
base,
|
|
366
|
-
file: fileName,
|
|
367
|
-
newName: base,
|
|
368
|
-
isEd: true,
|
|
369
|
-
});
|
|
370
|
-
return factory.updateSourceFile(sourceFile, [variableStatementNode, exportAssignmentNode], sourceFile.isDeclarationFile, sourceFile.referencedFiles, sourceFile.typeReferenceDirectives, sourceFile.hasNoDefaultLib, sourceFile.libReferenceDirectives);
|
|
371
|
-
}
|
|
372
|
-
} //
|
|
373
|
-
return ts.visitEachChild(node, visit, context);
|
|
374
|
-
};
|
|
375
|
-
return visit;
|
|
376
|
-
};
|
|
377
|
-
//src/lib/bundle/visitors/anonymousImport.ts
|
|
378
|
-
/**
|
|
379
|
-
* A BundleVisitor that updates the import declaration, property access expression, and new expression
|
|
380
|
-
* with the anonymous default import name.
|
|
381
|
-
*/
|
|
382
|
-
const anonymousImportVisitor = (context, depsTree, sourceFile, exportDefaultExportNameMap, exportDefaultImportNameMap) => {
|
|
383
|
-
const { factory } = context;
|
|
384
|
-
const visit = (node) => {
|
|
385
|
-
if (ts.isImportDeclaration(node)) {
|
|
386
|
-
const fileName = node.moduleSpecifier.getText(sourceFile);
|
|
387
|
-
const _name = path.basename(fileName).split(".")[0].trim();
|
|
388
|
-
// check only import default expression
|
|
389
|
-
if (node.importClause?.name && ts.isIdentifier(node.importClause.name)) {
|
|
390
|
-
const base = node.importClause.name.text.trim();
|
|
391
|
-
const mapping = exportDefaultExportNameMap.find((v) => v.file === _name);
|
|
392
|
-
if (mapping) {
|
|
393
|
-
exportDefaultImportNameMap.push({
|
|
394
|
-
base,
|
|
395
|
-
file: depsTree.file,
|
|
396
|
-
newName: mapping.newName,
|
|
397
|
-
isEd: true,
|
|
398
|
-
});
|
|
399
|
-
const newImportClause = factory.updateImportClause(node.importClause, node.importClause.phaseModifier, factory.createIdentifier(mapping.newName), node.importClause.namedBindings);
|
|
400
|
-
return factory.updateImportDeclaration(node, node.modifiers, newImportClause, node.moduleSpecifier, node.attributes);
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
return ts.visitEachChild(node, visit, context);
|
|
405
|
-
};
|
|
406
|
-
return visit;
|
|
407
|
-
};
|
|
408
|
-
//src/lib/bundle/visitors/duplicateCallExpression.ts
|
|
409
|
-
/**
|
|
410
|
-
* A BundleVisitor that updates the call expression, property access expression, and new expression
|
|
411
|
-
* with the anonymous default import name.
|
|
412
|
-
*/
|
|
413
|
-
const duplicateCallExpressionVisitor = (context, depsTree, _sourceFile, callNameMap, importNameMap) => {
|
|
414
|
-
const { factory } = context;
|
|
415
|
-
const visit = (node) => {
|
|
416
|
-
if (ts.isCallExpression(node)) {
|
|
417
|
-
if (ts.isIdentifier(node.expression)) {
|
|
418
|
-
const base = node.expression.text;
|
|
419
|
-
let new_name = null;
|
|
420
|
-
const mapping = callNameMap.find((m) => m.base === base && m.file === depsTree.file);
|
|
421
|
-
const importMapping = importNameMap.find((m) => m.base === base && m.file === depsTree.file);
|
|
422
|
-
if (mapping) {
|
|
423
|
-
new_name = mapping.newName;
|
|
424
|
-
}
|
|
425
|
-
else if (importMapping) {
|
|
426
|
-
new_name = importMapping.newName;
|
|
427
|
-
//flag.push(new_name);
|
|
428
|
-
}
|
|
429
|
-
if (new_name) {
|
|
430
|
-
return factory.updateCallExpression(node, factory.createIdentifier(new_name), node.typeArguments, node.arguments);
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
else if (ts.isPropertyAccessExpression(node)) {
|
|
435
|
-
if (ts.isIdentifier(node.expression)) {
|
|
436
|
-
const base = node.expression.text;
|
|
437
|
-
let new_name = null;
|
|
438
|
-
const mapping = callNameMap.find((m) => m.base === base && m.file === depsTree.file);
|
|
439
|
-
const importMapping = importNameMap.find((m) => m.base === base && m.file === depsTree.file);
|
|
440
|
-
if (mapping) {
|
|
441
|
-
new_name = mapping.newName;
|
|
442
|
-
}
|
|
443
|
-
else if (importMapping) {
|
|
444
|
-
new_name = importMapping.newName;
|
|
445
|
-
}
|
|
446
|
-
if (new_name) {
|
|
447
|
-
return factory.updatePropertyAccessExpression(node, factory.createIdentifier(new_name), node.name);
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
}
|
|
451
|
-
else if (ts.isNewExpression(node)) {
|
|
452
|
-
if (ts.isIdentifier(node.expression)) {
|
|
453
|
-
const base = node.expression.text;
|
|
454
|
-
let new_name = null;
|
|
455
|
-
const mapping = callNameMap.find((m) => m.base === base && m.file === depsTree.file);
|
|
456
|
-
const importMapping = importNameMap.find((m) => m.base === base && m.file === depsTree.file);
|
|
457
|
-
if (mapping) {
|
|
458
|
-
new_name = mapping.newName;
|
|
459
|
-
}
|
|
460
|
-
else if (importMapping) {
|
|
461
|
-
new_name = importMapping.newName;
|
|
462
|
-
}
|
|
463
|
-
if (new_name) {
|
|
464
|
-
return factory.updateNewExpression(node, factory.createIdentifier(new_name), node.typeArguments, node.arguments);
|
|
465
|
-
}
|
|
466
|
-
}
|
|
467
|
-
}
|
|
468
|
-
/* ----------------------Returns for visitor function------------------------------- */
|
|
469
|
-
return ts.visitEachChild(node, visit, context);
|
|
470
|
-
};
|
|
471
|
-
return visit;
|
|
472
|
-
};
|
|
473
|
-
//src/lib/bundle/visitors/duplicateCollection.ts
|
|
474
|
-
/**
|
|
475
|
-
* A BundleVisitor that updates the collection (variable, function, class, etc)
|
|
476
|
-
* declaration with the anonymous default import name.
|
|
477
|
-
*
|
|
478
|
-
* @param {BundleVisitor} context - The BundleVisitor context.
|
|
479
|
-
* @param {DepsTree} depsTree - The deps tree object.
|
|
480
|
-
* @param {SourceFile} sourceFile - The source file object.
|
|
481
|
-
* @param {DuplicatesNameMap} namesMap - The DuplicatesNameMap object.
|
|
482
|
-
* @return {NodeVisit} visit - The NodeVisit function.
|
|
483
|
-
*/
|
|
484
|
-
const duplicateCollectionVisitor = (context, depsTree, _sourceFile, namesMap) => {
|
|
485
|
-
//const { factory } = context;
|
|
486
|
-
const visit = (node, isGlobalScope = true) => {
|
|
487
|
-
// Global declarations များကိုသာ collect လုပ်မယ်
|
|
488
|
-
if (isGlobalScope) {
|
|
489
|
-
// Variable statements (const, let, var)
|
|
490
|
-
if (ts.isVariableStatement(node)) {
|
|
491
|
-
node.declarationList.declarations.forEach((decl) => {
|
|
492
|
-
if (ts.isIdentifier(decl.name)) {
|
|
493
|
-
const $name = decl.name.text;
|
|
494
|
-
if (!namesMap.has($name)) {
|
|
495
|
-
namesMap.set($name, new Set([{ file: depsTree.file }]));
|
|
496
|
-
}
|
|
497
|
-
else {
|
|
498
|
-
// biome-ignore lint/style/noNonNullAssertion : !namesMap.has($name) before
|
|
499
|
-
namesMap.get($name).add({ file: depsTree.file });
|
|
500
|
-
}
|
|
501
|
-
}
|
|
502
|
-
});
|
|
503
|
-
}
|
|
504
|
-
// Function, Class, Enum, Interface, Type declarations
|
|
505
|
-
else if (ts.isFunctionDeclaration(node) ||
|
|
506
|
-
ts.isClassDeclaration(node) ||
|
|
507
|
-
ts.isEnumDeclaration(node) ||
|
|
508
|
-
ts.isInterfaceDeclaration(node) ||
|
|
509
|
-
ts.isTypeAliasDeclaration(node)) {
|
|
510
|
-
const $name = node.name?.text;
|
|
511
|
-
if ($name) {
|
|
512
|
-
if (!namesMap.has($name)) {
|
|
513
|
-
namesMap.set($name, new Set([{ file: depsTree.file }]));
|
|
514
|
-
}
|
|
515
|
-
else {
|
|
516
|
-
// biome-ignore lint/style/noNonNullAssertion : !namesMap.has($name) before
|
|
517
|
-
namesMap.get($name).add({ file: depsTree.file });
|
|
518
|
-
}
|
|
519
|
-
}
|
|
520
|
-
}
|
|
521
|
-
}
|
|
522
|
-
// Local scope ထဲရောက်သွားတဲ့ node တွေအတွက် recursive visit
|
|
523
|
-
if (ts.isBlock(node) ||
|
|
524
|
-
ts.isFunctionDeclaration(node) ||
|
|
525
|
-
ts.isFunctionExpression(node) ||
|
|
526
|
-
ts.isArrowFunction(node) ||
|
|
527
|
-
ts.isMethodDeclaration(node) ||
|
|
528
|
-
ts.isClassDeclaration(node)) {
|
|
529
|
-
// Local scope ထဲကို ဝင်သွားပြီဆိုတာနဲ့ isGlobalScope = false
|
|
530
|
-
if (ts.isBlock(node)) {
|
|
531
|
-
ts.visitNodes(node.statements, (child) => visit(child, false));
|
|
532
|
-
}
|
|
533
|
-
else {
|
|
534
|
-
ts.forEachChild(node, (child) => {
|
|
535
|
-
visit(child, false);
|
|
536
|
-
});
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
else {
|
|
540
|
-
// Global scope ထဲဆက်ရှိနေတဲ့ node တွေအတွက်
|
|
541
|
-
return ts.visitEachChild(node, (child) => visit(child, isGlobalScope), context);
|
|
542
|
-
}
|
|
543
|
-
/* ----------------------Returns for visitNode function------------------------------- */
|
|
544
|
-
return node;
|
|
545
|
-
};
|
|
546
|
-
return visit;
|
|
547
|
-
};
|
|
548
|
-
//src/lib/bundle/visitors/duplicateExportExpression.ts
|
|
549
|
-
/**
|
|
550
|
-
* A BundleVisitor that updates the call expression, property access expression, and new expression
|
|
551
|
-
* with the anonymous default import name.
|
|
552
|
-
*/
|
|
553
|
-
const duplicateExportExpressionVisitor = (context, depsTree, _sourceFile, callNameMap, importNameMap, exportNameMap) => {
|
|
554
|
-
const { factory } = context;
|
|
555
|
-
const visit = (node) => {
|
|
556
|
-
if (ts.isExportSpecifier(node)) {
|
|
557
|
-
if (ts.isIdentifier(node.name)) {
|
|
558
|
-
const base = node.name.text;
|
|
559
|
-
let new_name = null;
|
|
560
|
-
const mapping = callNameMap.find((m) => m.base === base && m.file === depsTree.file);
|
|
561
|
-
const importMapping = importNameMap.find((m) => m.base === base && m.file === depsTree.file);
|
|
562
|
-
if (mapping) {
|
|
563
|
-
exportNameMap.push({
|
|
564
|
-
base,
|
|
565
|
-
file: getFileKey(depsTree.file),
|
|
566
|
-
newName: mapping.newName,
|
|
567
|
-
});
|
|
568
|
-
new_name = mapping.newName;
|
|
569
|
-
}
|
|
570
|
-
else if (importMapping) {
|
|
571
|
-
new_name = importMapping.newName;
|
|
572
|
-
}
|
|
573
|
-
if (new_name) {
|
|
574
|
-
return factory.updateExportSpecifier(node, node.isTypeOnly, node.propertyName, factory.createIdentifier(new_name));
|
|
575
|
-
}
|
|
576
|
-
}
|
|
577
|
-
}
|
|
578
|
-
else if (ts.isExportAssignment(node)) {
|
|
579
|
-
const expr = node.expression;
|
|
580
|
-
if (ts.isIdentifier(expr)) {
|
|
581
|
-
const base = expr.text;
|
|
582
|
-
let new_name = null;
|
|
583
|
-
const mapping = callNameMap.find((m) => m.base === base && m.file === depsTree.file);
|
|
584
|
-
const importMapping = importNameMap.find((m) => m.base === base && m.file === depsTree.file);
|
|
585
|
-
if (mapping) {
|
|
586
|
-
exportNameMap.push({
|
|
587
|
-
base,
|
|
588
|
-
file: getFileKey(depsTree.file),
|
|
589
|
-
newName: mapping.newName,
|
|
590
|
-
});
|
|
591
|
-
new_name = mapping.newName;
|
|
592
|
-
}
|
|
593
|
-
else if (importMapping) {
|
|
594
|
-
new_name = importMapping.newName;
|
|
595
|
-
}
|
|
596
|
-
if (new_name) {
|
|
597
|
-
return factory.updateExportAssignment(node, node.modifiers, factory.createIdentifier(new_name));
|
|
598
|
-
}
|
|
599
|
-
}
|
|
600
|
-
}
|
|
601
|
-
/* ----------------------Returns for visitor function------------------------------- */
|
|
602
|
-
return ts.visitEachChild(node, visit, context);
|
|
603
|
-
};
|
|
604
|
-
return visit;
|
|
605
|
-
};
|
|
606
|
-
//src/lib/bundle/visitors/duplicateImportExpression.ts
|
|
607
|
-
/**
|
|
608
|
-
* A BundleVisitor that updates the import declaration, property access expression, and new expression
|
|
609
|
-
* with the anonymous default import name.
|
|
610
|
-
*
|
|
611
|
-
* @param {BundleVisitor} context - The BundleVisitor context.
|
|
612
|
-
* @param {DepsTree} depsTree - The deps tree object.
|
|
613
|
-
* @param {SourceFile} sourceFile - The source file object.
|
|
614
|
-
* @param {NamesSets} exportNameMap - The export name map object.
|
|
615
|
-
* @param {NamesSets} importNameMap - The import name map object.
|
|
616
|
-
* @return {NodeVisit} visit - The NodeVisit function.
|
|
617
|
-
*/
|
|
618
|
-
const duplicateImportExpressionVisitor = (context, depsTree, sourceFile, exportNameMap, importNameMap) => {
|
|
619
|
-
const { factory } = context;
|
|
620
|
-
const visit = (node) => {
|
|
621
|
-
if (ts.isImportDeclaration(node)) {
|
|
622
|
-
const moduleKey = getModuleKeyFromSpecifier(node.moduleSpecifier, sourceFile, depsTree.file);
|
|
623
|
-
let baseNames = [];
|
|
624
|
-
if (node.importClause?.namedBindings &&
|
|
625
|
-
ts.isNamedImports(node.importClause.namedBindings)) {
|
|
626
|
-
baseNames = node.importClause.namedBindings.elements.map((el) => el.name.text.trim());
|
|
627
|
-
}
|
|
628
|
-
// import default expression
|
|
629
|
-
if (node.importClause?.name && ts.isIdentifier(node.importClause.name)) {
|
|
630
|
-
const base = node.importClause.name.text.trim();
|
|
631
|
-
const mapping = exportNameMap.find((m) => m.base === base && m.file === moduleKey);
|
|
632
|
-
if (mapping) {
|
|
633
|
-
importNameMap.push({
|
|
634
|
-
base: mapping.base,
|
|
635
|
-
file: depsTree.file,
|
|
636
|
-
newName: mapping.newName,
|
|
637
|
-
});
|
|
638
|
-
const newImportClause = factory.updateImportClause(node.importClause, node.importClause.phaseModifier, factory.createIdentifier(mapping.newName), node.importClause.namedBindings);
|
|
639
|
-
return factory.updateImportDeclaration(node, node.modifiers, newImportClause, node.moduleSpecifier, node.attributes);
|
|
640
|
-
}
|
|
641
|
-
}
|
|
642
|
-
// import name , `import{ ... }`
|
|
643
|
-
if (baseNames.length > 0 &&
|
|
644
|
-
node.importClause &&
|
|
645
|
-
node.importClause.namedBindings &&
|
|
646
|
-
ts.isNamedImports(node.importClause.namedBindings)) {
|
|
647
|
-
const updatedElements = node.importClause.namedBindings.elements.map((el) => {
|
|
648
|
-
const mapping = exportNameMap.find((m) => m.base === el.name.text.trim() && m.file === moduleKey);
|
|
649
|
-
if (mapping) {
|
|
650
|
-
importNameMap.push({
|
|
651
|
-
base: mapping.base,
|
|
652
|
-
file: depsTree.file,
|
|
653
|
-
newName: mapping.newName,
|
|
654
|
-
});
|
|
655
|
-
return factory.updateImportSpecifier(el, el.isTypeOnly, el.propertyName, factory.createIdentifier(mapping.newName));
|
|
656
|
-
}
|
|
657
|
-
return el;
|
|
658
|
-
});
|
|
659
|
-
const newNamedImports = factory.updateNamedImports(node.importClause.namedBindings, updatedElements);
|
|
660
|
-
const newImportClause = factory.updateImportClause(node.importClause, node.importClause.phaseModifier, node.importClause.name, newNamedImports);
|
|
661
|
-
return factory.updateImportDeclaration(node, node.modifiers, newImportClause, node.moduleSpecifier, node.attributes);
|
|
662
|
-
}
|
|
663
|
-
} //&&
|
|
664
|
-
/* ----------------------Returns for visitor function------------------------------- */
|
|
665
|
-
return ts.visitEachChild(node, visit, context);
|
|
666
|
-
};
|
|
667
|
-
return visit;
|
|
668
|
-
};
|
|
669
|
-
//src/lib/bundle/visitors/duplicateUpdate.ts
|
|
670
|
-
const dupName = uniqueName().setPrefix({
|
|
671
|
-
key: "DuplicatesNames",
|
|
672
|
-
value: "d_",
|
|
673
|
-
});
|
|
674
|
-
/**
|
|
675
|
-
* A BundleVisitor that updates the variable declaration, function declaration, and class declaration
|
|
676
|
-
* with the duplicates name.
|
|
677
|
-
*
|
|
678
|
-
* @param {BundleVisitor} context - The BundleVisitor context.
|
|
679
|
-
* @param {DepsTree} depsTree - The deps tree object.
|
|
680
|
-
* @param {SourceFile} sourceFile - The source file object.
|
|
681
|
-
* @param {DuplicatesNameMap} namesMap - The DuplicatesNameMap object.
|
|
682
|
-
* @param {NamesSets} callNameMap - The NamesSets object.
|
|
683
|
-
* @return {NodeVisit} visit - The NodeVisit function.
|
|
684
|
-
*/
|
|
685
|
-
const duplicateUpdateVisitor = (context, depsTree, _sourceFile, namesMap, callNameMap) => {
|
|
686
|
-
const { factory } = context;
|
|
687
|
-
const visit = (node) => {
|
|
688
|
-
if (ts.isVariableStatement(node)) {
|
|
689
|
-
const newDeclarations = node.declarationList.declarations.map((decl) => {
|
|
690
|
-
if (ts.isIdentifier(decl.name)) {
|
|
691
|
-
const base = decl.name.text;
|
|
692
|
-
// biome-ignore lint/style/noNonNullAssertion : namesMap.has(base) before that get just only size
|
|
693
|
-
if (namesMap.has(base) && namesMap.get(base).size > 1) {
|
|
694
|
-
const newName = dupName.getName(base);
|
|
695
|
-
callNameMap.push({ base, file: depsTree.file, newName });
|
|
696
|
-
return factory.updateVariableDeclaration(decl, factory.createIdentifier(newName), decl.exclamationToken, decl.type, decl.initializer);
|
|
697
|
-
}
|
|
698
|
-
}
|
|
699
|
-
return decl;
|
|
700
|
-
});
|
|
701
|
-
const newDeclList = factory.updateVariableDeclarationList(node.declarationList, newDeclarations);
|
|
702
|
-
return factory.updateVariableStatement(node, node.modifiers, newDeclList);
|
|
703
|
-
}
|
|
704
|
-
else if (ts.isFunctionDeclaration(node)) {
|
|
705
|
-
if (node.name && ts.isIdentifier(node.name)) {
|
|
706
|
-
const base = node.name.text;
|
|
707
|
-
// biome-ignore lint/style/noNonNullAssertion : namesMap.has(base) before that get just only size
|
|
708
|
-
if (namesMap.has(base) && namesMap.get(base).size > 1) {
|
|
709
|
-
const newName = dupName.getName(base);
|
|
710
|
-
callNameMap.push({ base, file: depsTree.file, newName });
|
|
711
|
-
return factory.updateFunctionDeclaration(node, node.modifiers, node.asteriskToken, factory.createIdentifier(newName), node.typeParameters, node.parameters, node.type, node.body);
|
|
712
|
-
}
|
|
713
|
-
}
|
|
714
|
-
}
|
|
715
|
-
else if (ts.isClassDeclaration(node)) {
|
|
716
|
-
if (node.name && ts.isIdentifier(node.name)) {
|
|
717
|
-
const base = node.name.text;
|
|
718
|
-
// biome-ignore lint/style/noNonNullAssertion : namesMap.has(base) before that get just only size
|
|
719
|
-
if (namesMap.has(base) && namesMap.get(base).size > 1) {
|
|
720
|
-
const newName = dupName.getName(base);
|
|
721
|
-
callNameMap.push({ base, file: depsTree.file, newName });
|
|
722
|
-
return factory.updateClassDeclaration(node, node.modifiers, factory.createIdentifier(newName), node.typeParameters, node.heritageClauses, node.members);
|
|
723
|
-
}
|
|
724
|
-
}
|
|
725
|
-
}
|
|
726
|
-
/* ----------------------Returns for visitor function------------------------------- */
|
|
727
|
-
return ts.visitEachChild(node, visit, context);
|
|
728
|
-
};
|
|
729
|
-
return visit;
|
|
730
|
-
};
|
|
731
|
-
//src/lib/bundle/visitors/removeExports.ts
|
|
732
|
-
/**
|
|
733
|
-
* A BundleVisitor that removes all exports from the given source file.
|
|
734
|
-
* It does so by stripping "export" modifiers from function, class, interface, type alias, enum, and variable declarations,
|
|
735
|
-
* and by removing "export { foo }" and "export default" declarations entirely.
|
|
736
|
-
*/
|
|
737
|
-
const removeExportsVisitor = (context) => {
|
|
738
|
-
const { factory } = context;
|
|
739
|
-
const visit = (node) => {
|
|
740
|
-
// --- Case 1: Strip "export" modifiers ---
|
|
741
|
-
const inside_nameSpace = utilities.isInsideNamespace(node);
|
|
742
|
-
if (!inside_nameSpace) {
|
|
743
|
-
if (ts.isFunctionDeclaration(node) ||
|
|
744
|
-
ts.isClassDeclaration(node) ||
|
|
745
|
-
ts.isInterfaceDeclaration(node) ||
|
|
746
|
-
ts.isTypeAliasDeclaration(node) ||
|
|
747
|
-
ts.isEnumDeclaration(node) ||
|
|
748
|
-
ts.isVariableStatement(node)) {
|
|
749
|
-
const modifiers = node.modifiers?.filter((m) => m.kind !== ts.SyntaxKind.ExportKeyword &&
|
|
750
|
-
m.kind !== ts.SyntaxKind.DefaultKeyword);
|
|
751
|
-
if (modifiers?.length !== node.modifiers?.length) {
|
|
752
|
-
// If the node has an export modifier, remove it.
|
|
753
|
-
// If the node is a function, class, interface, type alias, enum or variable declaration,
|
|
754
|
-
// update the declaration by removing the export modifier.
|
|
755
|
-
if (ts.isFunctionDeclaration(node)) {
|
|
756
|
-
return factory.updateFunctionDeclaration(node, modifiers, node.asteriskToken, node.name, node.typeParameters, node.parameters, node.type, node.body);
|
|
757
|
-
} // function
|
|
758
|
-
if (ts.isClassDeclaration(node)) {
|
|
759
|
-
return factory.updateClassDeclaration(node, modifiers, node.name, node.typeParameters, node.heritageClauses, node.members);
|
|
760
|
-
} // class
|
|
761
|
-
if (ts.isInterfaceDeclaration(node)) {
|
|
762
|
-
return factory.updateInterfaceDeclaration(node, modifiers, node.name, node.typeParameters, node.heritageClauses, node.members);
|
|
763
|
-
} // interface
|
|
764
|
-
if (ts.isTypeAliasDeclaration(node)) {
|
|
765
|
-
return factory.updateTypeAliasDeclaration(node, modifiers, node.name, node.typeParameters, node.type);
|
|
766
|
-
} // types
|
|
767
|
-
if (ts.isEnumDeclaration(node)) {
|
|
768
|
-
return factory.updateEnumDeclaration(node, modifiers, node.name, node.members);
|
|
769
|
-
} //enum
|
|
770
|
-
if (ts.isVariableStatement(node)) {
|
|
771
|
-
return factory.updateVariableStatement(node, modifiers, node.declarationList);
|
|
772
|
-
} // vars
|
|
773
|
-
} //--
|
|
774
|
-
} // --- Case 1
|
|
775
|
-
}
|
|
776
|
-
// --- Case 2: Remove "export { foo }" entirely ---
|
|
777
|
-
if (ts.isExportDeclaration(node)) {
|
|
778
|
-
// If the node is an export declaration, remove it.
|
|
779
|
-
return factory.createEmptyStatement();
|
|
780
|
-
}
|
|
781
|
-
// --- Case 3: Handle "export default ..." ---
|
|
782
|
-
if (ts.isExportAssignment(node)) {
|
|
783
|
-
const expr = node.expression;
|
|
784
|
-
// export default Foo; -> remove line
|
|
785
|
-
if (ts.isIdentifier(expr)) {
|
|
786
|
-
return factory.createEmptyStatement();
|
|
787
|
-
}
|
|
788
|
-
}
|
|
789
|
-
// --------- Visitor Return ------------------//
|
|
790
|
-
return ts.visitEachChild(node, visit, context);
|
|
791
|
-
};
|
|
792
|
-
return visit;
|
|
793
|
-
};
|
|
794
|
-
//src/lib/bundle/visitors/removeImports.ts
|
|
795
|
-
let properties = [];
|
|
796
|
-
const typeObj = {};
|
|
797
|
-
const typesNames = [];
|
|
798
|
-
function findProperty(node) {
|
|
799
|
-
const properties = [];
|
|
800
|
-
if (ts.isPropertyAccessExpression(node) && ts.isIdentifier(node.expression)) {
|
|
801
|
-
properties.push(node.expression.text);
|
|
802
|
-
}
|
|
803
|
-
node.forEachChild((n) => findProperty(n));
|
|
804
|
-
return properties;
|
|
805
|
-
}
|
|
806
|
-
/**
|
|
807
|
-
* A BundleVisitor that removes import declarations and import equals declarations from a TypeScript program.
|
|
808
|
-
* The visitor collects the names of type-only import-equals and emits a named/default type import if the type-only import-equals is not a namespace-type alias.
|
|
809
|
-
* The visitor also collects the names of type-only imports of namespace-type aliases and emits a namespace type import if the type-only import-equals is not a namespace-type alias.
|
|
810
|
-
*/
|
|
811
|
-
const removeImportsVisitor = (context, depsTree, sourceFile, removedStatements) => {
|
|
812
|
-
// Pre-scan: collect names of type-only import-equals (these are namespace-type aliases)
|
|
813
|
-
// import type NameSpace = require("foo")
|
|
814
|
-
const typeOnlyImportEquals = new Set();
|
|
815
|
-
for (const stmt of sourceFile.statements) {
|
|
816
|
-
if (ts.isImportEqualsDeclaration(stmt) && stmt.isTypeOnly) {
|
|
817
|
-
const moduleReference = stmt.moduleReference;
|
|
818
|
-
if (ts.isExternalModuleReference(moduleReference) &&
|
|
819
|
-
ts.isStringLiteral(moduleReference.expression)) {
|
|
820
|
-
typeOnlyImportEquals.add(stmt.name.text);
|
|
821
|
-
}
|
|
822
|
-
}
|
|
823
|
-
}
|
|
824
|
-
const { factory } = context;
|
|
825
|
-
const visit = (node) => {
|
|
826
|
-
properties = [...properties, ...findProperty(node)];
|
|
827
|
-
const obj = {
|
|
828
|
-
isNamespace: false,
|
|
829
|
-
isTypeOnly: false,
|
|
830
|
-
isTypeNamespace: false,
|
|
831
|
-
source: "",
|
|
832
|
-
importedString: undefined,
|
|
833
|
-
importedObject: undefined,
|
|
834
|
-
};
|
|
835
|
-
// --- Case: TypeReference with QualifiedName (collect type usage)
|
|
836
|
-
if (ts.isTypeReferenceNode(node) &&
|
|
837
|
-
ts.isQualifiedName(node.typeName) &&
|
|
838
|
-
ts.isIdentifier(node.typeName.left) &&
|
|
839
|
-
ts.isIdentifier(node.typeName.right)) {
|
|
840
|
-
const left = node.typeName.left.text;
|
|
841
|
-
const right = node.typeName.right.text;
|
|
842
|
-
typesNames.push(left);
|
|
843
|
-
if (left in typeObj) {
|
|
844
|
-
typeObj[left]?.push(right);
|
|
845
|
-
}
|
|
846
|
-
else {
|
|
847
|
-
typeObj[left] = [right];
|
|
848
|
-
}
|
|
849
|
-
// If this qualified name refers to a type-only import-equals alias, DO NOT rewrite.
|
|
850
|
-
// Rewriting (Foo.Bar -> Bar) was intended to support converting to named imports,
|
|
851
|
-
// but for type-only namespace imports we will emit `import type * as Foo from "..."`.
|
|
852
|
-
if (utilities.checkModuleType(sourceFile, depsTree.file).isCommonJs) {
|
|
853
|
-
if (left !== "ts" && !typeOnlyImportEquals.has(left)) {
|
|
854
|
-
return factory.updateTypeReferenceNode(node, factory.createIdentifier(right), undefined);
|
|
855
|
-
}
|
|
856
|
-
}
|
|
857
|
-
}
|
|
858
|
-
// ------------------------
|
|
859
|
-
if (ts.isImportDeclaration(node)) {
|
|
860
|
-
// --- Case 1: Import declarations
|
|
861
|
-
const text = node.getText(sourceFile);
|
|
862
|
-
removedStatements.push(text);
|
|
863
|
-
return factory.createEmptyStatement();
|
|
864
|
-
}
|
|
865
|
-
//--- Case 2: Import equals declarations
|
|
866
|
-
if (ts.isImportEqualsDeclaration(node)) {
|
|
867
|
-
const name = node.name.text;
|
|
868
|
-
const moduleReference = node.moduleReference;
|
|
869
|
-
if (node.isTypeOnly) {
|
|
870
|
-
obj.isTypeOnly = true;
|
|
871
|
-
}
|
|
872
|
-
obj.importedString = name;
|
|
873
|
-
if (!obj.isTypeOnly) {
|
|
874
|
-
if (properties.includes(name)) {
|
|
875
|
-
obj.isNamespace = true;
|
|
876
|
-
}
|
|
877
|
-
}
|
|
878
|
-
if (ts.isExternalModuleReference(moduleReference) &&
|
|
879
|
-
ts.isStringLiteral(moduleReference.expression)) {
|
|
880
|
-
obj.source = moduleReference.expression.text;
|
|
881
|
-
}
|
|
882
|
-
let t;
|
|
883
|
-
if (obj.importedString && !obj.importedObject) {
|
|
884
|
-
if (obj.isTypeOnly) {
|
|
885
|
-
// If this import-equals was a type-only namespace alias, emit a namespace type import
|
|
886
|
-
if (typeOnlyImportEquals.has(obj.importedString)) {
|
|
887
|
-
t = `import type * as ${obj.importedString} from "${obj.source}";`;
|
|
888
|
-
}
|
|
889
|
-
else {
|
|
890
|
-
// otherwise try to emit a named/default type import (existing behavior)
|
|
891
|
-
if (typesNames.includes(obj.importedString)) {
|
|
892
|
-
t = `import type { ${typeObj[obj.importedString]?.join(",")} } from "${obj.source}";`;
|
|
893
|
-
}
|
|
894
|
-
else {
|
|
895
|
-
t = `import type ${obj.importedString} from "${obj.source}";`;
|
|
896
|
-
}
|
|
897
|
-
}
|
|
898
|
-
}
|
|
899
|
-
else {
|
|
900
|
-
if (obj.isNamespace && obj.source && obj.source !== "typescript") {
|
|
901
|
-
t = `import * as ${obj.importedString} from "${obj.source}";`;
|
|
902
|
-
}
|
|
903
|
-
else {
|
|
904
|
-
t = `import ${obj.importedString} from "${obj.source}";`;
|
|
905
|
-
}
|
|
906
|
-
}
|
|
907
|
-
}
|
|
908
|
-
if (!obj.importedString && obj.importedObject) {
|
|
909
|
-
t = `import { ${obj.importedObject.join(", ")} } from "${obj.source}";`;
|
|
910
|
-
}
|
|
911
|
-
// removed
|
|
912
|
-
if (t) {
|
|
913
|
-
removedStatements.push(t);
|
|
914
|
-
return factory.createEmptyStatement();
|
|
915
|
-
}
|
|
916
|
-
}
|
|
917
|
-
// --- Case 3: Require imports
|
|
918
|
-
if (ts.isVariableStatement(node)) {
|
|
919
|
-
const decls = node.declarationList.declarations;
|
|
920
|
-
if (decls.length === 1) {
|
|
921
|
-
const decl = decls[0];
|
|
922
|
-
if (decl.initializer &&
|
|
923
|
-
ts.isCallExpression(decl.initializer) &&
|
|
924
|
-
ts.isIdentifier(decl.initializer.expression) &&
|
|
925
|
-
decl.initializer.expression.escapedText === "require") {
|
|
926
|
-
// imported from
|
|
927
|
-
const arg = decl.initializer.arguments[0];
|
|
928
|
-
if (ts.isStringLiteral(arg)) {
|
|
929
|
-
obj.source = arg.text;
|
|
930
|
-
}
|
|
931
|
-
if (ts.isIdentifier(decl.name)) {
|
|
932
|
-
const _n = decl.name.text;
|
|
933
|
-
obj.importedString = _n;
|
|
934
|
-
if (properties.includes(_n)) {
|
|
935
|
-
obj.isNamespace = true;
|
|
936
|
-
}
|
|
937
|
-
}
|
|
938
|
-
else if (ts.isObjectBindingPattern(decl.name)) {
|
|
939
|
-
const _names = [];
|
|
940
|
-
for (const ele of decl.name.elements) {
|
|
941
|
-
if (ts.isIdentifier(ele.name)) {
|
|
942
|
-
_names.push(ele.name.text);
|
|
943
|
-
}
|
|
944
|
-
}
|
|
945
|
-
if (_names.length > 0) {
|
|
946
|
-
obj.importedObject = _names;
|
|
947
|
-
}
|
|
948
|
-
}
|
|
949
|
-
let tt;
|
|
950
|
-
if (obj.importedString && !obj.importedObject) {
|
|
951
|
-
if (obj.isNamespace) {
|
|
952
|
-
tt = `import * as ${obj.importedString} from "${obj.source}";`;
|
|
953
|
-
}
|
|
954
|
-
else {
|
|
955
|
-
tt = `import ${obj.importedString} from "${obj.source}";`;
|
|
956
|
-
}
|
|
957
|
-
}
|
|
958
|
-
if (!obj.importedString && obj.importedObject) {
|
|
959
|
-
tt = `import { ${obj.importedObject.join(", ")} } from "${obj.source}";`;
|
|
960
|
-
}
|
|
961
|
-
if (tt) {
|
|
962
|
-
removedStatements.push(tt);
|
|
963
|
-
return factory.createEmptyStatement();
|
|
964
|
-
}
|
|
965
|
-
}
|
|
966
|
-
}
|
|
967
|
-
}
|
|
968
|
-
// --------- Visitor Return ------------------//
|
|
969
|
-
return ts.visitEachChild(node, visit, context);
|
|
970
|
-
};
|
|
971
|
-
return visit;
|
|
972
|
-
};
|
|
973
|
-
//src/lib/bundle/index.ts
|
|
974
|
-
// ------------------------------------------------------------------------------------//
|
|
975
|
-
/**
|
|
976
|
-
* Bundles a TypeScript project into a single file.
|
|
977
|
-
* This function takes a {@link CollatedPoint} object as input and returns a {@link BundleResultPoint} object.
|
|
978
|
-
* The function applies the following steps:
|
|
979
|
-
* 1. Call dependency plugins.
|
|
980
|
-
* 2. Handle duplicates.
|
|
981
|
-
* 3. Handling anonymous imports and exports.
|
|
982
|
-
* 4. Remove Imports.
|
|
983
|
-
* 5. Remove Exports from dependencies only.
|
|
984
|
-
* 6. Handle imported statements.
|
|
985
|
-
* 7. Create final content.
|
|
986
|
-
* 8. Call pre-process plugins.
|
|
987
|
-
* 9. Returns.
|
|
988
|
-
* @param {CollatedPoint} point - A {@link CollatedPoint} object.
|
|
989
|
-
* @returns {Promise<BundleResultPoint>} - A promise resolves with a {@link BundleResultPoint} object.
|
|
990
|
-
*/
|
|
991
|
-
async function bundler(point) {
|
|
992
|
-
let depsFiles = point.depFiles;
|
|
993
|
-
const reName = point.rename;
|
|
994
|
-
const compilerOptions = point.tsOptions.default;
|
|
995
|
-
const plugins = point.plugins;
|
|
996
|
-
// construct maps
|
|
997
|
-
const namesMap = new Map();
|
|
998
|
-
const callNameMap = [];
|
|
999
|
-
const importNameMap = [];
|
|
1000
|
-
const exportNameMap = [];
|
|
1001
|
-
const exportDefaultExportNameMap = [];
|
|
1002
|
-
const exportDefaultImportNameMap = [];
|
|
1003
|
-
let removedStatements = [];
|
|
1004
|
-
const duplicate = async (reName) => {
|
|
1005
|
-
if (reName) {
|
|
1006
|
-
// order is important here
|
|
1007
|
-
const re_name = resolves([
|
|
1008
|
-
// collector
|
|
1009
|
-
[bundleCreator, duplicateCollectionVisitor, compilerOptions, namesMap],
|
|
1010
|
-
// update
|
|
1011
|
-
[
|
|
1012
|
-
bundleCreator,
|
|
1013
|
-
duplicateUpdateVisitor,
|
|
1014
|
-
compilerOptions,
|
|
1015
|
-
namesMap,
|
|
1016
|
-
callNameMap,
|
|
1017
|
-
],
|
|
1018
|
-
// call exp
|
|
1019
|
-
[
|
|
1020
|
-
bundleCreator,
|
|
1021
|
-
duplicateCallExpressionVisitor,
|
|
1022
|
-
compilerOptions,
|
|
1023
|
-
callNameMap,
|
|
1024
|
-
importNameMap,
|
|
1025
|
-
],
|
|
1026
|
-
// export exp
|
|
1027
|
-
[
|
|
1028
|
-
bundleCreator,
|
|
1029
|
-
duplicateExportExpressionVisitor,
|
|
1030
|
-
compilerOptions,
|
|
1031
|
-
importNameMap,
|
|
1032
|
-
exportNameMap,
|
|
1033
|
-
],
|
|
1034
|
-
// import exp
|
|
1035
|
-
[
|
|
1036
|
-
bundleCreator,
|
|
1037
|
-
duplicateImportExpressionVisitor,
|
|
1038
|
-
compilerOptions,
|
|
1039
|
-
exportNameMap,
|
|
1040
|
-
importNameMap,
|
|
1041
|
-
],
|
|
1042
|
-
// export exp again
|
|
1043
|
-
[
|
|
1044
|
-
bundleCreator,
|
|
1045
|
-
duplicateExportExpressionVisitor,
|
|
1046
|
-
compilerOptions,
|
|
1047
|
-
importNameMap,
|
|
1048
|
-
exportNameMap,
|
|
1049
|
-
],
|
|
1050
|
-
// export exp again
|
|
1051
|
-
[
|
|
1052
|
-
bundleCreator,
|
|
1053
|
-
duplicateExportExpressionVisitor,
|
|
1054
|
-
compilerOptions,
|
|
1055
|
-
importNameMap,
|
|
1056
|
-
exportNameMap,
|
|
1057
|
-
],
|
|
1058
|
-
]); // re_name
|
|
1059
|
-
const re_name_call = await re_name.concurrent();
|
|
1060
|
-
for (const call of re_name_call) {
|
|
1061
|
-
await utilities.wait(500);
|
|
1062
|
-
depsFiles = depsFiles.map(call);
|
|
1063
|
-
}
|
|
1064
|
-
}
|
|
1065
|
-
else {
|
|
1066
|
-
let _err = false;
|
|
1067
|
-
const un_rename = resolves([
|
|
1068
|
-
// collector
|
|
1069
|
-
[bundleCreator, duplicateCollectionVisitor, compilerOptions, namesMap],
|
|
1070
|
-
]);
|
|
1071
|
-
const un_rename_call = await un_rename.concurrent();
|
|
1072
|
-
depsFiles.map(un_rename_call[0]);
|
|
1073
|
-
await utilities.wait(1000);
|
|
1074
|
-
namesMap.forEach((files, name) => {
|
|
1075
|
-
if (files.size > 1) {
|
|
1076
|
-
_err = true;
|
|
1077
|
-
console.warn(`Name -> ${name} declared in multiple files :`);
|
|
1078
|
-
// biome-ignore lint/suspicious/useIterableCallbackReturn : just log warn
|
|
1079
|
-
files.forEach((f) => console.warn(` - ${f.file}`));
|
|
1080
|
-
}
|
|
1081
|
-
});
|
|
1082
|
-
await utilities.wait(1000);
|
|
1083
|
-
if (_err) {
|
|
1084
|
-
process.exit(1);
|
|
1085
|
-
}
|
|
1086
|
-
}
|
|
1087
|
-
};
|
|
1088
|
-
// 1. Call dependency plugins
|
|
1089
|
-
if (plugins.length) {
|
|
1090
|
-
for (let plugin of plugins) {
|
|
1091
|
-
plugin = typeof plugin === "function" ? plugin() : plugin;
|
|
1092
|
-
if (plugin.type === "dependency") {
|
|
1093
|
-
if (plugin.async) {
|
|
1094
|
-
depsFiles = await plugin.func(depsFiles);
|
|
1095
|
-
}
|
|
1096
|
-
else {
|
|
1097
|
-
depsFiles = plugin.func(depsFiles);
|
|
1098
|
-
}
|
|
1099
|
-
}
|
|
1100
|
-
}
|
|
1101
|
-
} //--
|
|
1102
|
-
await utilities.wait(1000);
|
|
1103
|
-
// 2. Handle duplicates
|
|
1104
|
-
await duplicate(reName);
|
|
1105
|
-
// 3. Handling anonymous imports and exports
|
|
1106
|
-
const anonymous = resolves([
|
|
1107
|
-
[
|
|
1108
|
-
bundleCreator,
|
|
1109
|
-
anonymousExportVisitor,
|
|
1110
|
-
compilerOptions,
|
|
1111
|
-
exportDefaultExportNameMap,
|
|
1112
|
-
],
|
|
1113
|
-
[
|
|
1114
|
-
bundleCreator,
|
|
1115
|
-
anonymousImportVisitor,
|
|
1116
|
-
compilerOptions,
|
|
1117
|
-
exportDefaultImportNameMap,
|
|
1118
|
-
exportDefaultImportNameMap,
|
|
1119
|
-
],
|
|
1120
|
-
[
|
|
1121
|
-
bundleCreator,
|
|
1122
|
-
anonymousCallExpressionVisitor,
|
|
1123
|
-
compilerOptions,
|
|
1124
|
-
exportDefaultImportNameMap,
|
|
1125
|
-
],
|
|
1126
|
-
]);
|
|
1127
|
-
const anonymousCall = await anonymous.concurrent();
|
|
1128
|
-
for (const call of anonymousCall) {
|
|
1129
|
-
depsFiles = depsFiles.map(call);
|
|
1130
|
-
}
|
|
1131
|
-
await utilities.wait(1000);
|
|
1132
|
-
// 4. Remove Imports
|
|
1133
|
-
const removeImports = resolves([
|
|
1134
|
-
[bundleCreator, removeImportsVisitor, compilerOptions, removedStatements],
|
|
1135
|
-
]);
|
|
1136
|
-
const removeImport = await removeImports.concurrent();
|
|
1137
|
-
depsFiles = depsFiles.map(removeImport[0]);
|
|
1138
|
-
await utilities.wait(500);
|
|
1139
|
-
// 5. Remove Exports from dependencies only
|
|
1140
|
-
const removeExports = resolves([
|
|
1141
|
-
[bundleCreator, removeExportsVisitor, compilerOptions],
|
|
1142
|
-
]);
|
|
1143
|
-
const removeExport = await removeExports.concurrent();
|
|
1144
|
-
// not remove exports from entry file
|
|
1145
|
-
const deps_files = depsFiles.slice(0, -1).map(removeExport[0]);
|
|
1146
|
-
const mainFile = depsFiles.slice(-1);
|
|
1147
|
-
// 6. Handle imported statements
|
|
1148
|
-
// filter removed statements , that not from local like `./` or `../`
|
|
1149
|
-
const regexp = /["']((?!\.\/|\.\.\/)[^"']+)["']/;
|
|
1150
|
-
removedStatements = removedStatements.filter((i) => regexp.test(i));
|
|
1151
|
-
removedStatements = mergeImportsStatement(removedStatements);
|
|
1152
|
-
// 7. Create final content
|
|
1153
|
-
// make sure all imports are at the top of file
|
|
1154
|
-
const importStatements = removedStatements.join("\n").trim();
|
|
1155
|
-
const depFilesContent = deps_files
|
|
1156
|
-
.map((i) => {
|
|
1157
|
-
const file = `//${path.relative(process.cwd(), i.file)}`;
|
|
1158
|
-
return `${file}\n${i.content}`;
|
|
1159
|
-
})
|
|
1160
|
-
.join("\n")
|
|
1161
|
-
.trim();
|
|
1162
|
-
const mainFileContent = mainFile
|
|
1163
|
-
.map((i) => {
|
|
1164
|
-
const file = `//${path.relative(process.cwd(), i.file)}`;
|
|
1165
|
-
return `${file}\n${i.content}`;
|
|
1166
|
-
})
|
|
1167
|
-
.join("\n")
|
|
1168
|
-
.trim();
|
|
1169
|
-
await utilities.wait(1000);
|
|
1170
|
-
// text join order is important here
|
|
1171
|
-
let content = `${importStatements}\n${depFilesContent}\n${mainFileContent}`;
|
|
1172
|
-
// 8. Call pre-process plugins
|
|
1173
|
-
if (plugins.length) {
|
|
1174
|
-
for (let plugin of plugins) {
|
|
1175
|
-
plugin = typeof plugin === "function" ? plugin() : plugin;
|
|
1176
|
-
if (plugin.type === "pre-process") {
|
|
1177
|
-
if (plugin.async) {
|
|
1178
|
-
content = await plugin.func(content);
|
|
1179
|
-
}
|
|
1180
|
-
else {
|
|
1181
|
-
content = plugin.func(content);
|
|
1182
|
-
}
|
|
1183
|
-
}
|
|
1184
|
-
}
|
|
1185
|
-
} //--
|
|
1186
|
-
// 9. Returns
|
|
1187
|
-
return { bundledContent: content, ...point };
|
|
1188
|
-
}
|
|
1189
|
-
async function bundle(object) {
|
|
1190
|
-
const points = [];
|
|
1191
|
-
for (const point of object.points) {
|
|
1192
|
-
const _point = await bundler(point);
|
|
1193
|
-
points.push(_point);
|
|
1194
|
-
}
|
|
1195
|
-
return {
|
|
1196
|
-
points,
|
|
1197
|
-
allowUpdatePackageJson: object.allowUpdatePackageJson,
|
|
1198
|
-
};
|
|
1199
|
-
}
|
|
1200
|
-
//src/lib/compile/host.ts
|
|
1201
|
-
/**
|
|
1202
|
-
* Creates a ts.CompilerHost that can be used with the typescript compiler.
|
|
1203
|
-
* This host is designed to be used with in-memory compilation and will
|
|
1204
|
-
* return the source file for the given fileName and will write all output
|
|
1205
|
-
* files to the createdFiles object.
|
|
1206
|
-
* @param {string} sourceCode - the source code to compile
|
|
1207
|
-
* @param {string} fileName - the name of the file to compile
|
|
1208
|
-
* @returns {{createdFiles: Record<string, string>, host: ts.CompilerHost}}
|
|
1209
|
-
*/
|
|
1210
|
-
function createHost(sourceCode, fileName) {
|
|
1211
|
-
const createdFiles = {};
|
|
1212
|
-
const host = {
|
|
1213
|
-
getSourceFile: (file, languageVersion) => {
|
|
1214
|
-
if (file === fileName) {
|
|
1215
|
-
return ts.createSourceFile(file, sourceCode, languageVersion);
|
|
1216
|
-
}
|
|
1217
|
-
return undefined;
|
|
1218
|
-
},
|
|
1219
|
-
writeFile: (fileName, contents) => {
|
|
1220
|
-
createdFiles[fileName] = contents;
|
|
1221
|
-
},
|
|
1222
|
-
getDefaultLibFileName: (options) => ts.getDefaultLibFilePath(options),
|
|
1223
|
-
getCurrentDirectory: () => "",
|
|
1224
|
-
getDirectories: () => [],
|
|
1225
|
-
fileExists: (file) => file === fileName,
|
|
1226
|
-
readFile: (file) => (file === fileName ? sourceCode : undefined),
|
|
1227
|
-
getCanonicalFileName: (file) => file,
|
|
1228
|
-
useCaseSensitiveFileNames: () => true,
|
|
1229
|
-
getNewLine: () => "\n",
|
|
1230
|
-
};
|
|
1231
|
-
return { createdFiles, host };
|
|
1232
|
-
}
|
|
1233
|
-
//src/lib/compile/package.ts
|
|
1234
|
-
const isCjs = (files) => files.commonjs && files.commonjsTypes;
|
|
1235
|
-
const isEsm = (files) => files.esm && files.esmTypes;
|
|
1236
|
-
/**
|
|
1237
|
-
* Builds a package exports mapping for the given output files and export path.
|
|
1238
|
-
*
|
|
1239
|
-
* Produces the appropriate export shape based on whether CommonJS and/or ESM
|
|
1240
|
-
* artifacts are present, including their default entry points and type
|
|
1241
|
-
* definitions. If neither format is available, returns an empty object.
|
|
1242
|
-
*
|
|
1243
|
-
* @param files - The build output file paths for CommonJS/ESM and their types.
|
|
1244
|
-
* @param exportPath - The subpath export key (e.g. "." or "./feature").
|
|
1245
|
-
* @returns A {@link Exports} object describing the package exports map.
|
|
1246
|
-
*/
|
|
1247
|
-
function getExports(files, exportPath) {
|
|
1248
|
-
return isCjs(files) && isEsm(files)
|
|
1249
|
-
? {
|
|
1250
|
-
[exportPath]: {
|
|
1251
|
-
import: {
|
|
1252
|
-
types: `./${path.relative(process.cwd(), files.esmTypes)}`,
|
|
1253
|
-
default: `./${path.relative(process.cwd(), files.esm)}`,
|
|
1254
|
-
},
|
|
1255
|
-
require: {
|
|
1256
|
-
types: `./${path.relative(process.cwd(), files.commonjsTypes)}`,
|
|
1257
|
-
default: `./${path.relative(process.cwd(), files.commonjs)}`,
|
|
1258
|
-
},
|
|
1259
|
-
},
|
|
1260
|
-
}
|
|
1261
|
-
: isCjs(files) && !isEsm(files)
|
|
1262
|
-
? {
|
|
1263
|
-
[exportPath]: {
|
|
1264
|
-
require: {
|
|
1265
|
-
types: `./${path.relative(process.cwd(), files.commonjsTypes)}`,
|
|
1266
|
-
default: `./${path.relative(process.cwd(), files.commonjs)}`,
|
|
1267
|
-
},
|
|
1268
|
-
},
|
|
1269
|
-
}
|
|
1270
|
-
: !isCjs(files) && isEsm(files)
|
|
1271
|
-
? {
|
|
1272
|
-
[exportPath]: {
|
|
1273
|
-
import: {
|
|
1274
|
-
types: `./${path.relative(process.cwd(), files.esmTypes)}`,
|
|
1275
|
-
default: `./${path.relative(process.cwd(), files.esm)}`,
|
|
1276
|
-
},
|
|
1277
|
-
},
|
|
1278
|
-
}
|
|
1279
|
-
: {};
|
|
1280
|
-
}
|
|
1281
|
-
/**
|
|
1282
|
-
* Writes an updated `package.json` based on output files and export path.
|
|
1283
|
-
*
|
|
1284
|
-
* Determines module type (ESM/CommonJS), adjusts `main`, `module`, `types`,
|
|
1285
|
-
* and `exports` fields, and preserves other existing fields from the
|
|
1286
|
-
* current `package.json`.
|
|
1287
|
-
*
|
|
1288
|
-
* @param files - The generated output files used to populate entry points.
|
|
1289
|
-
* @param exportPath - The export path for subpath exports; "." denotes main export.
|
|
1290
|
-
*/
|
|
1291
|
-
async function writePackage(files, exportPath) {
|
|
1292
|
-
let isMain = true;
|
|
1293
|
-
if (exportPath !== ".") {
|
|
1294
|
-
isMain = false;
|
|
1295
|
-
}
|
|
1296
|
-
const pkgFile = ts.sys.resolvePath("package.json");
|
|
1297
|
-
const _pkgtext = fs.readFileSync(pkgFile, "utf8");
|
|
1298
|
-
const pkgtext = JSON.parse(_pkgtext);
|
|
1299
|
-
let { name, version, description, main, module, type, types, exports, ...rest } = pkgtext;
|
|
1300
|
-
await utilities.wait(500);
|
|
1301
|
-
type = "module";
|
|
1302
|
-
let _main = {};
|
|
1303
|
-
let _module = {};
|
|
1304
|
-
let _types = {};
|
|
1305
|
-
let _exports = {};
|
|
1306
|
-
if (isMain) {
|
|
1307
|
-
_main = files.main
|
|
1308
|
-
? { main: path.relative(process.cwd(), files.main) }
|
|
1309
|
-
: {};
|
|
1310
|
-
_module = files.module
|
|
1311
|
-
? { module: path.relative(process.cwd(), files.module) }
|
|
1312
|
-
: {};
|
|
1313
|
-
_types = files.types
|
|
1314
|
-
? { types: path.relative(process.cwd(), files.types) }
|
|
1315
|
-
: {};
|
|
1316
|
-
_exports = { exports: { ...getExports(files, exportPath) } };
|
|
1317
|
-
}
|
|
1318
|
-
else {
|
|
1319
|
-
_main = main ? { main: main } : {};
|
|
1320
|
-
_module = module ? { module: module } : {};
|
|
1321
|
-
_types = types ? { types: types } : {};
|
|
1322
|
-
const normalizedExports = exports && typeof exports === "object" && !Array.isArray(exports)
|
|
1323
|
-
? { ...exports }
|
|
1324
|
-
: {};
|
|
1325
|
-
_exports = {
|
|
1326
|
-
exports: { ...normalizedExports, ...getExports(files, exportPath) },
|
|
1327
|
-
};
|
|
1328
|
-
}
|
|
1329
|
-
await utilities.wait(1000);
|
|
1330
|
-
const pkgJson = {
|
|
1331
|
-
name,
|
|
1332
|
-
version,
|
|
1333
|
-
description,
|
|
1334
|
-
type,
|
|
1335
|
-
..._main,
|
|
1336
|
-
..._types,
|
|
1337
|
-
..._module,
|
|
1338
|
-
..._exports,
|
|
1339
|
-
...rest,
|
|
1340
|
-
};
|
|
1341
|
-
utilities.writeCompileFile(pkgFile, JSON.stringify(pkgJson, null, 2));
|
|
1342
|
-
}
|
|
1343
|
-
//src/lib/compile/index.ts
|
|
1344
|
-
function splitCamelCase(str) {
|
|
1345
|
-
const splitString = str
|
|
1346
|
-
.replace(/([a-z])([A-Z])/g, "$1 $2")
|
|
1347
|
-
.replace(/(_|-|\/)([a-z] || [A-Z])/g, " ")
|
|
1348
|
-
.replace(/([A-Z])/g, (match) => match.toLowerCase())
|
|
1349
|
-
.replace(/^([a-z])/, (match) => match.toUpperCase());
|
|
1350
|
-
return splitString;
|
|
1351
|
-
}
|
|
1352
|
-
class Compiler {
|
|
1353
|
-
constructor(object) {
|
|
1354
|
-
this.object = object;
|
|
1355
|
-
this.files = {
|
|
1356
|
-
commonjs: undefined,
|
|
1357
|
-
commonjsTypes: undefined,
|
|
1358
|
-
esm: undefined,
|
|
1359
|
-
esmTypes: undefined,
|
|
1360
|
-
main: undefined,
|
|
1361
|
-
module: undefined,
|
|
1362
|
-
types: undefined,
|
|
1363
|
-
};
|
|
1364
|
-
}
|
|
1365
|
-
_isUpdate() {
|
|
1366
|
-
return this.object.allowUpdatePackageJson;
|
|
1367
|
-
}
|
|
1368
|
-
async _commonjs(point) {
|
|
1369
|
-
const isMain = point.exportPath === ".";
|
|
1370
|
-
const _name = isMain ? "Main" : splitCamelCase(point.exportPath.slice(2));
|
|
1371
|
-
console.time(tcolor.cyan(`Compiled commonjs for ${_name} export path`));
|
|
1372
|
-
// init
|
|
1373
|
-
const fileName = point.fileName;
|
|
1374
|
-
const sourceCode = point.bundledContent;
|
|
1375
|
-
const format = point.format;
|
|
1376
|
-
const plugins = point.plugins;
|
|
1377
|
-
const compilerOptions = point.tsOptions.cjs;
|
|
1378
|
-
// create host
|
|
1379
|
-
const _host = createHost(sourceCode, fileName);
|
|
1380
|
-
const createdFiles = _host.createdFiles;
|
|
1381
|
-
const host = _host.host;
|
|
1382
|
-
const program = ts.createProgram([fileName], compilerOptions, host);
|
|
1383
|
-
program.emit();
|
|
1384
|
-
Object.entries(createdFiles).map(async ([outName, content]) => {
|
|
1385
|
-
// ------------------------------------
|
|
1386
|
-
if (plugins.length) {
|
|
1387
|
-
for (let plugin of plugins) {
|
|
1388
|
-
plugin = typeof plugin === "function" ? plugin() : plugin;
|
|
1389
|
-
if (plugin.type === "post-process") {
|
|
1390
|
-
if (plugin.async) {
|
|
1391
|
-
content = await plugin.func(content, outName);
|
|
1392
|
-
}
|
|
1393
|
-
else {
|
|
1394
|
-
content = plugin.func(content, outName);
|
|
1395
|
-
}
|
|
1396
|
-
}
|
|
1397
|
-
}
|
|
1398
|
-
}
|
|
1399
|
-
if (this._isUpdate()) {
|
|
1400
|
-
if (outName.match(/.js/g)) {
|
|
1401
|
-
this.files.commonjs = outName.replace(/.js/g, ".cjs");
|
|
1402
|
-
}
|
|
1403
|
-
if (outName.match(/.d.ts/g)) {
|
|
1404
|
-
this.files.commonjsTypes = outName.replace(/.d.ts/g, ".d.cts");
|
|
1405
|
-
}
|
|
1406
|
-
if (isMain && (format === "both" || format === "commonjs")) {
|
|
1407
|
-
if (this.files.commonjs)
|
|
1408
|
-
this.files.main = this.files.commonjs;
|
|
1409
|
-
if (this.files.commonjsTypes)
|
|
1410
|
-
this.files.types = this.files.commonjsTypes;
|
|
1411
|
-
}
|
|
1412
|
-
}
|
|
1413
|
-
outName = outName.replace(/.js/g, ".cjs");
|
|
1414
|
-
outName = outName.replace(/.map.js/g, ".map.cjs");
|
|
1415
|
-
outName = outName.replace(/.d.ts/g, ".d.cts");
|
|
1416
|
-
await utilities.wait(500);
|
|
1417
|
-
if (format === "commonjs") {
|
|
1418
|
-
await utilities.clearFolder(path.dirname(outName));
|
|
1419
|
-
}
|
|
1420
|
-
await utilities.writeCompileFile(outName, content);
|
|
1421
|
-
});
|
|
1422
|
-
console.timeEnd(tcolor.cyan(`Compiled commonjs for ${_name} export path`));
|
|
1423
|
-
}
|
|
1424
|
-
async _esm(point) {
|
|
1425
|
-
const isMain = point.exportPath === ".";
|
|
1426
|
-
const _name = isMain ? "Main" : splitCamelCase(point.exportPath.slice(2));
|
|
1427
|
-
console.time(tcolor.cyan(`Compiled esm for ${_name} export path`));
|
|
1428
|
-
// init
|
|
1429
|
-
const fileName = point.fileName;
|
|
1430
|
-
const sourceCode = point.bundledContent;
|
|
1431
|
-
const format = point.format;
|
|
1432
|
-
const plugins = point.plugins;
|
|
1433
|
-
const compilerOptions = point.tsOptions.esm;
|
|
1434
|
-
// create host
|
|
1435
|
-
const _host = createHost(sourceCode, fileName);
|
|
1436
|
-
const createdFiles = _host.createdFiles;
|
|
1437
|
-
const host = _host.host;
|
|
1438
|
-
const program = ts.createProgram([fileName], compilerOptions, host);
|
|
1439
|
-
program.emit();
|
|
1440
|
-
Object.entries(createdFiles).map(async ([outName, content]) => {
|
|
1441
|
-
if (plugins.length) {
|
|
1442
|
-
for (let plugin of plugins) {
|
|
1443
|
-
plugin = typeof plugin === "function" ? plugin() : plugin;
|
|
1444
|
-
if (plugin.type === "post-process") {
|
|
1445
|
-
if (plugin.async) {
|
|
1446
|
-
content = await plugin.func(content, outName);
|
|
1447
|
-
}
|
|
1448
|
-
else {
|
|
1449
|
-
content = plugin.func(content, outName);
|
|
1450
|
-
}
|
|
1451
|
-
}
|
|
1452
|
-
}
|
|
1453
|
-
}
|
|
1454
|
-
// ------------------------------------------
|
|
1455
|
-
if (this._isUpdate()) {
|
|
1456
|
-
if (outName.match(/.js/g)) {
|
|
1457
|
-
this.files.esm = outName.replace(/.js/g, ".mjs");
|
|
1458
|
-
}
|
|
1459
|
-
if (outName.match(/.d.ts/g)) {
|
|
1460
|
-
this.files.esmTypes = outName.replace(/.d.ts/g, ".d.mts");
|
|
1461
|
-
}
|
|
1462
|
-
if (isMain && format === "both" && this.files.esm) {
|
|
1463
|
-
this.files.module = this.files.esm;
|
|
1464
|
-
}
|
|
1465
|
-
}
|
|
1466
|
-
outName = outName.replace(/.js/g, ".mjs");
|
|
1467
|
-
outName = outName.replace(/.map.js/g, ".map.mjs");
|
|
1468
|
-
outName = outName.replace(/.d.ts/g, ".d.mts");
|
|
1469
|
-
await utilities.wait(500);
|
|
1470
|
-
if (format !== "commonjs") {
|
|
1471
|
-
await utilities.clearFolder(path.dirname(outName));
|
|
1472
|
-
}
|
|
1473
|
-
await utilities.writeCompileFile(outName, content);
|
|
1474
|
-
});
|
|
1475
|
-
console.timeEnd(tcolor.cyan(`Compiled esm for ${_name} export path`));
|
|
1476
|
-
}
|
|
1477
|
-
/**
|
|
1478
|
-
* Compile bundled code for each entry point.
|
|
1479
|
-
* This function will iterate through each entry point and compile code according to the format specified.
|
|
1480
|
-
* If the format is "commonjs", it will compile the code into commonjs format.
|
|
1481
|
-
* If the format is "esm", it will compile the code into esm format.
|
|
1482
|
-
* If the format is "both", it will compile the code into both commonjs and esm formats.
|
|
1483
|
-
* If the allowUpdatePackageJson flag is set to true, it will update the package.json according to the compiled file paths.
|
|
1484
|
-
*/
|
|
1485
|
-
async compile() {
|
|
1486
|
-
for (const point of this.object.points) {
|
|
1487
|
-
await utilities.wait(500);
|
|
1488
|
-
switch (point.format) {
|
|
1489
|
-
case "commonjs":
|
|
1490
|
-
await this._commonjs(point);
|
|
1491
|
-
if (this._isUpdate()) {
|
|
1492
|
-
await writePackage(this.files, point.exportPath);
|
|
1493
|
-
}
|
|
1494
|
-
break;
|
|
1495
|
-
case "esm":
|
|
1496
|
-
await this._esm(point);
|
|
1497
|
-
if (this._isUpdate()) {
|
|
1498
|
-
await writePackage(this.files, point.exportPath);
|
|
1499
|
-
}
|
|
1500
|
-
break;
|
|
1501
|
-
case "both":
|
|
1502
|
-
await this._esm(point);
|
|
1503
|
-
await utilities.wait(1000);
|
|
1504
|
-
await this._commonjs(point);
|
|
1505
|
-
if (this._isUpdate()) {
|
|
1506
|
-
await writePackage(this.files, point.exportPath);
|
|
1507
|
-
}
|
|
1508
|
-
break;
|
|
1509
|
-
}
|
|
1510
|
-
await utilities.wait(500);
|
|
1511
|
-
}
|
|
1512
|
-
}
|
|
1513
|
-
}
|
|
1514
|
-
//src/lib/init/checks.ts
|
|
1515
|
-
var checks;
|
|
1516
|
-
(function (checks) {
|
|
1517
|
-
/**
|
|
1518
|
-
* Checks the given dependencies for type errors. If any type errors are found,
|
|
1519
|
-
* an error message is printed to the console and the process exits with a code of 1.
|
|
1520
|
-
* @param dep The dependencies to check for type errors
|
|
1521
|
-
* @param compilerOptions The compiler options to use when checking for type errors
|
|
1522
|
-
* @returns true if no type errors are found, false otherwise
|
|
1523
|
-
*/
|
|
1524
|
-
function typesCheck(dep, compilerOptions) {
|
|
1525
|
-
if (!compilerOptions.noCheck) {
|
|
1526
|
-
const filePaths = dep.map((i) => i.file);
|
|
1527
|
-
let _err = false;
|
|
1528
|
-
// Create program
|
|
1529
|
-
const program = ts.createProgram(filePaths, compilerOptions);
|
|
1530
|
-
// Check each file individually for immediate feedback
|
|
1531
|
-
for (const filePath of filePaths) {
|
|
1532
|
-
const sourceFile = program.getSourceFile(filePath);
|
|
1533
|
-
if (!sourceFile) {
|
|
1534
|
-
console.error(tcolor.magenta(`File not found: ${filePath}`));
|
|
1535
|
-
ts.sys.exit(1);
|
|
1536
|
-
}
|
|
1537
|
-
const diagnostics = [
|
|
1538
|
-
...program.getSyntacticDiagnostics(sourceFile),
|
|
1539
|
-
...program.getSemanticDiagnostics(sourceFile),
|
|
1540
|
-
...program.getDeclarationDiagnostics(sourceFile),
|
|
1541
|
-
];
|
|
1542
|
-
if (diagnostics.length > 0) {
|
|
1543
|
-
const formatHost = {
|
|
1544
|
-
getCurrentDirectory: () => process.cwd(),
|
|
1545
|
-
getCanonicalFileName: (fileName) => fileName,
|
|
1546
|
-
getNewLine: () => ts.sys.newLine,
|
|
1547
|
-
};
|
|
1548
|
-
console.error(ts.formatDiagnosticsWithColorAndContext(diagnostics, formatHost));
|
|
1549
|
-
_err = true;
|
|
1550
|
-
}
|
|
1551
|
-
}
|
|
1552
|
-
if (_err) {
|
|
1553
|
-
ts.sys.exit(1);
|
|
1554
|
-
}
|
|
1555
|
-
else {
|
|
1556
|
-
return true;
|
|
1557
|
-
}
|
|
1558
|
-
}
|
|
1559
|
-
}
|
|
1560
|
-
/**
|
|
1561
|
-
* Check the module type of the given dependencies.
|
|
1562
|
-
* @param _dep The dependencies to check for module type
|
|
1563
|
-
* @returns true if all dependencies are ESM, false otherwise
|
|
1564
|
-
*/
|
|
1565
|
-
function moduleType(_dep) {
|
|
1566
|
-
let _esmCount = 0;
|
|
1567
|
-
let cjsCount = 0;
|
|
1568
|
-
let unknownCount = 0;
|
|
1569
|
-
for (const dep of _dep) {
|
|
1570
|
-
try {
|
|
1571
|
-
// Create a TypeScript source file
|
|
1572
|
-
const sourceFile = ts.createSourceFile(dep.file, dep.content, ts.ScriptTarget.Latest, true);
|
|
1573
|
-
let hasESMImports = false;
|
|
1574
|
-
let hasCommonJS = false;
|
|
1575
|
-
// Walk through the AST to detect module syntax
|
|
1576
|
-
function walk(node) {
|
|
1577
|
-
// Check for ESM import/export syntax
|
|
1578
|
-
if (ts.isImportDeclaration(node) ||
|
|
1579
|
-
ts.isImportEqualsDeclaration(node) ||
|
|
1580
|
-
ts.isExportDeclaration(node) ||
|
|
1581
|
-
ts.isExportSpecifier(node) ||
|
|
1582
|
-
ts.isExportAssignment(node)) {
|
|
1583
|
-
hasESMImports = true;
|
|
1584
|
-
}
|
|
1585
|
-
// Check for export modifier on declarations
|
|
1586
|
-
if ((ts.isVariableStatement(node) ||
|
|
1587
|
-
ts.isFunctionDeclaration(node) ||
|
|
1588
|
-
ts.isInterfaceDeclaration(node) ||
|
|
1589
|
-
ts.isTypeAliasDeclaration(node) ||
|
|
1590
|
-
ts.isEnumDeclaration(node) ||
|
|
1591
|
-
ts.isClassDeclaration(node)) &&
|
|
1592
|
-
node.modifiers?.some((mod) => mod.kind === ts.SyntaxKind.ExportKeyword)) {
|
|
1593
|
-
hasESMImports = true;
|
|
1594
|
-
}
|
|
1595
|
-
// Check for CommonJS require/exports
|
|
1596
|
-
if (ts.isCallExpression(node)) {
|
|
1597
|
-
if (ts.isIdentifier(node.expression) &&
|
|
1598
|
-
node.expression.text === "require" &&
|
|
1599
|
-
node.arguments.length > 0) {
|
|
1600
|
-
hasCommonJS = true;
|
|
1601
|
-
}
|
|
1602
|
-
}
|
|
1603
|
-
// Check for module.exports or exports.xxx
|
|
1604
|
-
if (ts.isPropertyAccessExpression(node)) {
|
|
1605
|
-
const text = node.getText(sourceFile);
|
|
1606
|
-
if (text.startsWith("module.exports") ||
|
|
1607
|
-
text.startsWith("exports.")) {
|
|
1608
|
-
hasCommonJS = true;
|
|
1609
|
-
}
|
|
1610
|
-
}
|
|
1611
|
-
// Continue walking the AST
|
|
1612
|
-
ts.forEachChild(node, walk);
|
|
1613
|
-
}
|
|
1614
|
-
walk(sourceFile);
|
|
1615
|
-
// Determine the module format based on what we found
|
|
1616
|
-
if (hasESMImports && !hasCommonJS) {
|
|
1617
|
-
_esmCount++;
|
|
1618
|
-
}
|
|
1619
|
-
else if (hasCommonJS && !hasESMImports) {
|
|
1620
|
-
cjsCount++;
|
|
1621
|
-
}
|
|
1622
|
-
else if (hasESMImports && hasCommonJS) {
|
|
1623
|
-
// Mixed - probably ESM with dynamic imports or similar
|
|
1624
|
-
_esmCount++;
|
|
1625
|
-
}
|
|
1626
|
-
}
|
|
1627
|
-
catch (error) {
|
|
1628
|
-
console.error(tcolor.magenta(`Error checking module format for ${dep.file} : \n ${error}`));
|
|
1629
|
-
unknownCount++;
|
|
1630
|
-
}
|
|
1631
|
-
}
|
|
1632
|
-
if (unknownCount) {
|
|
1633
|
-
console.error(tcolor.magenta("Unknown error when checking module types in the dependencies tree."));
|
|
1634
|
-
ts.sys.exit(1);
|
|
1635
|
-
}
|
|
1636
|
-
if (cjsCount) {
|
|
1637
|
-
console.error(tcolor.magenta("The package detects CommonJs format in the dependencies tree, that unsupported."));
|
|
1638
|
-
ts.sys.exit(1);
|
|
1639
|
-
}
|
|
1640
|
-
return true;
|
|
1641
|
-
}
|
|
1642
|
-
function ext(_dep) {
|
|
1643
|
-
const tsExt = new Set([".ts", ".mts", ".cts", ".tsx"]);
|
|
1644
|
-
for (const dep of _dep) {
|
|
1645
|
-
const ext = path.extname(dep.file);
|
|
1646
|
-
if (!tsExt.has(ext)) {
|
|
1647
|
-
console.error(tcolor.magenta(`${dep.file} has no valid TypeScript extension`));
|
|
1648
|
-
ts.sys.exit(1);
|
|
1649
|
-
}
|
|
1650
|
-
}
|
|
1651
|
-
return true;
|
|
1652
|
-
}
|
|
1653
|
-
async function init(_dep, options) {
|
|
1654
|
-
const res = resolves([
|
|
1655
|
-
[ext, _dep],
|
|
1656
|
-
[moduleType, _dep],
|
|
1657
|
-
[typesCheck, _dep, options],
|
|
1658
|
-
]);
|
|
1659
|
-
const results = await res.concurrent();
|
|
1660
|
-
return results.every((r) => r === true);
|
|
1661
|
-
}
|
|
1662
|
-
checks.init = init;
|
|
1663
|
-
})(checks || (checks = {}));
|
|
1664
|
-
//src/lib/init/config.ts
|
|
1665
|
-
// -------------
|
|
1666
|
-
const getConfigPath = () => {
|
|
1667
|
-
const fileNames = ["susee.config.ts", "susee.config.js", "susee.config.mjs"];
|
|
1668
|
-
let configFile;
|
|
1669
|
-
for (const file of fileNames) {
|
|
1670
|
-
const _file = ts.sys.resolvePath(file);
|
|
1671
|
-
if (ts.sys.fileExists(_file)) {
|
|
1672
|
-
configFile = _file;
|
|
1673
|
-
break;
|
|
1674
|
-
}
|
|
1675
|
-
}
|
|
1676
|
-
return configFile;
|
|
1677
|
-
};
|
|
1678
|
-
//---------
|
|
1679
|
-
function checkEntries(entries) {
|
|
1680
|
-
if (entries.length < 1) {
|
|
1681
|
-
console.error(tcolor.magenta(`No entry found in susee.config file, at least one entry required`));
|
|
1682
|
-
ts.sys.exit(1);
|
|
1683
|
-
}
|
|
1684
|
-
const objectStore = {};
|
|
1685
|
-
const duplicateExportPaths = [];
|
|
1686
|
-
for (const obj of entries) {
|
|
1687
|
-
const value = obj.exportPath;
|
|
1688
|
-
if (objectStore[value]) {
|
|
1689
|
-
duplicateExportPaths.push(`"${value}"`);
|
|
1690
|
-
}
|
|
1691
|
-
else {
|
|
1692
|
-
objectStore[value] = true;
|
|
1693
|
-
}
|
|
1694
|
-
}
|
|
1695
|
-
if (duplicateExportPaths.length > 0) {
|
|
1696
|
-
console.error(tcolor.magenta(`Duplicate export paths/path (${duplicateExportPaths.join(",")}) found in your susee.config file , that will error for bundled output`));
|
|
1697
|
-
ts.sys.exit(1);
|
|
1698
|
-
}
|
|
1699
|
-
for (const obj of entries) {
|
|
1700
|
-
if (!ts.sys.fileExists(ts.sys.resolvePath(obj.entry))) {
|
|
1701
|
-
console.error(tcolor.magenta(`Entry file ${obj.entry} dose not exists.`));
|
|
1702
|
-
ts.sys.exit(1);
|
|
1703
|
-
}
|
|
1704
|
-
}
|
|
1705
|
-
}
|
|
1706
|
-
/**
|
|
1707
|
-
* Get SuSee configuration from susee.config file (susee.config.ts, susee.config.js, susee.config.mjs)
|
|
1708
|
-
* @returns {Promise<ConfigReturns>} - SuSee configuration
|
|
1709
|
-
* @throws {Error} - when no susee.config file found
|
|
1710
|
-
*/
|
|
1711
|
-
async function getConfig() {
|
|
1712
|
-
const configPath = getConfigPath();
|
|
1713
|
-
if (configPath === undefined) {
|
|
1714
|
-
console.error(tcolor.magenta(`No susee.config file ("susee.config.ts", "susee.config.js", "susee.config.mjs") found`));
|
|
1715
|
-
ts.sys.exit(1);
|
|
1716
|
-
}
|
|
1717
|
-
const _default = await import(configPath);
|
|
1718
|
-
const config = _default.default;
|
|
1719
|
-
const entryCheck = resolves([[checkEntries, config.entryPoints]]);
|
|
1720
|
-
await entryCheck.series();
|
|
1721
|
-
await utilities.wait(1000);
|
|
1722
|
-
const points = [];
|
|
1723
|
-
for (const ent of config.entryPoints) {
|
|
1724
|
-
const point = {
|
|
1725
|
-
entry: ent.entry,
|
|
1726
|
-
exportPath: ent.exportPath,
|
|
1727
|
-
format: ent.format ?? "esm",
|
|
1728
|
-
tsconfigFilePath: ent.tsconfigFilePath ?? undefined,
|
|
1729
|
-
renameDuplicates: ent.renameDuplicates ?? true,
|
|
1730
|
-
// TODO check for defined out dir here or in config.ts
|
|
1731
|
-
outDir: config.outDir ?? "dist",
|
|
1732
|
-
};
|
|
1733
|
-
points.push(point);
|
|
1734
|
-
}
|
|
1735
|
-
return {
|
|
1736
|
-
points,
|
|
1737
|
-
plugins: config.plugins ?? [],
|
|
1738
|
-
allowUpdatePackageJson: config.allowUpdatePackageJson ?? true,
|
|
1739
|
-
};
|
|
1740
|
-
}
|
|
1741
|
-
//src/lib/init/deps.ts
|
|
1742
|
-
//---------------
|
|
1743
|
-
async function fileSizes(path) {
|
|
1744
|
-
const s = await fs.promises.stat(path);
|
|
1745
|
-
const logical = s.size; // bytes in file
|
|
1746
|
-
const allocated = s.blocks !== null ? s.blocks * 512 : null; // bytes actually allocated (POSIX)
|
|
1747
|
-
return { logical, allocated };
|
|
1748
|
-
}
|
|
1749
|
-
const checkExport = (str, file) => {
|
|
1750
|
-
const esmRex = /export default .*/gm;
|
|
1751
|
-
const cjsRex = /export = .*/gm;
|
|
1752
|
-
const ctsRex = /.cts/g;
|
|
1753
|
-
if (str.match(esmRex) || (str.match(cjsRex) && file.match(ctsRex))) {
|
|
1754
|
-
return true;
|
|
1755
|
-
}
|
|
1756
|
-
else {
|
|
1757
|
-
return false;
|
|
1758
|
-
}
|
|
1759
|
-
};
|
|
1760
|
-
/**
|
|
1761
|
-
* Generate dependencies graph for given entry file.
|
|
1762
|
-
*
|
|
1763
|
-
* This function will return an array of dependencies file objects.
|
|
1764
|
-
* Each object will contain the following properties:
|
|
1765
|
-
* - file: path to the file
|
|
1766
|
-
* - content: content of the file
|
|
1767
|
-
* - length: length of the content in bytes
|
|
1768
|
-
* - includeDefExport: whether the file includes export default or export = statement
|
|
1769
|
-
* - size: an object containing the following properties:
|
|
1770
|
-
* - logical: size of the file in bytes
|
|
1771
|
-
* - allocated: size of the file in bytes on disk
|
|
1772
|
-
* - utf8: size of the file in bytes when encoded in utf8
|
|
1773
|
-
* - buffBytes: size of the file in bytes when encoded in buffer
|
|
1774
|
-
*
|
|
1775
|
-
* @param {string} entryFile - path to the entry file
|
|
1776
|
-
* @param {SuseePlugins} plugins - array of plugins
|
|
1777
|
-
* @returns {Promise<DepsFiles>}
|
|
1778
|
-
*/
|
|
1779
|
-
async function generateDependencies(entryFile, plugins) {
|
|
1780
|
-
const deps = await dependencies(entryFile);
|
|
1781
|
-
const sorted = deps.sort(); // get dependencies graph
|
|
1782
|
-
let depsFiles = [];
|
|
1783
|
-
await utilities.wait(1000);
|
|
1784
|
-
for (const dep of sorted) {
|
|
1785
|
-
const file = ts.sys.resolvePath(dep);
|
|
1786
|
-
const content = await fs.promises.readFile(file, "utf8");
|
|
1787
|
-
const s = await fileSizes(file);
|
|
1788
|
-
const length = content.length;
|
|
1789
|
-
const includeDefExport = checkExport(content, file);
|
|
1790
|
-
const _files = {
|
|
1791
|
-
file,
|
|
1792
|
-
content,
|
|
1793
|
-
length,
|
|
1794
|
-
includeDefExport,
|
|
1795
|
-
size: {
|
|
1796
|
-
logical: s.logical,
|
|
1797
|
-
allocated: s.allocated,
|
|
1798
|
-
utf8: new TextEncoder().encode(content).length,
|
|
1799
|
-
buffBytes: Buffer.byteLength(content, "utf8"),
|
|
1800
|
-
},
|
|
1801
|
-
};
|
|
1802
|
-
depsFiles.push(_files);
|
|
1803
|
-
}
|
|
1804
|
-
// call dependency plugins
|
|
1805
|
-
if (plugins.length) {
|
|
1806
|
-
for (const plugin of plugins) {
|
|
1807
|
-
const _plug = typeof plugin === "function" ? plugin() : plugin;
|
|
1808
|
-
if (_plug.type === "dependency") {
|
|
1809
|
-
if (_plug.async) {
|
|
1810
|
-
depsFiles = await _plug.func(depsFiles);
|
|
1811
|
-
}
|
|
1812
|
-
else {
|
|
1813
|
-
depsFiles = _plug.func(depsFiles);
|
|
1814
|
-
}
|
|
1815
|
-
await utilities.wait(1000);
|
|
1816
|
-
}
|
|
1817
|
-
}
|
|
1818
|
-
}
|
|
1819
|
-
return depsFiles;
|
|
1820
|
-
}
|
|
1821
|
-
//src/lib/init/tsCompilerOptions.ts
|
|
1822
|
-
class GetOptions {
|
|
1823
|
-
constructor(point) {
|
|
1824
|
-
this._point = point;
|
|
1825
|
-
this._options = {};
|
|
1826
|
-
}
|
|
1827
|
-
__init() {
|
|
1828
|
-
const __opts = new TsConfig(this._point.tsconfigFilePath);
|
|
1829
|
-
const __outDir = this._point.exportPath === "."
|
|
1830
|
-
? this._point.outDir
|
|
1831
|
-
: `${this._point.outDir}/${this._point.exportPath.slice(2)}`;
|
|
1832
|
-
__opts.removeCompilerOption("rootDir");
|
|
1833
|
-
__opts.removeCompilerOption("module");
|
|
1834
|
-
__opts.editCompilerOptions({
|
|
1835
|
-
moduleResolution: ts.ModuleResolutionKind.NodeNext,
|
|
1836
|
-
outDir: __outDir,
|
|
1837
|
-
});
|
|
1838
|
-
this._options = __opts.getCompilerOptions();
|
|
1839
|
-
}
|
|
1840
|
-
__init2() {
|
|
1841
|
-
this.__init();
|
|
1842
|
-
let { types, lib, ...restOptions } = this._options;
|
|
1843
|
-
// normalize types into an array
|
|
1844
|
-
if (types) {
|
|
1845
|
-
if (!types.includes("node")) {
|
|
1846
|
-
types = ["node", ...types];
|
|
1847
|
-
}
|
|
1848
|
-
}
|
|
1849
|
-
else {
|
|
1850
|
-
types = ["node"];
|
|
1851
|
-
}
|
|
1852
|
-
if (lib) {
|
|
1853
|
-
lib = [...new Set(["ESNext", ...lib])];
|
|
1854
|
-
}
|
|
1855
|
-
else {
|
|
1856
|
-
lib = ["ESNext"];
|
|
1857
|
-
}
|
|
1858
|
-
return { types, lib, ...restOptions };
|
|
1859
|
-
}
|
|
1860
|
-
get commonjs() {
|
|
1861
|
-
const opts = this.__init2();
|
|
1862
|
-
const { module, ...rest } = opts;
|
|
1863
|
-
return { module: ts.ModuleKind.CommonJS, ...rest };
|
|
1864
|
-
}
|
|
1865
|
-
get esm() {
|
|
1866
|
-
const opts = this.__init2();
|
|
1867
|
-
const { module, ...rest } = opts;
|
|
1868
|
-
return { module: ts.ModuleKind.ES2020, ...rest };
|
|
1869
|
-
}
|
|
1870
|
-
get default() {
|
|
1871
|
-
return this.__init2();
|
|
1872
|
-
}
|
|
1873
|
-
}
|
|
1874
|
-
/**
|
|
1875
|
-
* Returns an instance of GetOptions, which provides various methods
|
|
1876
|
-
* to generate different sets of compiler options based on the
|
|
1877
|
-
* given Point.
|
|
1878
|
-
*
|
|
1879
|
-
* @param {Point} point - The point to generate compiler options for.
|
|
1880
|
-
* @returns {GetOptions}
|
|
1881
|
-
*/
|
|
1882
|
-
function getOptions(point) {
|
|
1883
|
-
return new GetOptions(point);
|
|
1884
|
-
}
|
|
1885
|
-
//src/lib/init/index.ts
|
|
1886
|
-
/**
|
|
1887
|
-
* This function takes a susee configuration object and returns a promise that resolves with a `CollatedReturn` object.
|
|
1888
|
-
* The function iterates over the `points` array in the susee configuration object.
|
|
1889
|
-
* For each point, it generates the dependencies using the `generateDependencies` function.
|
|
1890
|
-
* It then checks if the dependencies are valid using the `checks.init` function.
|
|
1891
|
-
* If the dependencies are invalid, it exits the process with code 1.
|
|
1892
|
-
* If the dependencies are valid, it constructs a `CollatedPoint` object and adds it to the result array.
|
|
1893
|
-
* Finally, it returns a `CollatedReturn` object with the result array and the `allowUpdatePackageJson` flag.
|
|
1894
|
-
*/
|
|
1895
|
-
async function collections() {
|
|
1896
|
-
const __config = await getConfig();
|
|
1897
|
-
const points = __config.points;
|
|
1898
|
-
const result = [];
|
|
1899
|
-
for (const point of points) {
|
|
1900
|
-
const __opts = getOptions(point);
|
|
1901
|
-
const __deps = await generateDependencies(point.entry, __config.plugins);
|
|
1902
|
-
const checked = await checks.init(__deps, __opts.esm);
|
|
1903
|
-
if (!checked) {
|
|
1904
|
-
ts.sys.exit(1);
|
|
1905
|
-
}
|
|
1906
|
-
const c = {
|
|
1907
|
-
fileName: point.entry,
|
|
1908
|
-
exportPath: point.exportPath,
|
|
1909
|
-
format: point.format,
|
|
1910
|
-
rename: point.renameDuplicates,
|
|
1911
|
-
outDir: point.outDir,
|
|
1912
|
-
tsOptions: {
|
|
1913
|
-
cjs: __opts.commonjs,
|
|
1914
|
-
esm: __opts.esm,
|
|
1915
|
-
default: __opts.default,
|
|
1916
|
-
},
|
|
1917
|
-
depFiles: __deps,
|
|
1918
|
-
plugins: __config.plugins,
|
|
1919
|
-
};
|
|
1920
|
-
result.push(c);
|
|
1921
|
-
}
|
|
1922
|
-
return {
|
|
1923
|
-
points: result,
|
|
1924
|
-
allowUpdatePackageJson: __config.allowUpdatePackageJson,
|
|
1925
|
-
};
|
|
1926
|
-
}
|
|
1927
|
-
//src/index.ts
|
|
1928
|
-
/**
|
|
1929
|
-
* Bundles a TypeScript project into a single file.
|
|
1930
|
-
* The function takes a {@link SuSeeConfig} object as input and returns a promise resolves with a bundled result.
|
|
1931
|
-
* The function applies the following steps:
|
|
1932
|
-
* 1. Call dependency plugins.
|
|
1933
|
-
* 2. Handle duplicates.
|
|
1934
|
-
* 3. Handling anonymous imports and exports.
|
|
1935
|
-
* 4. Remove Imports.
|
|
1936
|
-
* 5. Remove Exports from dependencies only.
|
|
1937
|
-
* 6. Handle imported statements.
|
|
1938
|
-
* 7. Create final content.
|
|
1939
|
-
* 8. Call pre-process plugins.
|
|
1940
|
-
* 9. Returns.
|
|
1941
|
-
*/
|
|
1942
|
-
async function susee() {
|
|
1943
|
-
console.info(`${tcolor.green("Start")} : ${tcolor.cyan("bundling")}`);
|
|
1944
|
-
const collected = await collections();
|
|
1945
|
-
await utilities.wait(1000);
|
|
1946
|
-
const bundled = await bundle(collected);
|
|
1947
|
-
await utilities.wait(1000);
|
|
1948
|
-
const compiler = new Compiler(bundled);
|
|
1949
|
-
await compiler.compile();
|
|
1950
|
-
console.info(`${tcolor.green("End")} : ${tcolor.cyan("bundling")}`);
|
|
1951
|
-
}
|
|
1952
|
-
export { susee };
|
|
1953
|
-
//# sourceMappingURL=index.js.map
|
|
8
|
+
import TsConfig from"@suseejs/tsconfig";import dependencies from"@suseejs/dependencies";import fs from"node:fs";import path from"node:path";import resolves from"@phothinmaung/resolves";import tcolor from"@suseejs/tcolor";import transformFunction from"@suseejs/transformer";import ts from"typescript";import utilities from"@suseejs/utils";import{Buffer}from"node:buffer";function splitCamelCase(e){return e.replace(/([a-z])([A-Z])/g,"$1 $2").replace(/(_|-|\/)([a-z] || [A-Z])/g," ").replace(/([A-Z])/g,e=>e.toLowerCase()).replace(/^([a-z])/,e=>e.toUpperCase())}function uniqueName(){const e=new Map,t={setPrefix({key:s,value:i}){if(e.has(s))throw console.warn(`${s} already exist`),new Error;return e.set(s,[i,0]),t},getName(t,s){const[i,n]=e.get(t)||[],a=i?`${i}${s}_${(n??0)+1}`:`$nyein${s}_${(n??0)+1}`;return e.set(t,[i??"$nyein",(n??0)+1]),a},getPrefix(t){const[s]=e.get(t)||[];return s}};return t}const exportDefaultExportNameMap=[],exportDefaultImportNameMap=[],prefixKey="AnonymousName",genName=uniqueName().setPrefix({key:prefixKey,value:"__anonymous__"});function anonymousCallExpressionHandler(e){return({file:t,content:s,...i})=>{const n=ts.createSourceFile(t,s,ts.ScriptTarget.Latest,!0),a=transformFunction(e=>{const{factory:s}=e,i=n=>{if(ts.isCallExpression(n)){if(ts.isIdentifier(n.expression)){const e=n.expression.text,i=exportDefaultImportNameMap.find(s=>s.base===e&&s.file===t);if(i)return s.updateCallExpression(n,s.createIdentifier(i.newName),n.typeArguments,n.arguments)}}else if(ts.isPropertyAccessExpression(n)){if(ts.isIdentifier(n.expression)){const e=n.expression.text,i=exportDefaultImportNameMap.find(s=>s.base===e&&s.file===t);if(i)return s.updatePropertyAccessExpression(n,s.createIdentifier(i.newName),n.name)}}else if(ts.isNewExpression(n)){if(ts.isIdentifier(n.expression)){const e=n.expression.text,i=exportDefaultImportNameMap.find(s=>s.base===e&&s.file===t);if(i)return s.updateNewExpression(n,s.createIdentifier(i.newName),n.typeArguments,n.arguments)}}else if(ts.isExportSpecifier(n)&&ts.isIdentifier(n.name)){const e=n.name.text,i=exportDefaultImportNameMap.find(s=>s.base===e&&s.file===t);if(i)return s.updateExportSpecifier(n,n.isTypeOnly,n.propertyName,s.createIdentifier(i.newName))}return ts.visitEachChild(n,i,e)};return e=>ts.visitNode(e,i)},n,e);return{file:t,content:a,...i}}}function anonymousExportHandler(e){return({file:t,content:s,...i})=>{const n=ts.createSourceFile(t,s,ts.ScriptTarget.Latest,!0),a=transformFunction(e=>{const{factory:s}=e,i=a=>{const r=path.basename(t).split(".")[0];if((ts.isFunctionDeclaration(a)||ts.isClassDeclaration(a))&&void 0===a.name){let e=!1,t=!1;if(a.modifiers?.forEach(s=>{s.kind===ts.SyntaxKind.ExportKeyword&&(e=!0),s.kind===ts.SyntaxKind.DefaultKeyword&&(t=!0)}),e&&t){const e=genName.getName(prefixKey,r);if(exportDefaultExportNameMap.push({base:e,file:r,newName:e,isEd:!0}),ts.isFunctionDeclaration(a))return s.updateFunctionDeclaration(a,a.modifiers,a.asteriskToken,s.createIdentifier(e),a.typeParameters,a.parameters,a.type,a.body);if(ts.isClassDeclaration(a))return s.updateClassDeclaration(a,a.modifiers,s.createIdentifier(e),a.typeParameters,a.heritageClauses,a.members)}}else if(ts.isExportAssignment(a)&&!a.name&&!a.isExportEquals){if(ts.isArrowFunction(a.expression)){const e=genName.getName(prefixKey,r),t=s.createArrowFunction(a.expression.modifiers,a.expression.typeParameters,a.expression.parameters,a.expression.type,a.expression.equalsGreaterThanToken,a.expression.body),i=s.createVariableDeclaration(s.createIdentifier(e),a.expression.exclamationToken,a.expression.type,t),o=s.createVariableDeclarationList([i],ts.NodeFlags.Const),c=s.createVariableStatement(a.expression.modifiers,o),l=s.createExportAssignment(void 0,void 0,s.createIdentifier(e));return exportDefaultExportNameMap.push({base:e,file:r,newName:e,isEd:!0}),s.updateSourceFile(n,[c,l],n.isDeclarationFile,n.referencedFiles,n.typeReferenceDirectives,n.hasNoDefaultLib,n.libReferenceDirectives)}if(ts.isObjectLiteralExpression(a.expression)){const e=genName.getName(prefixKey,r),t=s.createVariableDeclaration(s.createIdentifier(e),void 0,void 0,a.expression),i=s.createVariableDeclarationList([t],ts.NodeFlags.Const),o=s.createVariableStatement(void 0,i),c=s.createExportAssignment(void 0,void 0,s.createIdentifier(e));return exportDefaultExportNameMap.push({base:e,file:r,newName:e,isEd:!0}),s.updateSourceFile(n,[o,c],n.isDeclarationFile,n.referencedFiles,n.typeReferenceDirectives,n.hasNoDefaultLib,n.libReferenceDirectives)}if(ts.isArrayLiteralExpression(a.expression)){const e=genName.getName(prefixKey,r),t=s.createArrayLiteralExpression(a.expression.elements,!0),i=s.createVariableDeclaration(s.createIdentifier(e),void 0,void 0,t),o=s.createVariableDeclarationList([i],ts.NodeFlags.Const),c=s.createVariableStatement(void 0,o),l=s.createExportAssignment(void 0,void 0,s.createIdentifier(e));return exportDefaultExportNameMap.push({base:e,file:r,newName:e,isEd:!0}),s.updateSourceFile(n,[c,l],n.isDeclarationFile,n.referencedFiles,n.typeReferenceDirectives,n.hasNoDefaultLib,n.libReferenceDirectives)}if(ts.isStringLiteral(a.expression)){const e=genName.getName(prefixKey,r),t=s.createStringLiteral(a.expression.text),i=s.createVariableDeclaration(s.createIdentifier(e),void 0,void 0,t),o=s.createVariableDeclarationList([i],ts.NodeFlags.Const),c=s.createVariableStatement(void 0,o),l=s.createExportAssignment(void 0,void 0,s.createIdentifier(e));return exportDefaultExportNameMap.push({base:e,file:r,newName:e,isEd:!0}),s.updateSourceFile(n,[c,l],n.isDeclarationFile,n.referencedFiles,n.typeReferenceDirectives,n.hasNoDefaultLib,n.libReferenceDirectives)}if(ts.isNumericLiteral(a.expression)){const e=genName.getName(prefixKey,r),t=s.createNumericLiteral(a.expression.text),i=s.createVariableDeclaration(s.createIdentifier(e),void 0,void 0,t),o=s.createVariableDeclarationList([i],ts.NodeFlags.Const),c=s.createVariableStatement(void 0,o),l=s.createExportAssignment(void 0,void 0,s.createIdentifier(e));return exportDefaultExportNameMap.push({base:e,file:r,newName:e,isEd:!0}),s.updateSourceFile(n,[c,l],n.isDeclarationFile,n.referencedFiles,n.typeReferenceDirectives,n.hasNoDefaultLib,n.libReferenceDirectives)}}return ts.visitEachChild(a,i,e)};return e=>ts.visitNode(e,i)},n,e);return{file:t,content:a,...i}}}function anonymousImportHandler(e){return({file:t,content:s,...i})=>{const n=ts.createSourceFile(t,s,ts.ScriptTarget.Latest,!0),a=transformFunction(e=>{const{factory:s}=e,i=a=>{if(ts.isImportDeclaration(a)){const e=a.moduleSpecifier.getText(n),i=path.basename(e).split(".")[0].trim();if(a.importClause?.name&&ts.isIdentifier(a.importClause.name)){const e=a.importClause.name.text.trim(),n=exportDefaultExportNameMap.find(e=>e.file===i);if(n){exportDefaultImportNameMap.push({base:e,file:t,newName:n.newName,isEd:!0});const i=s.updateImportClause(a.importClause,a.importClause.phaseModifier,s.createIdentifier(n.newName),a.importClause.namedBindings);return s.updateImportDeclaration(a,a.modifiers,i,a.moduleSpecifier,a.attributes)}}}return ts.visitEachChild(a,i,e)};return e=>ts.visitNode(e,i)},n,e);return{file:t,content:a,...i}}}const anonymousHandler=async(e,t)=>{const s=resolves([[anonymousExportHandler,t],[anonymousImportHandler,t],[anonymousCallExpressionHandler,t]]),i=await s.concurrent();for(const t of i)e=e.map(t);return e},namesMap=new Map,callNameMap=[],importNameMap=[],exportNameMap=[];function __uniqueName(){const e=new Map;return{setPrefix({key:t,value:s}){const i=[];let n;if(e.has(t))throw console.warn(`${t} already exist`),new Error;return n=s,e.set(t,s),{getName:function(e){const t=i.length,s=n?`${n}${e}_${t+1}`:`$nyein${e}_${t+1}`;return i.push(s),s}}},getPrefix(t){if(e.has(t))return e.get(t)}}}const dupName=__uniqueName().setPrefix({key:"DuplicatesNames",value:"__duplicatesNames__"}),normalizePathKey=e=>{const t=path.parse(e);let s=path.join(t.dir,t.name);return"index"===t.name&&(s=t.dir),path.normalize(s)},getFileKey=e=>normalizePathKey(e),getModuleKeyFromSpecifier=(e,t,s)=>{let i="";if(i=ts.isStringLiteral(e)?e.text:e.getText(t).replace(/^['"]|['"]$/g,""),i.startsWith(".")||i.startsWith("/")){const e=path.dirname(s);return normalizePathKey(path.resolve(e,i))}return i},callExpression=e=>({file:t,content:s,...i})=>{const n=ts.createSourceFile(t,s,ts.ScriptTarget.Latest,!0),a=transformFunction(e=>{const{factory:s}=e,i=n=>{if(ts.isCallExpression(n)){if(ts.isIdentifier(n.expression)){const e=n.expression.text;let i=null;const a=callNameMap.find(s=>s.base===e&&s.file===t),r=importNameMap.find(s=>s.base===e&&s.file===t);if(a?i=a.newName:r&&(i=r.newName),i)return s.updateCallExpression(n,s.createIdentifier(i),n.typeArguments,n.arguments)}}else if(ts.isPropertyAccessExpression(n)){if(ts.isIdentifier(n.expression)){const e=n.expression.text;let i=null;const a=callNameMap.find(s=>s.base===e&&s.file===t),r=importNameMap.find(s=>s.base===e&&s.file===t);if(a?i=a.newName:r&&(i=r.newName),i)return s.updatePropertyAccessExpression(n,s.createIdentifier(i),n.name)}}else if(ts.isNewExpression(n)&&ts.isIdentifier(n.expression)){const e=n.expression.text;let i=null;const a=callNameMap.find(s=>s.base===e&&s.file===t),r=importNameMap.find(s=>s.base===e&&s.file===t);if(a?i=a.newName:r&&(i=r.newName),i)return s.updateNewExpression(n,s.createIdentifier(i),n.typeArguments,n.arguments)}return ts.visitEachChild(n,i,e)};return e=>ts.visitNode(e,i)},n,e);return{file:t,content:a,...i}},exportExpression=e=>({file:t,content:s,...i})=>{const n=ts.createSourceFile(t,s,ts.ScriptTarget.Latest,!0),a=transformFunction(e=>{const{factory:s}=e,i=n=>{if(ts.isExportSpecifier(n)){if(ts.isIdentifier(n.name)){const e=n.name.text;let i=null;const a=callNameMap.find(s=>s.base===e&&s.file===t),r=importNameMap.find(s=>s.base===e&&s.file===t);if(a?(exportNameMap.push({base:e,file:getFileKey(t),newName:a.newName}),i=a.newName):r&&(i=r.newName),i)return s.updateExportSpecifier(n,n.isTypeOnly,n.propertyName,s.createIdentifier(i))}}else if(ts.isExportAssignment(n)){const e=n.expression;if(ts.isIdentifier(e)){const i=e.text;let a=null;const r=callNameMap.find(e=>e.base===i&&e.file===t),o=importNameMap.find(e=>e.base===i&&e.file===t);if(r?(exportNameMap.push({base:i,file:getFileKey(t),newName:r.newName}),a=r.newName):o&&(a=o.newName),a)return s.updateExportAssignment(n,n.modifiers,s.createIdentifier(a))}}return ts.visitEachChild(n,i,e)};return e=>ts.visitNode(e,i)},n,e);return{file:t,content:a,...i}},importExpression=e=>({file:t,content:s,...i})=>{const n=ts.createSourceFile(t,s,ts.ScriptTarget.Latest,!0),a=transformFunction(e=>{const{factory:s}=e,i=a=>{if(ts.isImportDeclaration(a)){const e=getModuleKeyFromSpecifier(a.moduleSpecifier,n,t);let i=[];if(a.importClause?.namedBindings&&ts.isNamedImports(a.importClause.namedBindings)&&(i=a.importClause.namedBindings.elements.map(e=>e.name.text.trim())),a.importClause?.name&&ts.isIdentifier(a.importClause.name)){const i=a.importClause.name.text.trim(),n=exportNameMap.find(t=>t.base===i&&t.file===e);if(n){importNameMap.push({base:n.base,file:t,newName:n.newName});const e=s.updateImportClause(a.importClause,a.importClause.phaseModifier,s.createIdentifier(n.newName),a.importClause.namedBindings);return s.updateImportDeclaration(a,a.modifiers,e,a.moduleSpecifier,a.attributes)}}if(i.length>0&&a.importClause&&a.importClause.namedBindings&&ts.isNamedImports(a.importClause.namedBindings)){const i=a.importClause.namedBindings.elements.map(i=>{const n=exportNameMap.find(t=>t.base===i.name.text.trim()&&t.file===e);return n?(importNameMap.push({base:n.base,file:t,newName:n.newName}),s.updateImportSpecifier(i,i.isTypeOnly,i.propertyName,s.createIdentifier(n.newName))):i}),n=s.updateNamedImports(a.importClause.namedBindings,i),r=s.updateImportClause(a.importClause,a.importClause.phaseModifier,a.importClause.name,n);return s.updateImportDeclaration(a,a.modifiers,r,a.moduleSpecifier,a.attributes)}}return ts.visitEachChild(a,i,e)};return e=>ts.visitNode(e,i)},n,e);return{file:t,content:a,...i}},collector=e=>({file:t,content:s,...i})=>{const n=ts.createSourceFile(t,s,ts.ScriptTarget.Latest,!0),a=transformFunction(e=>{function s(i,n=!0){if(n)if(ts.isVariableStatement(i))i.declarationList.declarations.forEach(e=>{if(ts.isIdentifier(e.name)){const s=e.name.text;namesMap.has(s)?namesMap.get(s).add({file:t}):namesMap.set(s,new Set([{file:t}]))}});else if(ts.isFunctionDeclaration(i)||ts.isClassDeclaration(i)||ts.isEnumDeclaration(i)||ts.isInterfaceDeclaration(i)||ts.isTypeAliasDeclaration(i)){const e=i.name?.text;e&&(namesMap.has(e)?namesMap.get(e).add({file:t}):namesMap.set(e,new Set([{file:t}])))}return ts.isBlock(i)||ts.isFunctionDeclaration(i)||ts.isFunctionExpression(i)||ts.isArrowFunction(i)||ts.isMethodDeclaration(i)||ts.isClassDeclaration(i)?(ts.isBlock(i)?ts.visitNodes(i.statements,e=>s(e,!1)):ts.forEachChild(i,e=>{s(e,!1)}),i):ts.visitEachChild(i,e=>s(e,n),e)}return e=>s(e,!0)},n,e);return{file:t,content:a,...i}},updater=e=>({file:t,content:s,...i})=>{const n=ts.createSourceFile(t,s,ts.ScriptTarget.Latest,!0),a=transformFunction(e=>{const{factory:s}=e,i=n=>{if(ts.isVariableStatement(n)){const e=n.declarationList.declarations.map(e=>{if(ts.isIdentifier(e.name)){const i=e.name.text;if(namesMap.has(i)&&namesMap.get(i).size>1){const n=dupName.getName(i);return callNameMap.push({base:i,file:t,newName:n}),s.updateVariableDeclaration(e,s.createIdentifier(n),e.exclamationToken,e.type,e.initializer)}}return e}),i=s.updateVariableDeclarationList(n.declarationList,e);return s.updateVariableStatement(n,n.modifiers,i)}if(ts.isFunctionDeclaration(n)){if(n.name&&ts.isIdentifier(n.name)){const e=n.name.text;if(namesMap.has(e)&&namesMap.get(e).size>1){const i=dupName.getName(e);return callNameMap.push({base:e,file:t,newName:i}),s.updateFunctionDeclaration(n,n.modifiers,n.asteriskToken,s.createIdentifier(i),n.typeParameters,n.parameters,n.type,n.body)}}}else if(ts.isClassDeclaration(n)&&n.name&&ts.isIdentifier(n.name)){const e=n.name.text;if(namesMap.has(e)&&namesMap.get(e).size>1){const i=dupName.getName(e);return callNameMap.push({base:e,file:t,newName:i}),s.updateClassDeclaration(n,n.modifiers,s.createIdentifier(i),n.typeParameters,n.heritageClauses,n.members)}}return ts.visitEachChild(n,i,e)};return e=>ts.visitNode(e,i)},n,e);return{file:t,content:a,...i}},duplicateHandlers={renamed:async(e,t)=>{const s=resolves([[collector,t],[updater,t],[callExpression,t],[exportExpression,t],[importExpression,t],[callExpression,t],[exportExpression,t]]),i=await s.concurrent();for(const t of i)e=e.map(t);return e},notRenamed:async(e,t)=>{let s=!1;const i=resolves([[collector,namesMap,t]]),n=await i.concurrent();return e.map(n[0]),await utilities.wait(1e3),namesMap.forEach((e,t)=>{e.size>1&&(s=!0,console.warn(`Name -> ${t} declared in multiple files :`),e.forEach(e=>console.warn(` - ${e.file}`)))}),await utilities.wait(500),s&&process.exit(1),e}};function mergeImportsStatement(e){const t=new Map,s=new Map,i=new Map,n=new Map,a=new Map;for(const r of e){const e=r.match(/import\s+(?:type\s+)?(?:(.*?)\s+from\s+)?["']([^"']+)["'];?/);if(!e)continue;const[,o,c]=e,l=r.includes("import type"),p=c;if(!o){const e=r.match(/import\s+(?:type\s+)?(\w+)/);if(e){const t=e[1],s=l?n:i;s.has(p)||s.set(p,new Set),s.get(p)?.add(t)}continue}if(o.startsWith("{")){const e=l?s:t;e.has(p)||e.set(p,new Set);o.replace(/[{}]/g,"").split(",").map(e=>e.trim()).filter(Boolean).forEach(t=>e.get(p)?.add(t))}else if(o.startsWith("* as")){const e=o.match(/\*\s+as\s+(\w+)/);if(e){const t=e[1];a.has(p)||a.set(p,new Set),a.get(p)?.add(t)}}else{const e=l?n:i;e.has(p)||e.set(p,new Set),e.get(p)?.add(o.trim())}}const r=[];for(const[e,i]of t){const t=s.get(e)||new Set,n=new Set([...i]);for(const e of t)i.has(e)||n.add(e);if(n.size>0){const t=Array.from(n).sort().join(", ");r.push(`import { ${t} } from "${e}";`)}}for(const[e,i]of s)if(!t.has(e)&&i.size>0){const t=Array.from(i).sort().join(", ");r.push(`import type { ${t} } from "${e}";`)}for(const[e,t]of i){const s=n.get(e)||new Set,i=new Set([...t]);for(const e of s)t.has(e)||i.add(e);if(i.size>0){const t=Array.from(i).join(", ");r.push(`import ${t} from "${e}";`)}}for(const[e,t]of n)if(!i.has(e)&&t.size>0){const s=Array.from(t).join(", ");r.push(`import type ${s} from "${e}";`)}for(const[e,t]of a)if(t.size>0){const s=Array.from(t).join(", ");r.push(`import * as ${s} from "${e}";`)}return r.sort()}function esmExportRemoveHandler(e){return({file:t,content:s,...i})=>{const n=ts.createSourceFile(t,s,ts.ScriptTarget.Latest,!0);return{file:t,content:transformFunction(e=>{const{factory:t}=e,s=i=>{if(!utilities.isInsideNamespace(i)&&(ts.isFunctionDeclaration(i)||ts.isClassDeclaration(i)||ts.isInterfaceDeclaration(i)||ts.isTypeAliasDeclaration(i)||ts.isEnumDeclaration(i)||ts.isVariableStatement(i))){const e=i.modifiers?.filter(e=>e.kind!==ts.SyntaxKind.ExportKeyword&&e.kind!==ts.SyntaxKind.DefaultKeyword);if(e?.length!==i.modifiers?.length){if(ts.isFunctionDeclaration(i))return t.updateFunctionDeclaration(i,e,i.asteriskToken,i.name,i.typeParameters,i.parameters,i.type,i.body);if(ts.isClassDeclaration(i))return t.updateClassDeclaration(i,e,i.name,i.typeParameters,i.heritageClauses,i.members);if(ts.isInterfaceDeclaration(i))return t.updateInterfaceDeclaration(i,e,i.name,i.typeParameters,i.heritageClauses,i.members);if(ts.isTypeAliasDeclaration(i))return t.updateTypeAliasDeclaration(i,e,i.name,i.typeParameters,i.type);if(ts.isEnumDeclaration(i))return t.updateEnumDeclaration(i,e,i.name,i.members);if(ts.isVariableStatement(i))return t.updateVariableStatement(i,e,i.declarationList)}}if(ts.isExportDeclaration(i))return t.createEmptyStatement();if(ts.isExportAssignment(i)){const e=i.expression;if(ts.isIdentifier(e))return t.createEmptyStatement()}return ts.visitEachChild(i,s,e)};return e=>ts.visitNode(e,s)},n,e),...i}}}let properties=[];const typeObj={},typesNames=[];function findProperty(e){const t=[];return ts.isPropertyAccessExpression(e)&&ts.isIdentifier(e.expression)&&t.push(e.expression.text),e.forEachChild(e=>findProperty(e)),t}function importAllRemoveHandler(e,t){return({file:s,content:i,...n})=>{const a=ts.createSourceFile(s,i,ts.ScriptTarget.Latest,!0),r=new Set;for(const e of a.statements)if(ts.isImportEqualsDeclaration(e)&&e.isTypeOnly){const t=e.moduleReference;ts.isExternalModuleReference(t)&&ts.isStringLiteral(t.expression)&&r.add(e.name.text)}const o=transformFunction(t=>{const{factory:i}=t,n=o=>{properties=[...properties,...findProperty(o)];const c={isNamespace:!1,isTypeOnly:!1,isTypeNamespace:!1,source:"",importedString:void 0,importedObject:void 0};if(ts.isTypeReferenceNode(o)&&ts.isQualifiedName(o.typeName)&&ts.isIdentifier(o.typeName.left)&&ts.isIdentifier(o.typeName.right)){const e=o.typeName.left.text,t=o.typeName.right.text;if(typesNames.push(e),e in typeObj?typeObj[e]?.push(t):typeObj[e]=[t],utilities.checkModuleType(a,s).isCommonJs&&"ts"!==e&&!r.has(e))return i.updateTypeReferenceNode(o,i.createIdentifier(t),void 0)}if(ts.isImportDeclaration(o)){const t=o.getText(a);return e.push(t),i.createEmptyStatement()}if(ts.isImportEqualsDeclaration(o)){const t=o.name.text,s=o.moduleReference;let n;if(o.isTypeOnly&&(c.isTypeOnly=!0),c.importedString=t,c.isTypeOnly||properties.includes(t)&&(c.isNamespace=!0),ts.isExternalModuleReference(s)&&ts.isStringLiteral(s.expression)&&(c.source=s.expression.text),c.importedString&&!c.importedObject&&(n=c.isTypeOnly?r.has(c.importedString)?`import type * as ${c.importedString} from "${c.source}";`:typesNames.includes(c.importedString)?`import type { ${typeObj[c.importedString]?.join(",")} } from "${c.source}";`:`import type ${c.importedString} from "${c.source}";`:c.isNamespace&&c.source&&"typescript"!==c.source?`import * as ${c.importedString} from "${c.source}";`:`import ${c.importedString} from "${c.source}";`),!c.importedString&&c.importedObject&&(n=`import { ${c.importedObject.join(", ")} } from "${c.source}";`),n)return e.push(n),i.createEmptyStatement()}if(ts.isVariableStatement(o)){const t=o.declarationList.declarations;if(1===t.length){const s=t[0];if(s.initializer&&ts.isCallExpression(s.initializer)&&ts.isIdentifier(s.initializer.expression)&&"require"===s.initializer.expression.escapedText){const t=s.initializer.arguments[0];if(ts.isStringLiteral(t)&&(c.source=t.text),ts.isIdentifier(s.name)){const e=s.name.text;c.importedString=e,properties.includes(e)&&(c.isNamespace=!0)}else if(ts.isObjectBindingPattern(s.name)){const e=[];for(const t of s.name.elements)ts.isIdentifier(t.name)&&e.push(t.name.text);e.length>0&&(c.importedObject=e)}let n;if(c.importedString&&!c.importedObject&&(n=c.isNamespace?`import * as ${c.importedString} from "${c.source}";`:`import ${c.importedString} from "${c.source}";`),!c.importedString&&c.importedObject&&(n=`import { ${c.importedObject.join(", ")} } from "${c.source}";`),n)return e.push(n),i.createEmptyStatement()}}}return ts.visitEachChild(o,n,t)};return e=>ts.visitNode(e,n)},a,t);return{file:s,content:o,...n}}}const removeHandlers=async(e,t)=>{const s=resolves([[importAllRemoveHandler,e,t],[esmExportRemoveHandler,t]]);return await s.series()};function collectBindingNames(e,t){ts.isIdentifier(e)?t.push(e.text):(ts.isObjectBindingPattern(e)||ts.isArrayBindingPattern(e))&&e.elements.forEach(e=>{ts.isBindingElement(e)&&e.name&&collectBindingNames(e.name,t)})}function clearUnusedCode(e,t,s,i={treatExportsAsUsed:!0}){const n=ts.createSourceFile(t,e,ts.ScriptTarget.Latest,!0),a=new Map,r=new Set,o=(e,t=!1)=>{const s=a.get(e);a.set(e,{exported:!!s?.exported||t})},c=e=>{if(ts.isImportDeclaration(e)&&e.importClause){const t=e.importClause;t.name&&ts.isIdentifier(t.name)&&o(t.name.text,!1),t.namedBindings&&(ts.isNamedImports(t.namedBindings)?t.namedBindings.elements.forEach(e=>{ts.isImportSpecifier(e)&&ts.isIdentifier(e.name)&&o(e.name.text,!1)}):ts.isNamespaceImport(t.namedBindings)&&ts.isIdentifier(t.namedBindings.name)&&o(t.namedBindings.name.text,!1))}else if(ts.isImportEqualsDeclaration(e)&&ts.isIdentifier(e.name))o(e.name.text,!1);else if(ts.isVariableStatement(e)){const t=e.modifiers?.some(e=>e.kind===ts.SyntaxKind.ExportKeyword)??!1;e.declarationList.declarations.forEach(e=>{collectBindingNames(e.name,[]);const s=[];collectBindingNames(e.name,s),s.forEach(e=>o(e,t))})}else if(ts.isFunctionDeclaration(e)&&e.name&&ts.isIdentifier(e.name)){const t=e.modifiers?.some(e=>e.kind===ts.SyntaxKind.ExportKeyword)??!1;o(e.name.text,t)}else if(ts.isClassDeclaration(e)&&e.name&&ts.isIdentifier(e.name)){const t=e.modifiers?.some(e=>e.kind===ts.SyntaxKind.ExportKeyword)??!1;o(e.name.text,t)}if(ts.isIdentifier(e)){const t=e.parent;ts.isVariableDeclaration(t)&&t.name===e||ts.isFunctionDeclaration(t)&&t.name===e||ts.isClassDeclaration(t)&&t.name===e||ts.isImportClause(t)&&t.name===e||ts.isImportSpecifier(t)&&t.name===e||ts.isNamespaceImport(t)&&t.name===e||ts.isBindingElement(t)&&t.name===e||ts.isParameter(t)&&t.name===e||r.add(e.text)}ts.forEachChild(e,c)};c(n);const l=new Set;a.forEach((e,t)=>{r.has(t)||i.treatExportsAsUsed&&e.exported||l.add(t)});return transformFunction(e=>{const t=s=>{if(ts.isImportDeclaration(s)&&s.importClause){const e=s.importClause,t=e.name&&ts.isIdentifier(e.name)?e.name.text:void 0;let i;const n=[];e.namedBindings&&(ts.isNamedImports(e.namedBindings)?e.namedBindings.elements.forEach(e=>{ts.isImportSpecifier(e)&&ts.isIdentifier(e.name)&&n.push(e)}):ts.isNamespaceImport(e.namedBindings)&&ts.isIdentifier(e.namedBindings.name)&&(i=e.namedBindings.name.text));const a=!!t&&!l.has(t),r=!!i&&!l.has(i),o=n.filter(e=>!l.has(e.name.text));if(!a&&!r&&0===o.length)return ts.factory.createNotEmittedStatement(s);if(!a&&!!e.name||void 0!==i&&!r||o.length!==n.length){let e;e=o.length>0?ts.factory.createNamedImports(o):r&&i?ts.factory.createNamespaceImport(ts.factory.createIdentifier(i)):void 0;const n=a&&t?ts.factory.createIdentifier(t):void 0,c=ts.factory.createImportClause(!1,n,e);return ts.factory.updateImportDeclaration(s,s.modifiers,c,s.moduleSpecifier,s.assertClause)}return s}if((ts.isFunctionDeclaration(s)||ts.isClassDeclaration(s))&&s.name&&ts.isIdentifier(s.name))return l.has(s.name.text)?ts.factory.createNotEmittedStatement(s):s;if(ts.isVariableStatement(s)){const e=[];s.declarationList.declarations.forEach(t=>collectBindingNames(t.name,e));return e.some(e=>!l.has(e))?s:ts.factory.createNotEmittedStatement(s)}return ts.visitEachChild(s,t,e)};return e=>ts.visitNode(e,t)},n,s)}async function bundler(e){const t="."===e.exportPath?"Main":splitCamelCase(e.exportPath.slice(2));console.time(`${tcolor.cyan("Bundled")} -> ${tcolor.brightCyan(t)} ${tcolor.cyan("export path")}`);let s=e.depFiles;const i=e.rename,n=e.tsOptions.default,a=e.plugins;let r=[];if(a.length)for(let e of a)e="function"==typeof e?e():e,"dependency"===e.type&&(s=e.async?await e.func(s):e.func(s));s=i?await duplicateHandlers.renamed(s,n):await duplicateHandlers.notRenamed(s,n),s=await anonymousHandler(s,n);const o=await removeHandlers(r,n);s=s.map(o[0]);const c=s.slice(0,-1).map(o[1]),l=s.slice(-1),p=/["']((?!\.\/|\.\.\/)[^"']+)["']/;r=r.filter(e=>p.test(e)),r=mergeImportsStatement(r);let m=`${r.join("\n").trim()}\n${c.map(e=>`${`//${path.relative(process.cwd(),e.file)}`}\n${e.content}`).join("\n").trim()}\n${l.map(e=>`${`//${path.relative(process.cwd(),e.file)}`}\n${e.content}`).join("\n").trim()}`;if(m=m.replace(/^s*;\s*$/gm,"").trim(),m=clearUnusedCode(m,e.fileName,n),a.length)for(let e of a)e="function"==typeof e?e():e,"pre-process"===e.type&&(m=e.async?await e.func(m):e.func(m));return console.timeEnd(`${tcolor.cyan("Bundled")} -> ${tcolor.brightCyan(t)} ${tcolor.cyan("export path")}`),{bundledContent:m,...e}}async function bundle(e){const t=[];for(const s of e.points){const e=await bundler(s);t.push(e)}return{points:t,allowUpdatePackageJson:e.allowUpdatePackageJson}}function createHost(e,t){const s={},i={getSourceFile:(s,i)=>{if(s===t)return ts.createSourceFile(s,e,i)},writeFile:(e,t)=>{s[e]=t},getDefaultLibFileName:e=>ts.getDefaultLibFilePath(e),getCurrentDirectory:()=>"",getDirectories:()=>[],fileExists:e=>e===t,readFile:s=>s===t?e:void 0,getCanonicalFileName:e=>e,useCaseSensitiveFileNames:()=>!0,getNewLine:()=>"\n"};return{createdFiles:s,host:i}}const isCjs=e=>e.commonjs&&e.commonjsTypes,isEsm=e=>e.esm&&e.esmTypes;function getExports(e,t){return isCjs(e)&&isEsm(e)?{[t]:{import:{types:`./${path.relative(process.cwd(),e.esmTypes)}`,default:`./${path.relative(process.cwd(),e.esm)}`},require:{types:`./${path.relative(process.cwd(),e.commonjsTypes)}`,default:`./${path.relative(process.cwd(),e.commonjs)}`}}}:isCjs(e)&&!isEsm(e)?{[t]:{require:{types:`./${path.relative(process.cwd(),e.commonjsTypes)}`,default:`./${path.relative(process.cwd(),e.commonjs)}`}}}:!isCjs(e)&&isEsm(e)?{[t]:{import:{types:`./${path.relative(process.cwd(),e.esmTypes)}`,default:`./${path.relative(process.cwd(),e.esm)}`}}}:{}}async function writePackage(e,t){let s=!0;"."!==t&&(s=!1);const i=ts.sys.resolvePath("package.json"),n=fs.readFileSync(i,"utf8"),a=JSON.parse(n);let{name:r,version:o,description:c,main:l,module:p,type:m,types:f,exports:d,...u}=a;await utilities.wait(500),m="module";let y={},h={},g={},x={};if(s)y=e.main?{main:path.relative(process.cwd(),e.main)}:{},h=e.module?{module:path.relative(process.cwd(),e.module)}:{},g=e.types?{types:path.relative(process.cwd(),e.types)}:{},x={exports:{...getExports(e,t)}};else{y=l?{main:l}:{},h=p?{module:p}:{},g=f?{types:f}:{};x={exports:{...d&&"object"==typeof d&&!Array.isArray(d)?{...d}:{},...getExports(e,t)}}}await utilities.wait(1e3);const w={name:r,version:o,description:c,type:m,...y,...g,...h,...x,...u};utilities.writeCompileFile(i,JSON.stringify(w,null,2))}class Compiler{constructor(e){this.object=e,this.files={commonjs:void 0,commonjsTypes:void 0,esm:void 0,esmTypes:void 0,main:void 0,module:void 0,types:void 0}}_isUpdate(){return this.object.allowUpdatePackageJson}async _commonjs(e){const t="."===e.exportPath,s=t?"Main":splitCamelCase(e.exportPath.slice(2));console.time(`${tcolor.cyan("Compiled CJS")} -> ${tcolor.brightCyan(s)} ${tcolor.cyan("export path")}`);const i=e.fileName,n=e.bundledContent,a=e.format,r=e.plugins,o=e.tsOptions.cjs,c=createHost(n,i),l=c.createdFiles,p=c.host;ts.createProgram([i],o,p).emit(),Object.entries(l).map(async([e,s])=>{if(".js"===path.extname(e)&&r.length)for(let t of r)t="function"==typeof t?t():t,"post-process"===t.type&&(s=t.async?await t.func(s,e):t.func(s,e));this._isUpdate()&&(e.match(/.js/g)&&(this.files.commonjs=e.replace(/.js/g,".cjs")),e.match(/.d.ts/g)&&(this.files.commonjsTypes=e.replace(/.d.ts/g,".d.cts")),!t||"both"!==a&&"commonjs"!==a||(this.files.commonjs&&(this.files.main=this.files.commonjs),this.files.commonjsTypes&&(this.files.types=this.files.commonjsTypes))),e=(e=(e=e.replace(/.js/g,".cjs")).replace(/.map.js/g,".map.cjs")).replace(/.d.ts/g,".d.cts"),await utilities.wait(500),"commonjs"===a&&await utilities.clearFolder(path.dirname(e)),await utilities.writeCompileFile(e,s)}),console.timeEnd(`${tcolor.cyan("Compiled CJS")} -> ${tcolor.brightCyan(s)} ${tcolor.cyan("export path")}`)}async _esm(e){const t="."===e.exportPath,s=t?"Main":splitCamelCase(e.exportPath.slice(2));console.time(`${tcolor.cyan("Compiled ESM")} -> ${tcolor.brightCyan(s)} ${tcolor.cyan("export path")}`);const i=e.fileName,n=e.bundledContent,a=e.format,r=e.plugins,o=e.tsOptions.esm,c=createHost(n,i),l=c.createdFiles,p=c.host;ts.createProgram([i],o,p).emit(),Object.entries(l).map(async([e,s])=>{if(".js"===path.extname(e)&&r.length)for(let t of r)t="function"==typeof t?t():t,"post-process"===t.type&&(s=t.async?await t.func(s,e):t.func(s,e));this._isUpdate()&&(e.match(/.js/g)&&(this.files.esm=e.replace(/.js/g,".mjs")),e.match(/.d.ts/g)&&(this.files.esmTypes=e.replace(/.d.ts/g,".d.mts")),t&&"both"===a&&this.files.esm&&(this.files.module=this.files.esm)),e=(e=(e=e.replace(/.js/g,".mjs")).replace(/.map.js/g,".map.mjs")).replace(/.d.ts/g,".d.mts"),await utilities.wait(500),"commonjs"!==a&&await utilities.clearFolder(path.dirname(e)),await utilities.writeCompileFile(e,s)}),console.timeEnd(`${tcolor.cyan("Compiled ESM")} -> ${tcolor.brightCyan(s)} ${tcolor.cyan("export path")}`)}async compile(){for(const e of this.object.points){switch(await utilities.wait(500),e.format){case"commonjs":await this._commonjs(e),this._isUpdate()&&await writePackage(this.files,e.exportPath);break;case"esm":await this._esm(e),this._isUpdate()&&await writePackage(this.files,e.exportPath);break;case"both":await this._esm(e),await utilities.wait(1e3),await this._commonjs(e),this._isUpdate()&&await writePackage(this.files,e.exportPath)}await utilities.wait(500)}}}var checks;!function(e){function t(e,t){if(!t.noCheck){const s=e.map(e=>e.file);let i=!1;const n=ts.createProgram(s,t);for(const e of s){const t=n.getSourceFile(e);t||(console.error(tcolor.magenta(`File not found: ${e}`)),ts.sys.exit(1));const s=[...n.getSyntacticDiagnostics(t),...n.getSemanticDiagnostics(t),...n.getDeclarationDiagnostics(t)];if(s.length>0){const e={getCurrentDirectory:()=>process.cwd(),getCanonicalFileName:e=>e,getNewLine:()=>ts.sys.newLine};console.error(ts.formatDiagnosticsWithColorAndContext(s,e)),i=!0}}if(!i)return!0;ts.sys.exit(1)}}function s(e){let t=0,s=0;for(const n of e)try{const a=ts.createSourceFile(n.file,n.content,ts.ScriptTarget.Latest,!0);let r=!1,o=!1;function i(e){if((ts.isImportDeclaration(e)||ts.isImportEqualsDeclaration(e)||ts.isExportDeclaration(e)||ts.isExportSpecifier(e)||ts.isExportAssignment(e))&&(r=!0),(ts.isVariableStatement(e)||ts.isFunctionDeclaration(e)||ts.isInterfaceDeclaration(e)||ts.isTypeAliasDeclaration(e)||ts.isEnumDeclaration(e)||ts.isClassDeclaration(e))&&e.modifiers?.some(e=>e.kind===ts.SyntaxKind.ExportKeyword)&&(r=!0),ts.isCallExpression(e)&&ts.isIdentifier(e.expression)&&"require"===e.expression.text&&e.arguments.length>0&&(o=!0),ts.isPropertyAccessExpression(e)){const t=e.getText(a);(t.startsWith("module.exports")||t.startsWith("exports."))&&(o=!0)}ts.forEachChild(e,i)}i(a),r&&!o?0:o&&!r?t++:r&&o&&0}catch(c){console.error(tcolor.magenta(`Error checking module format for ${n.file} : \n ${c}`)),s++}return s&&(console.error(tcolor.magenta("Unknown error when checking module types in the dependencies tree.")),ts.sys.exit(1)),t&&(console.error(tcolor.magenta("The package detects CommonJs format in the dependencies tree, that unsupported.")),ts.sys.exit(1)),!0}function i(e){const t=new Set([".ts",".mts",".cts",".tsx"]);for(const s of e){const e=path.extname(s.file);t.has(e)||(console.error(tcolor.magenta(`${s.file} has no valid TypeScript extension`)),ts.sys.exit(1))}return!0}e.types=async function(e,s){const i=resolves([[t,e,s]]);return(await i.series())[0]},e.moduleAndExtension=async function(e){const t=resolves([[s,e],[i,e]]);return(await t.concurrent()).every(e=>!0===e)}}(checks||(checks={}));const getConfigPath=()=>{const e=["susee.config.ts","susee.config.js","susee.config.mjs"];let t;for(const s of e){const e=ts.sys.resolvePath(s);if(ts.sys.fileExists(e)){t=e;break}}return t};function checkEntries(e){e.length<1&&(console.error(tcolor.magenta("No entry found in susee.config file, at least one entry required")),ts.sys.exit(1));const t={},s=[];for(const i of e){const e=i.exportPath;t[e]?s.push(`"${e}"`):t[e]=!0}s.length>0&&(console.error(tcolor.magenta(`Duplicate export paths/path (${s.join(",")}) found in your susee.config file , that will error for bundled output`)),ts.sys.exit(1));for(const t of e)ts.sys.fileExists(ts.sys.resolvePath(t.entry))||(console.error(tcolor.magenta(`Entry file ${t.entry} dose not exists.`)),ts.sys.exit(1))}async function getConfig(){const e=getConfigPath();void 0===e&&(console.error(tcolor.magenta('No susee.config file ("susee.config.ts", "susee.config.js", "susee.config.mjs") found')),ts.sys.exit(1));const t=(await import(e)).default,s=resolves([[checkEntries,t.entryPoints]]);await s.series(),await utilities.wait(1e3);const i=[];for(const e of t.entryPoints){const s={entry:e.entry,exportPath:e.exportPath,format:e.format??"esm",tsconfigFilePath:e.tsconfigFilePath??void 0,renameDuplicates:e.renameDuplicates??!0,outDir:t.outDir??"dist"};i.push(s)}return{points:i,plugins:t.plugins??[],allowUpdatePackageJson:t.allowUpdatePackageJson??!0}}async function fileSizes(e){const t=await fs.promises.stat(e);return{logical:t.size,allocated:null!==t.blocks?512*t.blocks:null}}const checkExport=(e,t)=>!!(e.match(/export default .*/gm)||e.match(/export = .*/gm)&&t.match(/.cts/g));async function generateDependencies(e){const t=(await dependencies(e)).sort(),s=[];await utilities.wait(1e3);for(const e of t){const t=ts.sys.resolvePath(e),i=await fs.promises.readFile(t,"utf8"),n=await fileSizes(t),a=i.length,r=checkExport(i,t),o=ts.createSourceFile(t,i,ts.ScriptTarget.Latest,!0),c=utilities.checkModuleType(o,t).isCommonJs?"cjs":"esm",l={file:t,content:i,length:a,includeDefExport:r,size:{logical:n.logical,allocated:n.allocated,utf8:(new TextEncoder).encode(i).length,buffBytes:Buffer.byteLength(i,"utf8")},type:c};s.push(l)}return s}class GetOptions{constructor(e){this._point=e,this._options={}}__init(){const e=new TsConfig(this._point.tsconfigFilePath),t="."===this._point.exportPath?this._point.outDir:`${this._point.outDir}/${this._point.exportPath.slice(2)}`;e.removeCompilerOption("rootDir"),e.removeCompilerOption("module"),e.editCompilerOptions({moduleResolution:ts.ModuleResolutionKind.NodeNext,outDir:t}),this._options=e.getCompilerOptions()}__init2(){this.__init();let{types:e,lib:t,...s}=this._options;return e?e.includes("node")||(e=["node",...e]):e=["node"],t=t?[...new Set(["ESNext",...t])]:["ESNext"],{types:e,lib:t,...s}}get commonjs(){const e=this.__init2(),{module:t,...s}=e;return{module:ts.ModuleKind.CommonJS,...s}}get esm(){const e=this.__init2(),{module:t,...s}=e;return{module:ts.ModuleKind.ES2020,...s}}get default(){return this.__init2()}}function getOptions(e){return new GetOptions(e)}async function collections(){console.time(`${tcolor.cyan("Collected Data")} :`);const e=await getConfig(),t=e.points,s=e.plugins,i=[];for(const e of t){const t=getOptions(e);let n=await generateDependencies(e.entry);await checks.types(n,t.esm)||ts.sys.exit(1);let a=!1;if(s.length)for(const e of s){const t="function"==typeof e?e():e;"dependency"===t.type&&(t.name&&"@suseejs/plugin-commonjs"===t.name&&(a=!0),n=t.async?await t.func(n):t.func(n))}if(!a){await checks.moduleAndExtension(n)||ts.sys.exit(1)}const r={fileName:e.entry,exportPath:e.exportPath,format:e.format,rename:e.renameDuplicates,outDir:e.outDir,tsOptions:{cjs:t.commonjs,esm:t.esm,default:t.default},depFiles:n,plugins:s};i.push(r)}return console.timeEnd(`${tcolor.cyan("Collected Data")} :`),{points:i,allowUpdatePackageJson:e.allowUpdatePackageJson}}async function susee(){console.info(`${tcolor.cyan("Started")} : `),console.time(`${tcolor.cyan("Done")}`);const e=await collections();await utilities.wait(1e3);const t=await bundle(e);await utilities.wait(1e3);const s=new Compiler(t);await s.compile(),console.timeEnd(`${tcolor.cyan("Done")}`)}export{susee};
|