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