susee 0.1.2 → 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.mjs CHANGED
@@ -15,6 +15,14 @@ import transformFunction from "@suseejs/transformer";
15
15
  import ts from "typescript";
16
16
  import utilities from "@suseejs/utils";
17
17
  import { Buffer } from "node:buffer";
18
+ //src/lib/bundle/bundleCreator.ts
19
+ /**
20
+ * Creates a BundleCreator function that transforms a DepsFile with a given BundleVisitor and typescript compiler options.
21
+ * @param {BundleVisitor} bundleVisitor - a BundleVisitor function that takes a context, depsTree, sourceFile, and any number of arguments.
22
+ * @param {ts.CompilerOptions} compilerOptions - typescript compiler options.
23
+ * @param {...any} args - any number of arguments to pass to the BundleVisitor function.
24
+ * @returns {BundleCreator} a BundleCreator function that takes a DepsFile and returns a transformed DepsFile.
25
+ */
18
26
  const bundleCreator = (bundleVisitor, compilerOptions, ...args) => {
19
27
  return (depsTree) => {
20
28
  const sourceFile = ts.createSourceFile(depsTree.file, depsTree.content, ts.ScriptTarget.Latest, true);
@@ -28,12 +36,14 @@ const bundleCreator = (bundleVisitor, compilerOptions, ...args) => {
28
36
  return { content: _content, ...rest };
29
37
  };
30
38
  };
39
+ //src/lib/bundle/mergeImportsStatement.ts
31
40
  function mergeImportsStatement(imports) {
32
41
  const importMap = new Map();
33
42
  const typeImportMap = new Map();
34
43
  const defaultImports = new Map();
35
44
  const typeDefaultImports = new Map();
36
45
  const namespaceImports = new Map();
46
+ // Parse each import statement
37
47
  for (const importStr of imports) {
38
48
  const importMatch = importStr.match(/import\s+(?:type\s+)?(?:(.*?)\s+from\s+)?["']([^"']+)["'];?/);
39
49
  if (!importMatch)
@@ -42,6 +52,7 @@ function mergeImportsStatement(imports) {
42
52
  const isTypeImport = importStr.includes("import type");
43
53
  const modulePath = _modulePath;
44
54
  if (!importClause) {
55
+ // Default import or side-effect import
45
56
  const defaultMatch = importStr.match(/import\s+(?:type\s+)?(\w+)/);
46
57
  if (defaultMatch) {
47
58
  const importName = defaultMatch[1];
@@ -53,6 +64,7 @@ function mergeImportsStatement(imports) {
53
64
  continue;
54
65
  }
55
66
  if (importClause.startsWith("{")) {
67
+ // Named imports: import { a, b } from 'module'
56
68
  const targetMap = isTypeImport ? typeImportMap : importMap;
57
69
  if (!targetMap.has(modulePath))
58
70
  targetMap.set(modulePath, new Set());
@@ -61,9 +73,11 @@ function mergeImportsStatement(imports) {
61
73
  .split(",")
62
74
  .map((s) => s.trim())
63
75
  .filter(Boolean);
76
+ // biome-ignore lint/suspicious/useIterableCallbackReturn : just add name for names each
64
77
  names.forEach((name) => targetMap.get(modulePath)?.add(name));
65
78
  }
66
79
  else if (importClause.startsWith("* as")) {
80
+ // Namespace import: import * as name from 'module'
67
81
  const namespaceMatch = importClause.match(/\*\s+as\s+(\w+)/);
68
82
  if (namespaceMatch) {
69
83
  const namespaceName = namespaceMatch[1];
@@ -73,6 +87,7 @@ function mergeImportsStatement(imports) {
73
87
  }
74
88
  }
75
89
  else {
90
+ // Default import: import name from 'module'
76
91
  const targetMap = isTypeImport ? typeDefaultImports : defaultImports;
77
92
  if (!targetMap.has(modulePath))
78
93
  targetMap.set(modulePath, new Set());
@@ -80,8 +95,10 @@ function mergeImportsStatement(imports) {
80
95
  }
81
96
  }
82
97
  const mergedImports = [];
98
+ // Process named imports - remove type imports that have regular imports
83
99
  for (const [modulePath, regularNames] of importMap) {
84
100
  const typeNames = typeImportMap.get(modulePath) || new Set();
101
+ // Only include type names that don't have regular imports
85
102
  const finalNames = new Set([...regularNames]);
86
103
  for (const typeName of typeNames) {
87
104
  if (!regularNames.has(typeName)) {
@@ -93,14 +110,17 @@ function mergeImportsStatement(imports) {
93
110
  mergedImports.push(`import { ${importNames} } from "${modulePath}";`);
94
111
  }
95
112
  }
113
+ // Add remaining type-only imports (where no regular imports exist for the module)
96
114
  for (const [modulePath, typeNames] of typeImportMap) {
97
115
  if (!importMap.has(modulePath) && typeNames.size > 0) {
98
116
  const importNames = Array.from(typeNames).sort().join(", ");
99
117
  mergedImports.push(`import type { ${importNames} } from "${modulePath}";`);
100
118
  }
101
119
  }
120
+ // Process default imports - remove type default imports that have regular default imports
102
121
  for (const [modulePath, regularDefaultNames] of defaultImports) {
103
122
  const typeDefaultNames = typeDefaultImports.get(modulePath) || new Set();
123
+ // Only include type default names that don't have regular default imports
104
124
  const finalNames = new Set([...regularDefaultNames]);
105
125
  for (const typeName of typeDefaultNames) {
106
126
  if (!regularDefaultNames.has(typeName)) {
@@ -112,12 +132,14 @@ function mergeImportsStatement(imports) {
112
132
  mergedImports.push(`import ${importNames} from "${modulePath}";`);
113
133
  }
114
134
  }
135
+ // Add remaining type-only default imports
115
136
  for (const [modulePath, typeDefaultNames] of typeDefaultImports) {
116
137
  if (!defaultImports.has(modulePath) && typeDefaultNames.size > 0) {
117
138
  const importNames = Array.from(typeDefaultNames).join(", ");
118
139
  mergedImports.push(`import type ${importNames} from "${modulePath}";`);
119
140
  }
120
141
  }
142
+ // Process namespace imports
121
143
  for (const [modulePath, names] of namespaceImports) {
122
144
  if (names.size > 0) {
123
145
  const importNames = Array.from(names).join(", ");
@@ -126,6 +148,11 @@ function mergeImportsStatement(imports) {
126
148
  }
127
149
  return mergedImports.sort();
128
150
  }
151
+ //src/lib/bundle/visitors/anonymousCallExpression.ts
152
+ /**
153
+ * A BundleVisitor that updates the call expression, property access expression, and new expression
154
+ * with the anonymous default import name.
155
+ */
129
156
  const anonymousCallExpressionVisitor = (context, depsTree, _sourceFile, exportDefaultImportNameMap) => {
130
157
  const { factory } = context;
131
158
  const visit = (node) => {
@@ -155,6 +182,7 @@ const anonymousCallExpressionVisitor = (context, depsTree, _sourceFile, exportDe
155
182
  return factory.updateNewExpression(node, factory.createIdentifier(mapping.newName), node.typeArguments, node.arguments);
156
183
  }
157
184
  }
185
+ // for export specifier it is focus on entry file
158
186
  }
159
187
  else if (ts.isExportSpecifier(node)) {
160
188
  if (ts.isIdentifier(node.name)) {
@@ -169,6 +197,7 @@ const anonymousCallExpressionVisitor = (context, depsTree, _sourceFile, exportDe
169
197
  };
170
198
  return visit;
171
199
  };
200
+ //src/lib/bundle/visitors/visitorHelpers.ts
172
201
  const normalizePathKey = (filePath) => {
173
202
  const parsed = path.parse(filePath);
174
203
  let noExt = path.join(parsed.dir, parsed.name);
@@ -224,8 +253,13 @@ function uniqueName() {
224
253
  };
225
254
  return obj;
226
255
  }
256
+ //src/lib/bundle/visitors/anonymousExport.ts
227
257
  const prefixKey = "AnonymousName";
228
258
  const genName = uniqueName().setPrefix({ key: prefixKey, value: "a_" });
259
+ /**
260
+ * A BundleVisitor that updates the call expression, property access expression, and new expression
261
+ * with the anonymous default import name.
262
+ */
229
263
  const anonymousExportVisitor = (context, depsTree, sourceFile, exportDefaultExportNameMap) => {
230
264
  const { factory } = context;
231
265
  const visit = (node) => {
@@ -335,17 +369,23 @@ const anonymousExportVisitor = (context, depsTree, sourceFile, exportDefaultExpo
335
369
  });
336
370
  return factory.updateSourceFile(sourceFile, [variableStatementNode, exportAssignmentNode], sourceFile.isDeclarationFile, sourceFile.referencedFiles, sourceFile.typeReferenceDirectives, sourceFile.hasNoDefaultLib, sourceFile.libReferenceDirectives);
337
371
  }
338
- }
372
+ } //
339
373
  return ts.visitEachChild(node, visit, context);
340
374
  };
341
375
  return visit;
342
376
  };
377
+ //src/lib/bundle/visitors/anonymousImport.ts
378
+ /**
379
+ * A BundleVisitor that updates the import declaration, property access expression, and new expression
380
+ * with the anonymous default import name.
381
+ */
343
382
  const anonymousImportVisitor = (context, depsTree, sourceFile, exportDefaultExportNameMap, exportDefaultImportNameMap) => {
344
383
  const { factory } = context;
345
384
  const visit = (node) => {
346
385
  if (ts.isImportDeclaration(node)) {
347
386
  const fileName = node.moduleSpecifier.getText(sourceFile);
348
387
  const _name = path.basename(fileName).split(".")[0].trim();
388
+ // check only import default expression
349
389
  if (node.importClause?.name && ts.isIdentifier(node.importClause.name)) {
350
390
  const base = node.importClause.name.text.trim();
351
391
  const mapping = exportDefaultExportNameMap.find((v) => v.file === _name);
@@ -365,6 +405,11 @@ const anonymousImportVisitor = (context, depsTree, sourceFile, exportDefaultExpo
365
405
  };
366
406
  return visit;
367
407
  };
408
+ //src/lib/bundle/visitors/duplicateCallExpression.ts
409
+ /**
410
+ * A BundleVisitor that updates the call expression, property access expression, and new expression
411
+ * with the anonymous default import name.
412
+ */
368
413
  const duplicateCallExpressionVisitor = (context, depsTree, _sourceFile, callNameMap, importNameMap) => {
369
414
  const { factory } = context;
370
415
  const visit = (node) => {
@@ -379,6 +424,7 @@ const duplicateCallExpressionVisitor = (context, depsTree, _sourceFile, callName
379
424
  }
380
425
  else if (importMapping) {
381
426
  new_name = importMapping.newName;
427
+ //flag.push(new_name);
382
428
  }
383
429
  if (new_name) {
384
430
  return factory.updateCallExpression(node, factory.createIdentifier(new_name), node.typeArguments, node.arguments);
@@ -419,13 +465,28 @@ const duplicateCallExpressionVisitor = (context, depsTree, _sourceFile, callName
419
465
  }
420
466
  }
421
467
  }
468
+ /* ----------------------Returns for visitor function------------------------------- */
422
469
  return ts.visitEachChild(node, visit, context);
423
470
  };
424
471
  return visit;
425
472
  };
473
+ //src/lib/bundle/visitors/duplicateCollection.ts
474
+ /**
475
+ * A BundleVisitor that updates the collection (variable, function, class, etc)
476
+ * declaration with the anonymous default import name.
477
+ *
478
+ * @param {BundleVisitor} context - The BundleVisitor context.
479
+ * @param {DepsTree} depsTree - The deps tree object.
480
+ * @param {SourceFile} sourceFile - The source file object.
481
+ * @param {DuplicatesNameMap} namesMap - The DuplicatesNameMap object.
482
+ * @return {NodeVisit} visit - The NodeVisit function.
483
+ */
426
484
  const duplicateCollectionVisitor = (context, depsTree, _sourceFile, namesMap) => {
485
+ //const { factory } = context;
427
486
  const visit = (node, isGlobalScope = true) => {
487
+ // Global declarations များကိုသာ collect လုပ်မယ်
428
488
  if (isGlobalScope) {
489
+ // Variable statements (const, let, var)
429
490
  if (ts.isVariableStatement(node)) {
430
491
  node.declarationList.declarations.forEach((decl) => {
431
492
  if (ts.isIdentifier(decl.name)) {
@@ -434,11 +495,13 @@ const duplicateCollectionVisitor = (context, depsTree, _sourceFile, namesMap) =>
434
495
  namesMap.set($name, new Set([{ file: depsTree.file }]));
435
496
  }
436
497
  else {
498
+ // biome-ignore lint/style/noNonNullAssertion : !namesMap.has($name) before
437
499
  namesMap.get($name).add({ file: depsTree.file });
438
500
  }
439
501
  }
440
502
  });
441
503
  }
504
+ // Function, Class, Enum, Interface, Type declarations
442
505
  else if (ts.isFunctionDeclaration(node) ||
443
506
  ts.isClassDeclaration(node) ||
444
507
  ts.isEnumDeclaration(node) ||
@@ -450,17 +513,20 @@ const duplicateCollectionVisitor = (context, depsTree, _sourceFile, namesMap) =>
450
513
  namesMap.set($name, new Set([{ file: depsTree.file }]));
451
514
  }
452
515
  else {
516
+ // biome-ignore lint/style/noNonNullAssertion : !namesMap.has($name) before
453
517
  namesMap.get($name).add({ file: depsTree.file });
454
518
  }
455
519
  }
456
520
  }
457
521
  }
522
+ // Local scope ထဲရောက်သွားတဲ့ node တွေအတွက် recursive visit
458
523
  if (ts.isBlock(node) ||
459
524
  ts.isFunctionDeclaration(node) ||
460
525
  ts.isFunctionExpression(node) ||
461
526
  ts.isArrowFunction(node) ||
462
527
  ts.isMethodDeclaration(node) ||
463
528
  ts.isClassDeclaration(node)) {
529
+ // Local scope ထဲကို ဝင်သွားပြီဆိုတာနဲ့ isGlobalScope = false
464
530
  if (ts.isBlock(node)) {
465
531
  ts.visitNodes(node.statements, (child) => visit(child, false));
466
532
  }
@@ -471,12 +537,19 @@ const duplicateCollectionVisitor = (context, depsTree, _sourceFile, namesMap) =>
471
537
  }
472
538
  }
473
539
  else {
540
+ // Global scope ထဲဆက်ရှိနေတဲ့ node တွေအတွက်
474
541
  return ts.visitEachChild(node, (child) => visit(child, isGlobalScope), context);
475
542
  }
543
+ /* ----------------------Returns for visitNode function------------------------------- */
476
544
  return node;
477
545
  };
478
546
  return visit;
479
547
  };
548
+ //src/lib/bundle/visitors/duplicateExportExpression.ts
549
+ /**
550
+ * A BundleVisitor that updates the call expression, property access expression, and new expression
551
+ * with the anonymous default import name.
552
+ */
480
553
  const duplicateExportExpressionVisitor = (context, depsTree, _sourceFile, callNameMap, importNameMap, exportNameMap) => {
481
554
  const { factory } = context;
482
555
  const visit = (node) => {
@@ -525,10 +598,23 @@ const duplicateExportExpressionVisitor = (context, depsTree, _sourceFile, callNa
525
598
  }
526
599
  }
527
600
  }
601
+ /* ----------------------Returns for visitor function------------------------------- */
528
602
  return ts.visitEachChild(node, visit, context);
529
603
  };
530
604
  return visit;
531
605
  };
606
+ //src/lib/bundle/visitors/duplicateImportExpression.ts
607
+ /**
608
+ * A BundleVisitor that updates the import declaration, property access expression, and new expression
609
+ * with the anonymous default import name.
610
+ *
611
+ * @param {BundleVisitor} context - The BundleVisitor context.
612
+ * @param {DepsTree} depsTree - The deps tree object.
613
+ * @param {SourceFile} sourceFile - The source file object.
614
+ * @param {NamesSets} exportNameMap - The export name map object.
615
+ * @param {NamesSets} importNameMap - The import name map object.
616
+ * @return {NodeVisit} visit - The NodeVisit function.
617
+ */
532
618
  const duplicateImportExpressionVisitor = (context, depsTree, sourceFile, exportNameMap, importNameMap) => {
533
619
  const { factory } = context;
534
620
  const visit = (node) => {
@@ -539,6 +625,7 @@ const duplicateImportExpressionVisitor = (context, depsTree, sourceFile, exportN
539
625
  ts.isNamedImports(node.importClause.namedBindings)) {
540
626
  baseNames = node.importClause.namedBindings.elements.map((el) => el.name.text.trim());
541
627
  }
628
+ // import default expression
542
629
  if (node.importClause?.name && ts.isIdentifier(node.importClause.name)) {
543
630
  const base = node.importClause.name.text.trim();
544
631
  const mapping = exportNameMap.find((m) => m.base === base && m.file === moduleKey);
@@ -552,6 +639,7 @@ const duplicateImportExpressionVisitor = (context, depsTree, sourceFile, exportN
552
639
  return factory.updateImportDeclaration(node, node.modifiers, newImportClause, node.moduleSpecifier, node.attributes);
553
640
  }
554
641
  }
642
+ // import name , `import{ ... }`
555
643
  if (baseNames.length > 0 &&
556
644
  node.importClause &&
557
645
  node.importClause.namedBindings &&
@@ -572,15 +660,28 @@ const duplicateImportExpressionVisitor = (context, depsTree, sourceFile, exportN
572
660
  const newImportClause = factory.updateImportClause(node.importClause, node.importClause.phaseModifier, node.importClause.name, newNamedImports);
573
661
  return factory.updateImportDeclaration(node, node.modifiers, newImportClause, node.moduleSpecifier, node.attributes);
574
662
  }
575
- }
663
+ } //&&
664
+ /* ----------------------Returns for visitor function------------------------------- */
576
665
  return ts.visitEachChild(node, visit, context);
577
666
  };
578
667
  return visit;
579
668
  };
669
+ //src/lib/bundle/visitors/duplicateUpdate.ts
580
670
  const dupName = uniqueName().setPrefix({
581
671
  key: "DuplicatesNames",
582
672
  value: "d_",
583
673
  });
674
+ /**
675
+ * A BundleVisitor that updates the variable declaration, function declaration, and class declaration
676
+ * with the duplicates name.
677
+ *
678
+ * @param {BundleVisitor} context - The BundleVisitor context.
679
+ * @param {DepsTree} depsTree - The deps tree object.
680
+ * @param {SourceFile} sourceFile - The source file object.
681
+ * @param {DuplicatesNameMap} namesMap - The DuplicatesNameMap object.
682
+ * @param {NamesSets} callNameMap - The NamesSets object.
683
+ * @return {NodeVisit} visit - The NodeVisit function.
684
+ */
584
685
  const duplicateUpdateVisitor = (context, depsTree, _sourceFile, namesMap, callNameMap) => {
585
686
  const { factory } = context;
586
687
  const visit = (node) => {
@@ -588,6 +689,7 @@ const duplicateUpdateVisitor = (context, depsTree, _sourceFile, namesMap, callNa
588
689
  const newDeclarations = node.declarationList.declarations.map((decl) => {
589
690
  if (ts.isIdentifier(decl.name)) {
590
691
  const base = decl.name.text;
692
+ // biome-ignore lint/style/noNonNullAssertion : namesMap.has(base) before that get just only size
591
693
  if (namesMap.has(base) && namesMap.get(base).size > 1) {
592
694
  const newName = dupName.getName(base);
593
695
  callNameMap.push({ base, file: depsTree.file, newName });
@@ -602,6 +704,7 @@ const duplicateUpdateVisitor = (context, depsTree, _sourceFile, namesMap, callNa
602
704
  else if (ts.isFunctionDeclaration(node)) {
603
705
  if (node.name && ts.isIdentifier(node.name)) {
604
706
  const base = node.name.text;
707
+ // biome-ignore lint/style/noNonNullAssertion : namesMap.has(base) before that get just only size
605
708
  if (namesMap.has(base) && namesMap.get(base).size > 1) {
606
709
  const newName = dupName.getName(base);
607
710
  callNameMap.push({ base, file: depsTree.file, newName });
@@ -612,6 +715,7 @@ const duplicateUpdateVisitor = (context, depsTree, _sourceFile, namesMap, callNa
612
715
  else if (ts.isClassDeclaration(node)) {
613
716
  if (node.name && ts.isIdentifier(node.name)) {
614
717
  const base = node.name.text;
718
+ // biome-ignore lint/style/noNonNullAssertion : namesMap.has(base) before that get just only size
615
719
  if (namesMap.has(base) && namesMap.get(base).size > 1) {
616
720
  const newName = dupName.getName(base);
617
721
  callNameMap.push({ base, file: depsTree.file, newName });
@@ -619,13 +723,21 @@ const duplicateUpdateVisitor = (context, depsTree, _sourceFile, namesMap, callNa
619
723
  }
620
724
  }
621
725
  }
726
+ /* ----------------------Returns for visitor function------------------------------- */
622
727
  return ts.visitEachChild(node, visit, context);
623
728
  };
624
729
  return visit;
625
730
  };
731
+ //src/lib/bundle/visitors/removeExports.ts
732
+ /**
733
+ * A BundleVisitor that removes all exports from the given source file.
734
+ * It does so by stripping "export" modifiers from function, class, interface, type alias, enum, and variable declarations,
735
+ * and by removing "export { foo }" and "export default" declarations entirely.
736
+ */
626
737
  const removeExportsVisitor = (context) => {
627
738
  const { factory } = context;
628
739
  const visit = (node) => {
740
+ // --- Case 1: Strip "export" modifiers ---
629
741
  const inside_nameSpace = utilities.isInsideNamespace(node);
630
742
  if (!inside_nameSpace) {
631
743
  if (ts.isFunctionDeclaration(node) ||
@@ -637,40 +749,49 @@ const removeExportsVisitor = (context) => {
637
749
  const modifiers = node.modifiers?.filter((m) => m.kind !== ts.SyntaxKind.ExportKeyword &&
638
750
  m.kind !== ts.SyntaxKind.DefaultKeyword);
639
751
  if (modifiers?.length !== node.modifiers?.length) {
752
+ // If the node has an export modifier, remove it.
753
+ // If the node is a function, class, interface, type alias, enum or variable declaration,
754
+ // update the declaration by removing the export modifier.
640
755
  if (ts.isFunctionDeclaration(node)) {
641
756
  return factory.updateFunctionDeclaration(node, modifiers, node.asteriskToken, node.name, node.typeParameters, node.parameters, node.type, node.body);
642
- }
757
+ } // function
643
758
  if (ts.isClassDeclaration(node)) {
644
759
  return factory.updateClassDeclaration(node, modifiers, node.name, node.typeParameters, node.heritageClauses, node.members);
645
- }
760
+ } // class
646
761
  if (ts.isInterfaceDeclaration(node)) {
647
762
  return factory.updateInterfaceDeclaration(node, modifiers, node.name, node.typeParameters, node.heritageClauses, node.members);
648
- }
763
+ } // interface
649
764
  if (ts.isTypeAliasDeclaration(node)) {
650
765
  return factory.updateTypeAliasDeclaration(node, modifiers, node.name, node.typeParameters, node.type);
651
- }
766
+ } // types
652
767
  if (ts.isEnumDeclaration(node)) {
653
768
  return factory.updateEnumDeclaration(node, modifiers, node.name, node.members);
654
- }
769
+ } //enum
655
770
  if (ts.isVariableStatement(node)) {
656
771
  return factory.updateVariableStatement(node, modifiers, node.declarationList);
657
- }
658
- }
659
- }
772
+ } // vars
773
+ } //--
774
+ } // --- Case 1
660
775
  }
776
+ // --- Case 2: Remove "export { foo }" entirely ---
661
777
  if (ts.isExportDeclaration(node)) {
778
+ // If the node is an export declaration, remove it.
662
779
  return factory.createEmptyStatement();
663
780
  }
781
+ // --- Case 3: Handle "export default ..." ---
664
782
  if (ts.isExportAssignment(node)) {
665
783
  const expr = node.expression;
784
+ // export default Foo; -> remove line
666
785
  if (ts.isIdentifier(expr)) {
667
786
  return factory.createEmptyStatement();
668
787
  }
669
788
  }
789
+ // --------- Visitor Return ------------------//
670
790
  return ts.visitEachChild(node, visit, context);
671
791
  };
672
792
  return visit;
673
793
  };
794
+ //src/lib/bundle/visitors/removeImports.ts
674
795
  let properties = [];
675
796
  const typeObj = {};
676
797
  const typesNames = [];
@@ -682,7 +803,14 @@ function findProperty(node) {
682
803
  node.forEachChild((n) => findProperty(n));
683
804
  return properties;
684
805
  }
806
+ /**
807
+ * A BundleVisitor that removes import declarations and import equals declarations from a TypeScript program.
808
+ * The visitor collects the names of type-only import-equals and emits a named/default type import if the type-only import-equals is not a namespace-type alias.
809
+ * The visitor also collects the names of type-only imports of namespace-type aliases and emits a namespace type import if the type-only import-equals is not a namespace-type alias.
810
+ */
685
811
  const removeImportsVisitor = (context, depsTree, sourceFile, removedStatements) => {
812
+ // Pre-scan: collect names of type-only import-equals (these are namespace-type aliases)
813
+ // import type NameSpace = require("foo")
686
814
  const typeOnlyImportEquals = new Set();
687
815
  for (const stmt of sourceFile.statements) {
688
816
  if (ts.isImportEqualsDeclaration(stmt) && stmt.isTypeOnly) {
@@ -704,6 +832,7 @@ const removeImportsVisitor = (context, depsTree, sourceFile, removedStatements)
704
832
  importedString: undefined,
705
833
  importedObject: undefined,
706
834
  };
835
+ // --- Case: TypeReference with QualifiedName (collect type usage)
707
836
  if (ts.isTypeReferenceNode(node) &&
708
837
  ts.isQualifiedName(node.typeName) &&
709
838
  ts.isIdentifier(node.typeName.left) &&
@@ -717,17 +846,23 @@ const removeImportsVisitor = (context, depsTree, sourceFile, removedStatements)
717
846
  else {
718
847
  typeObj[left] = [right];
719
848
  }
849
+ // If this qualified name refers to a type-only import-equals alias, DO NOT rewrite.
850
+ // Rewriting (Foo.Bar -> Bar) was intended to support converting to named imports,
851
+ // but for type-only namespace imports we will emit `import type * as Foo from "..."`.
720
852
  if (utilities.checkModuleType(sourceFile, depsTree.file).isCommonJs) {
721
853
  if (left !== "ts" && !typeOnlyImportEquals.has(left)) {
722
854
  return factory.updateTypeReferenceNode(node, factory.createIdentifier(right), undefined);
723
855
  }
724
856
  }
725
857
  }
858
+ // ------------------------
726
859
  if (ts.isImportDeclaration(node)) {
860
+ // --- Case 1: Import declarations
727
861
  const text = node.getText(sourceFile);
728
862
  removedStatements.push(text);
729
863
  return factory.createEmptyStatement();
730
864
  }
865
+ //--- Case 2: Import equals declarations
731
866
  if (ts.isImportEqualsDeclaration(node)) {
732
867
  const name = node.name.text;
733
868
  const moduleReference = node.moduleReference;
@@ -747,10 +882,12 @@ const removeImportsVisitor = (context, depsTree, sourceFile, removedStatements)
747
882
  let t;
748
883
  if (obj.importedString && !obj.importedObject) {
749
884
  if (obj.isTypeOnly) {
885
+ // If this import-equals was a type-only namespace alias, emit a namespace type import
750
886
  if (typeOnlyImportEquals.has(obj.importedString)) {
751
887
  t = `import type * as ${obj.importedString} from "${obj.source}";`;
752
888
  }
753
889
  else {
890
+ // otherwise try to emit a named/default type import (existing behavior)
754
891
  if (typesNames.includes(obj.importedString)) {
755
892
  t = `import type { ${typeObj[obj.importedString]?.join(",")} } from "${obj.source}";`;
756
893
  }
@@ -771,11 +908,13 @@ const removeImportsVisitor = (context, depsTree, sourceFile, removedStatements)
771
908
  if (!obj.importedString && obj.importedObject) {
772
909
  t = `import { ${obj.importedObject.join(", ")} } from "${obj.source}";`;
773
910
  }
911
+ // removed
774
912
  if (t) {
775
913
  removedStatements.push(t);
776
914
  return factory.createEmptyStatement();
777
915
  }
778
916
  }
917
+ // --- Case 3: Require imports
779
918
  if (ts.isVariableStatement(node)) {
780
919
  const decls = node.declarationList.declarations;
781
920
  if (decls.length === 1) {
@@ -784,6 +923,7 @@ const removeImportsVisitor = (context, depsTree, sourceFile, removedStatements)
784
923
  ts.isCallExpression(decl.initializer) &&
785
924
  ts.isIdentifier(decl.initializer.expression) &&
786
925
  decl.initializer.expression.escapedText === "require") {
926
+ // imported from
787
927
  const arg = decl.initializer.arguments[0];
788
928
  if (ts.isStringLiteral(arg)) {
789
929
  obj.source = arg.text;
@@ -825,15 +965,35 @@ const removeImportsVisitor = (context, depsTree, sourceFile, removedStatements)
825
965
  }
826
966
  }
827
967
  }
968
+ // --------- Visitor Return ------------------//
828
969
  return ts.visitEachChild(node, visit, context);
829
970
  };
830
971
  return visit;
831
972
  };
973
+ //src/lib/bundle/index.ts
974
+ // ------------------------------------------------------------------------------------//
975
+ /**
976
+ * Bundles a TypeScript project into a single file.
977
+ * This function takes a {@link CollatedPoint} object as input and returns a {@link BundleResultPoint} object.
978
+ * The function applies the following steps:
979
+ * 1. Call dependency plugins.
980
+ * 2. Handle duplicates.
981
+ * 3. Handling anonymous imports and exports.
982
+ * 4. Remove Imports.
983
+ * 5. Remove Exports from dependencies only.
984
+ * 6. Handle imported statements.
985
+ * 7. Create final content.
986
+ * 8. Call pre-process plugins.
987
+ * 9. Returns.
988
+ * @param {CollatedPoint} point - A {@link CollatedPoint} object.
989
+ * @returns {Promise<BundleResultPoint>} - A promise resolves with a {@link BundleResultPoint} object.
990
+ */
832
991
  async function bundler(point) {
833
992
  let depsFiles = point.depFiles;
834
993
  const reName = point.rename;
835
994
  const compilerOptions = point.tsOptions.default;
836
995
  const plugins = point.plugins;
996
+ // construct maps
837
997
  const namesMap = new Map();
838
998
  const callNameMap = [];
839
999
  const importNameMap = [];
@@ -843,8 +1003,11 @@ async function bundler(point) {
843
1003
  let removedStatements = [];
844
1004
  const duplicate = async (reName) => {
845
1005
  if (reName) {
1006
+ // order is important here
846
1007
  const re_name = resolves([
1008
+ // collector
847
1009
  [bundleCreator, duplicateCollectionVisitor, compilerOptions, namesMap],
1010
+ // update
848
1011
  [
849
1012
  bundleCreator,
850
1013
  duplicateUpdateVisitor,
@@ -852,6 +1015,7 @@ async function bundler(point) {
852
1015
  namesMap,
853
1016
  callNameMap,
854
1017
  ],
1018
+ // call exp
855
1019
  [
856
1020
  bundleCreator,
857
1021
  duplicateCallExpressionVisitor,
@@ -859,6 +1023,7 @@ async function bundler(point) {
859
1023
  callNameMap,
860
1024
  importNameMap,
861
1025
  ],
1026
+ // export exp
862
1027
  [
863
1028
  bundleCreator,
864
1029
  duplicateExportExpressionVisitor,
@@ -866,6 +1031,7 @@ async function bundler(point) {
866
1031
  importNameMap,
867
1032
  exportNameMap,
868
1033
  ],
1034
+ // import exp
869
1035
  [
870
1036
  bundleCreator,
871
1037
  duplicateImportExpressionVisitor,
@@ -873,6 +1039,7 @@ async function bundler(point) {
873
1039
  exportNameMap,
874
1040
  importNameMap,
875
1041
  ],
1042
+ // export exp again
876
1043
  [
877
1044
  bundleCreator,
878
1045
  duplicateExportExpressionVisitor,
@@ -880,6 +1047,7 @@ async function bundler(point) {
880
1047
  importNameMap,
881
1048
  exportNameMap,
882
1049
  ],
1050
+ // export exp again
883
1051
  [
884
1052
  bundleCreator,
885
1053
  duplicateExportExpressionVisitor,
@@ -887,7 +1055,7 @@ async function bundler(point) {
887
1055
  importNameMap,
888
1056
  exportNameMap,
889
1057
  ],
890
- ]);
1058
+ ]); // re_name
891
1059
  const re_name_call = await re_name.concurrent();
892
1060
  for (const call of re_name_call) {
893
1061
  await utilities.wait(500);
@@ -897,6 +1065,7 @@ async function bundler(point) {
897
1065
  else {
898
1066
  let _err = false;
899
1067
  const un_rename = resolves([
1068
+ // collector
900
1069
  [bundleCreator, duplicateCollectionVisitor, compilerOptions, namesMap],
901
1070
  ]);
902
1071
  const un_rename_call = await un_rename.concurrent();
@@ -906,6 +1075,7 @@ async function bundler(point) {
906
1075
  if (files.size > 1) {
907
1076
  _err = true;
908
1077
  console.warn(`Name -> ${name} declared in multiple files :`);
1078
+ // biome-ignore lint/suspicious/useIterableCallbackReturn : just log warn
909
1079
  files.forEach((f) => console.warn(` - ${f.file}`));
910
1080
  }
911
1081
  });
@@ -915,6 +1085,7 @@ async function bundler(point) {
915
1085
  }
916
1086
  }
917
1087
  };
1088
+ // 1. Call dependency plugins
918
1089
  if (plugins.length) {
919
1090
  for (let plugin of plugins) {
920
1091
  plugin = typeof plugin === "function" ? plugin() : plugin;
@@ -927,9 +1098,11 @@ async function bundler(point) {
927
1098
  }
928
1099
  }
929
1100
  }
930
- }
1101
+ } //--
931
1102
  await utilities.wait(1000);
1103
+ // 2. Handle duplicates
932
1104
  await duplicate(reName);
1105
+ // 3. Handling anonymous imports and exports
933
1106
  const anonymous = resolves([
934
1107
  [
935
1108
  bundleCreator,
@@ -956,21 +1129,28 @@ async function bundler(point) {
956
1129
  depsFiles = depsFiles.map(call);
957
1130
  }
958
1131
  await utilities.wait(1000);
1132
+ // 4. Remove Imports
959
1133
  const removeImports = resolves([
960
1134
  [bundleCreator, removeImportsVisitor, compilerOptions, removedStatements],
961
1135
  ]);
962
1136
  const removeImport = await removeImports.concurrent();
963
1137
  depsFiles = depsFiles.map(removeImport[0]);
964
1138
  await utilities.wait(500);
1139
+ // 5. Remove Exports from dependencies only
965
1140
  const removeExports = resolves([
966
1141
  [bundleCreator, removeExportsVisitor, compilerOptions],
967
1142
  ]);
968
1143
  const removeExport = await removeExports.concurrent();
1144
+ // not remove exports from entry file
969
1145
  const deps_files = depsFiles.slice(0, -1).map(removeExport[0]);
970
1146
  const mainFile = depsFiles.slice(-1);
1147
+ // 6. Handle imported statements
1148
+ // filter removed statements , that not from local like `./` or `../`
971
1149
  const regexp = /["']((?!\.\/|\.\.\/)[^"']+)["']/;
972
1150
  removedStatements = removedStatements.filter((i) => regexp.test(i));
973
1151
  removedStatements = mergeImportsStatement(removedStatements);
1152
+ // 7. Create final content
1153
+ // make sure all imports are at the top of file
974
1154
  const importStatements = removedStatements.join("\n").trim();
975
1155
  const depFilesContent = deps_files
976
1156
  .map((i) => {
@@ -987,7 +1167,9 @@ async function bundler(point) {
987
1167
  .join("\n")
988
1168
  .trim();
989
1169
  await utilities.wait(1000);
1170
+ // text join order is important here
990
1171
  let content = `${importStatements}\n${depFilesContent}\n${mainFileContent}`;
1172
+ // 8. Call pre-process plugins
991
1173
  if (plugins.length) {
992
1174
  for (let plugin of plugins) {
993
1175
  plugin = typeof plugin === "function" ? plugin() : plugin;
@@ -1000,7 +1182,8 @@ async function bundler(point) {
1000
1182
  }
1001
1183
  }
1002
1184
  }
1003
- }
1185
+ } //--
1186
+ // 9. Returns
1004
1187
  return { bundledContent: content, ...point };
1005
1188
  }
1006
1189
  async function bundle(object) {
@@ -1014,6 +1197,16 @@ async function bundle(object) {
1014
1197
  allowUpdatePackageJson: object.allowUpdatePackageJson,
1015
1198
  };
1016
1199
  }
1200
+ //src/lib/compile/host.ts
1201
+ /**
1202
+ * Creates a ts.CompilerHost that can be used with the typescript compiler.
1203
+ * This host is designed to be used with in-memory compilation and will
1204
+ * return the source file for the given fileName and will write all output
1205
+ * files to the createdFiles object.
1206
+ * @param {string} sourceCode - the source code to compile
1207
+ * @param {string} fileName - the name of the file to compile
1208
+ * @returns {{createdFiles: Record<string, string>, host: ts.CompilerHost}}
1209
+ */
1017
1210
  function createHost(sourceCode, fileName) {
1018
1211
  const createdFiles = {};
1019
1212
  const host = {
@@ -1037,19 +1230,31 @@ function createHost(sourceCode, fileName) {
1037
1230
  };
1038
1231
  return { createdFiles, host };
1039
1232
  }
1233
+ //src/lib/compile/package.ts
1040
1234
  const isCjs = (files) => files.commonjs && files.commonjsTypes;
1041
1235
  const isEsm = (files) => files.esm && files.esmTypes;
1236
+ /**
1237
+ * Builds a package exports mapping for the given output files and export path.
1238
+ *
1239
+ * Produces the appropriate export shape based on whether CommonJS and/or ESM
1240
+ * artifacts are present, including their default entry points and type
1241
+ * definitions. If neither format is available, returns an empty object.
1242
+ *
1243
+ * @param files - The build output file paths for CommonJS/ESM and their types.
1244
+ * @param exportPath - The subpath export key (e.g. "." or "./feature").
1245
+ * @returns A {@link Exports} object describing the package exports map.
1246
+ */
1042
1247
  function getExports(files, exportPath) {
1043
1248
  return isCjs(files) && isEsm(files)
1044
1249
  ? {
1045
1250
  [exportPath]: {
1046
1251
  import: {
1047
- default: `./${path.relative(process.cwd(), files.esm)}`,
1048
1252
  types: `./${path.relative(process.cwd(), files.esmTypes)}`,
1253
+ default: `./${path.relative(process.cwd(), files.esm)}`,
1049
1254
  },
1050
1255
  require: {
1051
- default: `./${path.relative(process.cwd(), files.commonjs)}`,
1052
1256
  types: `./${path.relative(process.cwd(), files.commonjsTypes)}`,
1257
+ default: `./${path.relative(process.cwd(), files.commonjs)}`,
1053
1258
  },
1054
1259
  },
1055
1260
  }
@@ -1057,8 +1262,8 @@ function getExports(files, exportPath) {
1057
1262
  ? {
1058
1263
  [exportPath]: {
1059
1264
  require: {
1060
- default: `./${path.relative(process.cwd(), files.commonjs)}`,
1061
1265
  types: `./${path.relative(process.cwd(), files.commonjsTypes)}`,
1266
+ default: `./${path.relative(process.cwd(), files.commonjs)}`,
1062
1267
  },
1063
1268
  },
1064
1269
  }
@@ -1066,13 +1271,23 @@ function getExports(files, exportPath) {
1066
1271
  ? {
1067
1272
  [exportPath]: {
1068
1273
  import: {
1069
- default: `./${path.relative(process.cwd(), files.esm)}`,
1070
1274
  types: `./${path.relative(process.cwd(), files.esmTypes)}`,
1275
+ default: `./${path.relative(process.cwd(), files.esm)}`,
1071
1276
  },
1072
1277
  },
1073
1278
  }
1074
1279
  : {};
1075
1280
  }
1281
+ /**
1282
+ * Writes an updated `package.json` based on output files and export path.
1283
+ *
1284
+ * Determines module type (ESM/CommonJS), adjusts `main`, `module`, `types`,
1285
+ * and `exports` fields, and preserves other existing fields from the
1286
+ * current `package.json`.
1287
+ *
1288
+ * @param files - The generated output files used to populate entry points.
1289
+ * @param exportPath - The export path for subpath exports; "." denotes main export.
1290
+ */
1076
1291
  async function writePackage(files, exportPath) {
1077
1292
  let isMain = true;
1078
1293
  if (exportPath !== ".") {
@@ -1125,6 +1340,7 @@ async function writePackage(files, exportPath) {
1125
1340
  };
1126
1341
  utilities.writeCompileFile(pkgFile, JSON.stringify(pkgJson, null, 2));
1127
1342
  }
1343
+ //src/lib/compile/index.ts
1128
1344
  function splitCamelCase(str) {
1129
1345
  const splitString = str
1130
1346
  .replace(/([a-z])([A-Z])/g, "$1 $2")
@@ -1153,17 +1369,20 @@ class Compiler {
1153
1369
  const isMain = point.exportPath === ".";
1154
1370
  const _name = isMain ? "Main" : splitCamelCase(point.exportPath.slice(2));
1155
1371
  console.time(tcolor.cyan(`Compiled commonjs for ${_name} export path`));
1372
+ // init
1156
1373
  const fileName = point.fileName;
1157
1374
  const sourceCode = point.bundledContent;
1158
1375
  const format = point.format;
1159
1376
  const plugins = point.plugins;
1160
1377
  const compilerOptions = point.tsOptions.cjs;
1378
+ // create host
1161
1379
  const _host = createHost(sourceCode, fileName);
1162
1380
  const createdFiles = _host.createdFiles;
1163
1381
  const host = _host.host;
1164
1382
  const program = ts.createProgram([fileName], compilerOptions, host);
1165
1383
  program.emit();
1166
1384
  Object.entries(createdFiles).map(async ([outName, content]) => {
1385
+ // ------------------------------------
1167
1386
  if (plugins.length) {
1168
1387
  for (let plugin of plugins) {
1169
1388
  plugin = typeof plugin === "function" ? plugin() : plugin;
@@ -1206,11 +1425,13 @@ class Compiler {
1206
1425
  const isMain = point.exportPath === ".";
1207
1426
  const _name = isMain ? "Main" : splitCamelCase(point.exportPath.slice(2));
1208
1427
  console.time(tcolor.cyan(`Compiled esm for ${_name} export path`));
1428
+ // init
1209
1429
  const fileName = point.fileName;
1210
1430
  const sourceCode = point.bundledContent;
1211
1431
  const format = point.format;
1212
1432
  const plugins = point.plugins;
1213
1433
  const compilerOptions = point.tsOptions.esm;
1434
+ // create host
1214
1435
  const _host = createHost(sourceCode, fileName);
1215
1436
  const createdFiles = _host.createdFiles;
1216
1437
  const host = _host.host;
@@ -1230,6 +1451,7 @@ class Compiler {
1230
1451
  }
1231
1452
  }
1232
1453
  }
1454
+ // ------------------------------------------
1233
1455
  if (this._isUpdate()) {
1234
1456
  if (outName.match(/.js/g)) {
1235
1457
  this.files.esm = outName.replace(/.js/g, ".mjs");
@@ -1252,6 +1474,14 @@ class Compiler {
1252
1474
  });
1253
1475
  console.timeEnd(tcolor.cyan(`Compiled esm for ${_name} export path`));
1254
1476
  }
1477
+ /**
1478
+ * Compile bundled code for each entry point.
1479
+ * This function will iterate through each entry point and compile code according to the format specified.
1480
+ * If the format is "commonjs", it will compile the code into commonjs format.
1481
+ * If the format is "esm", it will compile the code into esm format.
1482
+ * If the format is "both", it will compile the code into both commonjs and esm formats.
1483
+ * If the allowUpdatePackageJson flag is set to true, it will update the package.json according to the compiled file paths.
1484
+ */
1255
1485
  async compile() {
1256
1486
  for (const point of this.object.points) {
1257
1487
  await utilities.wait(500);
@@ -1281,13 +1511,23 @@ class Compiler {
1281
1511
  }
1282
1512
  }
1283
1513
  }
1514
+ //src/lib/init/checks.ts
1284
1515
  var checks;
1285
1516
  (function (checks) {
1517
+ /**
1518
+ * Checks the given dependencies for type errors. If any type errors are found,
1519
+ * an error message is printed to the console and the process exits with a code of 1.
1520
+ * @param dep The dependencies to check for type errors
1521
+ * @param compilerOptions The compiler options to use when checking for type errors
1522
+ * @returns true if no type errors are found, false otherwise
1523
+ */
1286
1524
  function typesCheck(dep, compilerOptions) {
1287
1525
  if (!compilerOptions.noCheck) {
1288
1526
  const filePaths = dep.map((i) => i.file);
1289
1527
  let _err = false;
1528
+ // Create program
1290
1529
  const program = ts.createProgram(filePaths, compilerOptions);
1530
+ // Check each file individually for immediate feedback
1291
1531
  for (const filePath of filePaths) {
1292
1532
  const sourceFile = program.getSourceFile(filePath);
1293
1533
  if (!sourceFile) {
@@ -1317,16 +1557,24 @@ var checks;
1317
1557
  }
1318
1558
  }
1319
1559
  }
1560
+ /**
1561
+ * Check the module type of the given dependencies.
1562
+ * @param _dep The dependencies to check for module type
1563
+ * @returns true if all dependencies are ESM, false otherwise
1564
+ */
1320
1565
  function moduleType(_dep) {
1321
1566
  let _esmCount = 0;
1322
1567
  let cjsCount = 0;
1323
1568
  let unknownCount = 0;
1324
1569
  for (const dep of _dep) {
1325
1570
  try {
1571
+ // Create a TypeScript source file
1326
1572
  const sourceFile = ts.createSourceFile(dep.file, dep.content, ts.ScriptTarget.Latest, true);
1327
1573
  let hasESMImports = false;
1328
1574
  let hasCommonJS = false;
1575
+ // Walk through the AST to detect module syntax
1329
1576
  function walk(node) {
1577
+ // Check for ESM import/export syntax
1330
1578
  if (ts.isImportDeclaration(node) ||
1331
1579
  ts.isImportEqualsDeclaration(node) ||
1332
1580
  ts.isExportDeclaration(node) ||
@@ -1334,6 +1582,7 @@ var checks;
1334
1582
  ts.isExportAssignment(node)) {
1335
1583
  hasESMImports = true;
1336
1584
  }
1585
+ // Check for export modifier on declarations
1337
1586
  if ((ts.isVariableStatement(node) ||
1338
1587
  ts.isFunctionDeclaration(node) ||
1339
1588
  ts.isInterfaceDeclaration(node) ||
@@ -1343,6 +1592,7 @@ var checks;
1343
1592
  node.modifiers?.some((mod) => mod.kind === ts.SyntaxKind.ExportKeyword)) {
1344
1593
  hasESMImports = true;
1345
1594
  }
1595
+ // Check for CommonJS require/exports
1346
1596
  if (ts.isCallExpression(node)) {
1347
1597
  if (ts.isIdentifier(node.expression) &&
1348
1598
  node.expression.text === "require" &&
@@ -1350,6 +1600,7 @@ var checks;
1350
1600
  hasCommonJS = true;
1351
1601
  }
1352
1602
  }
1603
+ // Check for module.exports or exports.xxx
1353
1604
  if (ts.isPropertyAccessExpression(node)) {
1354
1605
  const text = node.getText(sourceFile);
1355
1606
  if (text.startsWith("module.exports") ||
@@ -1357,9 +1608,11 @@ var checks;
1357
1608
  hasCommonJS = true;
1358
1609
  }
1359
1610
  }
1611
+ // Continue walking the AST
1360
1612
  ts.forEachChild(node, walk);
1361
1613
  }
1362
1614
  walk(sourceFile);
1615
+ // Determine the module format based on what we found
1363
1616
  if (hasESMImports && !hasCommonJS) {
1364
1617
  _esmCount++;
1365
1618
  }
@@ -1367,6 +1620,7 @@ var checks;
1367
1620
  cjsCount++;
1368
1621
  }
1369
1622
  else if (hasESMImports && hasCommonJS) {
1623
+ // Mixed - probably ESM with dynamic imports or similar
1370
1624
  _esmCount++;
1371
1625
  }
1372
1626
  }
@@ -1407,6 +1661,8 @@ var checks;
1407
1661
  }
1408
1662
  checks.init = init;
1409
1663
  })(checks || (checks = {}));
1664
+ //src/lib/init/config.ts
1665
+ // -------------
1410
1666
  const getConfigPath = () => {
1411
1667
  const fileNames = ["susee.config.ts", "susee.config.js", "susee.config.mjs"];
1412
1668
  let configFile;
@@ -1419,6 +1675,7 @@ const getConfigPath = () => {
1419
1675
  }
1420
1676
  return configFile;
1421
1677
  };
1678
+ //---------
1422
1679
  function checkEntries(entries) {
1423
1680
  if (entries.length < 1) {
1424
1681
  console.error(tcolor.magenta(`No entry found in susee.config file, at least one entry required`));
@@ -1446,6 +1703,11 @@ function checkEntries(entries) {
1446
1703
  }
1447
1704
  }
1448
1705
  }
1706
+ /**
1707
+ * Get SuSee configuration from susee.config file (susee.config.ts, susee.config.js, susee.config.mjs)
1708
+ * @returns {Promise<ConfigReturns>} - SuSee configuration
1709
+ * @throws {Error} - when no susee.config file found
1710
+ */
1449
1711
  async function getConfig() {
1450
1712
  const configPath = getConfigPath();
1451
1713
  if (configPath === undefined) {
@@ -1465,6 +1727,7 @@ async function getConfig() {
1465
1727
  format: ent.format ?? "esm",
1466
1728
  tsconfigFilePath: ent.tsconfigFilePath ?? undefined,
1467
1729
  renameDuplicates: ent.renameDuplicates ?? true,
1730
+ // TODO check for defined out dir here or in config.ts
1468
1731
  outDir: config.outDir ?? "dist",
1469
1732
  };
1470
1733
  points.push(point);
@@ -1475,10 +1738,12 @@ async function getConfig() {
1475
1738
  allowUpdatePackageJson: config.allowUpdatePackageJson ?? true,
1476
1739
  };
1477
1740
  }
1741
+ //src/lib/init/deps.ts
1742
+ //---------------
1478
1743
  async function fileSizes(path) {
1479
1744
  const s = await fs.promises.stat(path);
1480
- const logical = s.size;
1481
- const allocated = s.blocks !== null ? s.blocks * 512 : null;
1745
+ const logical = s.size; // bytes in file
1746
+ const allocated = s.blocks !== null ? s.blocks * 512 : null; // bytes actually allocated (POSIX)
1482
1747
  return { logical, allocated };
1483
1748
  }
1484
1749
  const checkExport = (str, file) => {
@@ -1492,9 +1757,28 @@ const checkExport = (str, file) => {
1492
1757
  return false;
1493
1758
  }
1494
1759
  };
1760
+ /**
1761
+ * Generate dependencies graph for given entry file.
1762
+ *
1763
+ * This function will return an array of dependencies file objects.
1764
+ * Each object will contain the following properties:
1765
+ * - file: path to the file
1766
+ * - content: content of the file
1767
+ * - length: length of the content in bytes
1768
+ * - includeDefExport: whether the file includes export default or export = statement
1769
+ * - size: an object containing the following properties:
1770
+ * - logical: size of the file in bytes
1771
+ * - allocated: size of the file in bytes on disk
1772
+ * - utf8: size of the file in bytes when encoded in utf8
1773
+ * - buffBytes: size of the file in bytes when encoded in buffer
1774
+ *
1775
+ * @param {string} entryFile - path to the entry file
1776
+ * @param {SuseePlugins} plugins - array of plugins
1777
+ * @returns {Promise<DepsFiles>}
1778
+ */
1495
1779
  async function generateDependencies(entryFile, plugins) {
1496
1780
  const deps = await dependencies(entryFile);
1497
- const sorted = deps.sort();
1781
+ const sorted = deps.sort(); // get dependencies graph
1498
1782
  let depsFiles = [];
1499
1783
  await utilities.wait(1000);
1500
1784
  for (const dep of sorted) {
@@ -1517,6 +1801,7 @@ async function generateDependencies(entryFile, plugins) {
1517
1801
  };
1518
1802
  depsFiles.push(_files);
1519
1803
  }
1804
+ // call dependency plugins
1520
1805
  if (plugins.length) {
1521
1806
  for (const plugin of plugins) {
1522
1807
  const _plug = typeof plugin === "function" ? plugin() : plugin;
@@ -1533,6 +1818,7 @@ async function generateDependencies(entryFile, plugins) {
1533
1818
  }
1534
1819
  return depsFiles;
1535
1820
  }
1821
+ //src/lib/init/tsCompilerOptions.ts
1536
1822
  class GetOptions {
1537
1823
  constructor(point) {
1538
1824
  this._point = point;
@@ -1554,6 +1840,7 @@ class GetOptions {
1554
1840
  __init2() {
1555
1841
  this.__init();
1556
1842
  let { types, lib, ...restOptions } = this._options;
1843
+ // normalize types into an array
1557
1844
  if (types) {
1558
1845
  if (!types.includes("node")) {
1559
1846
  types = ["node", ...types];
@@ -1584,9 +1871,27 @@ class GetOptions {
1584
1871
  return this.__init2();
1585
1872
  }
1586
1873
  }
1874
+ /**
1875
+ * Returns an instance of GetOptions, which provides various methods
1876
+ * to generate different sets of compiler options based on the
1877
+ * given Point.
1878
+ *
1879
+ * @param {Point} point - The point to generate compiler options for.
1880
+ * @returns {GetOptions}
1881
+ */
1587
1882
  function getOptions(point) {
1588
1883
  return new GetOptions(point);
1589
1884
  }
1885
+ //src/lib/init/index.ts
1886
+ /**
1887
+ * This function takes a susee configuration object and returns a promise that resolves with a `CollatedReturn` object.
1888
+ * The function iterates over the `points` array in the susee configuration object.
1889
+ * For each point, it generates the dependencies using the `generateDependencies` function.
1890
+ * It then checks if the dependencies are valid using the `checks.init` function.
1891
+ * If the dependencies are invalid, it exits the process with code 1.
1892
+ * If the dependencies are valid, it constructs a `CollatedPoint` object and adds it to the result array.
1893
+ * Finally, it returns a `CollatedReturn` object with the result array and the `allowUpdatePackageJson` flag.
1894
+ */
1590
1895
  async function collections() {
1591
1896
  const __config = await getConfig();
1592
1897
  const points = __config.points;
@@ -1619,6 +1924,21 @@ async function collections() {
1619
1924
  allowUpdatePackageJson: __config.allowUpdatePackageJson,
1620
1925
  };
1621
1926
  }
1927
+ //src/index.ts
1928
+ /**
1929
+ * Bundles a TypeScript project into a single file.
1930
+ * The function takes a {@link SuSeeConfig} object as input and returns a promise resolves with a bundled result.
1931
+ * The function applies the following steps:
1932
+ * 1. Call dependency plugins.
1933
+ * 2. Handle duplicates.
1934
+ * 3. Handling anonymous imports and exports.
1935
+ * 4. Remove Imports.
1936
+ * 5. Remove Exports from dependencies only.
1937
+ * 6. Handle imported statements.
1938
+ * 7. Create final content.
1939
+ * 8. Call pre-process plugins.
1940
+ * 9. Returns.
1941
+ */
1622
1942
  async function susee() {
1623
1943
  console.info(`${tcolor.green("Start")} : ${tcolor.cyan("bundling")}`);
1624
1944
  const collected = await collections();