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/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
- function removeExportExpressionHandler(compilerOptions) {
59
- return ({ file, content }) => {
60
- const sourceFile = typescript_1.default.createSourceFile(file, content, typescript_1.default.ScriptTarget.Latest, true);
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 { factory } = context;
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
- return { file, content: _content };
74
+ const { content, ...rest } = depsTree;
75
+ return { content: _content, ...rest };
134
76
  };
135
- }
136
- function mergeImports(imports) {
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
- async function bundler({ depsFiles, compilerOptions, renameDuplicates, }) {
235
- const reName = renameDuplicates ?? true;
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
- if (reName) {
244
- depsFiles = await duplicates_1.default.renamed(depsFiles, namesMap, callNameMap, importNameMap, exportNameMap, compilerOptions);
245
- }
246
- else {
247
- depsFiles = await duplicates_1.default.notRenamed(depsFiles, namesMap, compilerOptions);
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
- depsFiles = await (0, anonymous_1.default)(depsFiles, exportDefaultExportNameMap, exportDefaultImportNameMap, compilerOptions);
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
- [removeImportExpressionHandler, removedStatements, compilerOptions],
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(1000);
1177
+ await utils_1.default.wait(500);
1178
+ // 5. Remove Exports from dependencies only
258
1179
  const removeExports = (0, resolves_1.default)([
259
- [removeExportExpressionHandler, compilerOptions],
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 = mergeImports(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
- const content = `${importStatements}\n${depFilesContent}\n${mainFileContent}`;
284
- return content;
285
- }
286
- function checkExports(file, str) {
287
- const sourceFile = typescript_1.default.createSourceFile(file, str, typescript_1.default.ScriptTarget.Latest, true);
288
- let nameExport = false;
289
- let defExport = false;
290
- const transformer = (context) => {
291
- const visitor = (node) => {
292
- if (typescript_1.default.isExportAssignment(node) &&
293
- !node.isExportEquals &&
294
- node.modifiers === undefined &&
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
- else if (typescript_1.default.isNamedExports(node)) {
323
- nameExport = true;
324
- }
325
- else if (typescript_1.default.isVariableStatement(node) ||
326
- typescript_1.default.isFunctionDeclaration(node) ||
327
- typescript_1.default.isInterfaceDeclaration(node) ||
328
- typescript_1.default.isTypeAliasDeclaration(node)) {
329
- const isInsideNamespace = (n) => {
330
- let current = n.parent;
331
- while (current) {
332
- if (typescript_1.default.isModuleDeclaration(current) &&
333
- current.flags === typescript_1.default.NodeFlags.Namespace) {
334
- return true;
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
- const createHost = (sourceCode, fileName) => {
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
- function replaceInJs(fileName, sourceCode, compilerOptions) {
379
- const sourceFile = typescript_1.default.createSourceFile(fileName, sourceCode, typescript_1.default.ScriptTarget.Latest, true);
380
- const transformer = (context) => {
381
- const { factory } = context;
382
- const visitor = (node) => {
383
- if (typescript_1.default.isExpressionStatement(node)) {
384
- const expr = node.expression;
385
- if (typescript_1.default.isBinaryExpression(expr) &&
386
- typescript_1.default.isPropertyAccessExpression(expr.left) &&
387
- typescript_1.default.isIdentifier(expr.left.expression) &&
388
- expr.left.expression.escapedText === "exports" &&
389
- typescript_1.default.isIdentifier(expr.left.name) &&
390
- expr.left.name.escapedText === "default" &&
391
- expr.operatorToken.kind === typescript_1.default.SyntaxKind.EqualsToken &&
392
- typescript_1.default.isIdentifier(expr.right)) {
393
- const newLeftExpr = factory.createIdentifier("module");
394
- const newName = factory.createIdentifier("exports");
395
- const newLeft = factory.updatePropertyAccessExpression(expr.left, newLeftExpr, newName);
396
- const newExpr = factory.updateBinaryExpression(expr, newLeft, expr.operatorToken, expr.right);
397
- return factory.updateExpressionStatement(node, newExpr);
398
- }
399
- }
400
- return typescript_1.default.visitEachChild(node, visitor, context);
401
- };
402
- return (rootNode) => typescript_1.default.visitNode(rootNode, visitor);
403
- };
404
- return (0, transformer_1.default)(transformer, sourceFile, compilerOptions);
405
- }
406
- function replaceInTs(fileName, sourceCode, compilerOptions) {
407
- const sourceFile = typescript_1.default.createSourceFile(fileName, sourceCode, typescript_1.default.ScriptTarget.Latest, true);
408
- const transformer = (context) => {
409
- const { factory } = context;
410
- const visitor = (node) => {
411
- if (typescript_1.default.isExportAssignment(node) &&
412
- node.modifiers === undefined &&
413
- !node.isExportEquals) {
414
- return factory.createExportAssignment(node.modifiers, true, node.expression);
415
- }
416
- return typescript_1.default.visitEachChild(node, visitor, context);
417
- };
418
- return (rootNode) => typescript_1.default.visitNode(rootNode, visitor);
419
- };
420
- return (0, transformer_1.default)(transformer, sourceFile, compilerOptions);
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
- async function clearFolder(folderPath) {
423
- folderPath = node_path_1.default.resolve(process.cwd(), folderPath);
424
- try {
425
- const entries = await node_fs_1.default.promises.readdir(folderPath, {
426
- withFileTypes: true,
427
- });
428
- await Promise.all(entries.map((entry) => node_fs_1.default.promises.rm(node_path_1.default.join(folderPath, entry.name), {
429
- recursive: true,
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
- catch (error) {
433
- if (error.code !== "ENOENT") {
434
- throw error;
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
- async function writeCompileFile(file, content) {
439
- const filePath = typescript_1.default.sys.resolvePath(file);
440
- const dir = node_path_1.default.dirname(filePath);
441
- if (!typescript_1.default.sys.directoryExists(dir)) {
442
- await node_fs_1.default.promises.mkdir(dir, { recursive: true });
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(500);
445
- await node_fs_1.default.promises.writeFile(filePath, content);
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
- class Compilers {
448
- constructor(options) {
449
- this._target = options?.target ?? "both";
450
- this._configPath = options?.configPath;
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
- async commonjs(sourceCode, fileName, compilerOptions, isMain, hooks, isUpdate = true) {
463
- console.time(tcolor_1.default.green("Compiled Commonjs"));
464
- const ck = checkExports(fileName, sourceCode);
465
- if (ck.defExport && ck.nameExport) {
466
- console.warn(tcolor_1.default.yellow("Both name export and default export are exported from your project,that will effect on default export for commonjs output"));
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
- if (ck.defExport && !ck.nameExport) {
475
- const ext = utils_1.default.extname(outName);
476
- if (ext === ".js") {
477
- content = replaceInJs(fileName, content, compilerOptions);
478
- }
479
- if (ext === ".ts") {
480
- content = replaceInTs(fileName, content, compilerOptions);
481
- }
482
- }
483
- if (hooks?.length) {
484
- for (const hook of hooks) {
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 (isUpdate) {
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 (this._target !== "both" && this._target !== "esm") {
513
- await clearFolder(utils_1.default.dirname(outName));
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.green("Compiled Commonjs"));
1461
+ console.timeEnd(tcolor_1.default.cyan(`Compiled commonjs for ${_name} export path`));
518
1462
  }
519
- async esm(sourceCode, fileName, compilerOptions, isMain, hooks, isUpdate = true) {
520
- console.time(tcolor_1.default.green("Compiled ESM"));
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 (hooks?.length) {
528
- for (const hook of hooks) {
529
- if (hook.async) {
530
- content = await hook.func(content, outName);
531
- }
532
- else {
533
- content = hook.func(content, outName);
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
- if (isUpdate) {
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 && this._target === "both" && this.files.esm) {
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 (this._target !== "commonjs") {
553
- await clearFolder(utils_1.default.dirname(outName));
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.green("Compiled ESM"));
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
- const depsCheck = {
561
- types(deps, compilerOptions) {
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 = deps.map((i) => i.file);
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
- ext(deps) {
596
- const tsExt = new Set([".ts", ".mts", ".cts", ".tsx"]);
597
- for (const dep of deps) {
598
- const ext = utils_1.default.extname(dep.file);
599
- if (!tsExt.has(ext)) {
600
- console.error(tcolor_1.default.magenta(`${dep.file} has no valid TypeScript extension`));
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 unknowCount = 0;
610
- for (const dep of deps) {
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
- unknowCount++;
1668
+ unknownCount++;
662
1669
  }
663
1670
  }
664
- if (unknowCount) {
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
- nodeCheck(nodeEnvOption, nodeModules) {
675
- if (!nodeEnvOption && nodeModules.length > 0) {
676
- console.error();
677
- typescript_1.default.sys.exit(1);
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 make(deps, compilerOptions, nodeModules, nodeEnv = true) {
1691
+ }
1692
+ async function init(_dep, options) {
682
1693
  const res = (0, resolves_1.default)([
683
- [depsCheck.ext, deps],
684
- [depsCheck.nodeCheck, nodeEnv, nodeModules],
685
- [depsCheck.moduleType, deps],
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
- return {
788
- depFiles,
789
- modOpts,
790
- generalOptions,
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 duplicates = [];
1724
+ const duplicateExportPaths = [];
812
1725
  for (const obj of entries) {
813
1726
  const value = obj.exportPath;
814
1727
  if (objectStore[value]) {
815
- duplicates.push(`"${value}"`);
1728
+ duplicateExportPaths.push(`"${value}"`);
816
1729
  }
817
1730
  else {
818
1731
  objectStore[value] = true;
819
1732
  }
820
1733
  }
821
- if (duplicates.length > 0) {
822
- console.error(tcolor_1.default.magenta(`Duplicate export paths/path (${duplicates.join(",")}) found in your susee.config file , that will error for bundled output`));
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
- entryPoints: config.entryPoints,
845
- postProcessHooks: config.postProcessHooks ?? [],
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
- const isCjs = (files) => files.commonjs && files.commonjsTypes;
852
- const isEsm = (files) => files.esm && files.esmTypes;
853
- function getExports(files, exportPath) {
854
- return isCjs(files) && isEsm(files)
855
- ? {
856
- [exportPath]: {
857
- import: {
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
- async function writePackage(files, exportPath) {
888
- let isMain = true;
889
- if (exportPath !== ".") {
890
- isMain = false;
891
- }
892
- const pkgFile = utils_1.default.resolvePath("package.json");
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
- _main = main ? { main: main } : {};
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 pkgJson = {
927
- name,
928
- version,
929
- description,
930
- type,
931
- ..._main,
932
- ..._types,
933
- ..._module,
934
- ..._exports,
935
- ...rest,
936
- };
937
- utils_1.default.writeFile(pkgFile, JSON.stringify(pkgJson, null, 2));
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
- async function susee() {
940
- const config = await getConfig();
941
- console.info(tcolor_1.default.cyan("Start Bundle"));
942
- const compile = async (e) => {
943
- const target = e.moduleType ? e.moduleType : "esm";
944
- const configPath = e.tsconfigFilePath;
945
- const ent = await entry({
946
- entryPath: e.entry,
947
- exportPath: e.exportPath,
948
- configPath: e.tsconfigFilePath,
949
- nodeEnv: config.nodeEnv,
950
- });
951
- const sourceCode = await bundler({
952
- depsFiles: ent.depFiles,
953
- compilerOptions: ent.generalOptions,
954
- renameDuplicates: config.renameDuplicates,
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
- const mdOpts = ent.modOpts;
957
- const cjsOpts = mdOpts.commonjs();
958
- const esmOpts = mdOpts.esm();
959
- const compiler = new Compilers({ target, configPath });
960
- if (target === "commonjs") {
961
- await compiler.commonjs(sourceCode, e.entry, cjsOpts.compilerOptions, cjsOpts.isMain, config.postProcessHooks, config.allowUpdatePackageJson);
962
- }
963
- else if (target === "esm") {
964
- await compiler.esm(sourceCode, e.entry, esmOpts.compilerOptions, esmOpts.isMain, config.postProcessHooks, config.allowUpdatePackageJson);
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
- await utils_1.default.wait(1000);
972
- if (config.allowUpdatePackageJson) {
973
- await writePackage(compiler.files, e.exportPath);
1888
+ else {
1889
+ types = ["node"];
974
1890
  }
975
- };
976
- for (const entry of config.entryPoints) {
977
- const entName = entry.exportPath === "." ? "main" : entry.exportPath.slice(2);
978
- await utils_1.default.wait(1000);
979
- console.info(tcolor_1.default.cyan(`Start ${tcolor_1.default.green("->")} "${entName}" export path`));
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
- console.info(tcolor_1.default.cyan("Finished Bundle"));
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