@reliverse/dler 2.0.0 → 2.0.2

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.
Files changed (135) hide show
  1. package/dist/cli.d.ts +2 -0
  2. package/dist/cli.js +3 -0
  3. package/dist/cmds/build/cmd.d.ts +2 -0
  4. package/dist/cmds/build/cmd.js +564 -0
  5. package/dist/cmds/clean/cmd.d.ts +2 -0
  6. package/dist/cmds/clean/cmd.js +146 -0
  7. package/dist/cmds/clean/impl.d.ts +2 -0
  8. package/dist/cmds/clean/impl.js +627 -0
  9. package/dist/cmds/clean/presets.d.ts +10 -0
  10. package/dist/cmds/clean/presets.js +112 -0
  11. package/dist/cmds/clean/types.d.ts +62 -0
  12. package/dist/cmds/clean/types.js +0 -0
  13. package/dist/cmds/init/cmd.d.ts +3 -0
  14. package/dist/cmds/init/cmd.js +56 -0
  15. package/dist/cmds/init/impl/config.d.ts +45 -0
  16. package/dist/cmds/init/impl/config.js +99 -0
  17. package/dist/cmds/init/impl/generators.d.ts +6 -0
  18. package/dist/cmds/init/impl/generators.js +178 -0
  19. package/dist/cmds/init/impl/prompts.d.ts +2 -0
  20. package/dist/cmds/init/impl/prompts.js +98 -0
  21. package/dist/cmds/init/impl/types.d.ts +22 -0
  22. package/dist/cmds/init/impl/types.js +0 -0
  23. package/dist/cmds/init/impl/utils.d.ts +4 -0
  24. package/dist/cmds/init/impl/utils.js +11 -0
  25. package/dist/cmds/init/impl/validators.d.ts +4 -0
  26. package/dist/cmds/init/impl/validators.js +42 -0
  27. package/dist/cmds/integrate/cmd.d.ts +3 -0
  28. package/dist/cmds/integrate/cmd.js +70 -0
  29. package/dist/cmds/integrate/impl.d.ts +7 -0
  30. package/dist/cmds/integrate/impl.js +127 -0
  31. package/dist/cmds/integrate/integrations/base.d.ts +13 -0
  32. package/dist/cmds/integrate/integrations/base.js +41 -0
  33. package/dist/cmds/integrate/integrations/nextjs.d.ts +16 -0
  34. package/dist/cmds/integrate/integrations/nextjs.js +167 -0
  35. package/dist/cmds/integrate/integrations/registry.d.ts +7 -0
  36. package/dist/cmds/integrate/integrations/registry.js +31 -0
  37. package/dist/cmds/integrate/integrations/ultracite.d.ts +11 -0
  38. package/dist/cmds/integrate/integrations/ultracite.js +40 -0
  39. package/dist/cmds/integrate/types.d.ts +39 -0
  40. package/dist/cmds/integrate/types.js +0 -0
  41. package/dist/cmds/integrate/utils/biome.d.ts +4 -0
  42. package/dist/cmds/integrate/utils/biome.js +140 -0
  43. package/dist/cmds/integrate/utils/context.d.ts +3 -0
  44. package/dist/cmds/integrate/utils/context.js +111 -0
  45. package/dist/cmds/integrate/utils/temp.d.ts +3 -0
  46. package/dist/cmds/integrate/utils/temp.js +36 -0
  47. package/dist/cmds/perf/analysis/bundle.d.ts +20 -0
  48. package/dist/cmds/perf/analysis/bundle.js +225 -0
  49. package/dist/cmds/perf/analysis/filesystem.d.ts +27 -0
  50. package/dist/cmds/perf/analysis/filesystem.js +246 -0
  51. package/dist/cmds/perf/analysis/monorepo.d.ts +29 -0
  52. package/dist/cmds/perf/analysis/monorepo.js +307 -0
  53. package/dist/cmds/perf/benchmarks/command.d.ts +21 -0
  54. package/dist/cmds/perf/benchmarks/command.js +162 -0
  55. package/dist/cmds/perf/benchmarks/memory.d.ts +41 -0
  56. package/dist/cmds/perf/benchmarks/memory.js +169 -0
  57. package/dist/cmds/perf/benchmarks/runner.d.ts +22 -0
  58. package/dist/cmds/perf/benchmarks/runner.js +157 -0
  59. package/dist/cmds/perf/cmd.d.ts +2 -0
  60. package/dist/cmds/perf/cmd.js +238 -0
  61. package/dist/cmds/perf/impl.d.ts +24 -0
  62. package/dist/cmds/perf/impl.js +304 -0
  63. package/dist/cmds/perf/reporters/console.d.ts +12 -0
  64. package/dist/cmds/perf/reporters/console.js +257 -0
  65. package/dist/cmds/perf/reporters/html.d.ts +27 -0
  66. package/dist/cmds/perf/reporters/html.js +881 -0
  67. package/dist/cmds/perf/reporters/json.d.ts +9 -0
  68. package/dist/cmds/perf/reporters/json.js +32 -0
  69. package/dist/cmds/perf/types.d.ts +184 -0
  70. package/dist/cmds/perf/types.js +0 -0
  71. package/dist/cmds/perf/utils/cache.d.ts +23 -0
  72. package/dist/cmds/perf/utils/cache.js +171 -0
  73. package/dist/cmds/perf/utils/formatter.d.ts +17 -0
  74. package/dist/cmds/perf/utils/formatter.js +134 -0
  75. package/dist/cmds/perf/utils/stats.d.ts +15 -0
  76. package/dist/cmds/perf/utils/stats.js +101 -0
  77. package/dist/cmds/publish/cmd.d.ts +3 -0
  78. package/dist/cmds/publish/cmd.js +189 -0
  79. package/dist/cmds/shell/cmd.d.ts +3 -0
  80. package/dist/cmds/shell/cmd.js +50 -0
  81. package/dist/cmds/tsc/cache.d.ts +27 -0
  82. package/dist/cmds/tsc/cache.js +160 -0
  83. package/dist/cmds/tsc/cmd.d.ts +2 -0
  84. package/dist/cmds/tsc/cmd.js +111 -0
  85. package/dist/cmds/tsc/impl.d.ts +41 -0
  86. package/dist/cmds/tsc/impl.js +572 -0
  87. package/dist/cmds/tsc/types.d.ts +57 -0
  88. package/dist/cmds/tsc/types.js +0 -0
  89. package/package.json +4 -11
  90. package/src/cli.ts +8 -0
  91. package/src/cmds/build/cmd.ts +582 -0
  92. package/src/cmds/clean/cmd.ts +166 -0
  93. package/src/cmds/clean/impl.ts +900 -0
  94. package/src/cmds/clean/presets.ts +158 -0
  95. package/src/cmds/clean/types.ts +71 -0
  96. package/src/cmds/init/cmd.ts +68 -0
  97. package/src/cmds/init/impl/config.ts +105 -0
  98. package/src/cmds/init/impl/generators.ts +220 -0
  99. package/src/cmds/init/impl/prompts.ts +137 -0
  100. package/src/cmds/init/impl/types.ts +25 -0
  101. package/src/cmds/init/impl/utils.ts +17 -0
  102. package/src/cmds/init/impl/validators.ts +55 -0
  103. package/src/cmds/integrate/cmd.ts +82 -0
  104. package/src/cmds/integrate/impl.ts +204 -0
  105. package/src/cmds/integrate/integrations/base.ts +69 -0
  106. package/src/cmds/integrate/integrations/nextjs.ts +227 -0
  107. package/src/cmds/integrate/integrations/registry.ts +45 -0
  108. package/src/cmds/integrate/integrations/ultracite.ts +53 -0
  109. package/src/cmds/integrate/types.ts +48 -0
  110. package/src/cmds/integrate/utils/biome.ts +173 -0
  111. package/src/cmds/integrate/utils/context.ts +148 -0
  112. package/src/cmds/integrate/utils/temp.ts +47 -0
  113. package/src/cmds/perf/analysis/bundle.ts +311 -0
  114. package/src/cmds/perf/analysis/filesystem.ts +324 -0
  115. package/src/cmds/perf/analysis/monorepo.ts +439 -0
  116. package/src/cmds/perf/benchmarks/command.ts +230 -0
  117. package/src/cmds/perf/benchmarks/memory.ts +249 -0
  118. package/src/cmds/perf/benchmarks/runner.ts +220 -0
  119. package/src/cmds/perf/cmd.ts +285 -0
  120. package/src/cmds/perf/impl.ts +411 -0
  121. package/src/cmds/perf/reporters/console.ts +331 -0
  122. package/src/cmds/perf/reporters/html.ts +984 -0
  123. package/src/cmds/perf/reporters/json.ts +42 -0
  124. package/src/cmds/perf/types.ts +220 -0
  125. package/src/cmds/perf/utils/cache.ts +234 -0
  126. package/src/cmds/perf/utils/formatter.ts +190 -0
  127. package/src/cmds/perf/utils/stats.ts +153 -0
  128. package/src/cmds/publish/cmd.ts +215 -0
  129. package/src/cmds/shell/cmd.ts +61 -0
  130. package/src/cmds/tsc/cache.ts +237 -0
  131. package/src/cmds/tsc/cmd.ts +139 -0
  132. package/src/cmds/tsc/impl.ts +855 -0
  133. package/src/cmds/tsc/types.ts +66 -0
  134. package/tsconfig.json +9 -0
  135. package/cli.js +0 -1316
@@ -0,0 +1,140 @@
1
+ import { existsSync } from "node:fs";
2
+ import { join, resolve } from "node:path";
3
+ import { writeJsonFile } from "@reliverse/dler-helpers";
4
+ import { logger } from "@reliverse/dler-logger";
5
+ import { hasWorkspaces, readPackageJSON } from "@reliverse/dler-pkg-tsc";
6
+ export const findBiomeConfig = async (startDir) => {
7
+ let currentDir = resolve(startDir);
8
+ let depth = 0;
9
+ const maxDepth = 3;
10
+ while (depth <= maxDepth) {
11
+ const biomePath = join(currentDir, "biome.json");
12
+ if (existsSync(biomePath)) {
13
+ try {
14
+ const content = await Bun.file(biomePath).json();
15
+ return {
16
+ path: biomePath,
17
+ exists: true,
18
+ content
19
+ };
20
+ } catch {
21
+ }
22
+ }
23
+ const parentDir = resolve(currentDir, "..");
24
+ if (parentDir === currentDir) break;
25
+ currentDir = parentDir;
26
+ depth++;
27
+ }
28
+ const monorepoRoot = await findMonorepoRoot(startDir);
29
+ const targetPath = monorepoRoot || startDir;
30
+ return {
31
+ path: join(targetPath, "biome.json"),
32
+ exists: false
33
+ };
34
+ };
35
+ const findMonorepoRoot = async (startDir) => {
36
+ let currentDir = resolve(startDir);
37
+ while (currentDir !== "/") {
38
+ const pkgPath = join(currentDir, "package.json");
39
+ if (existsSync(pkgPath)) {
40
+ const pkg = await readPackageJSON(currentDir);
41
+ if (pkg && hasWorkspaces(pkg)) {
42
+ return currentDir;
43
+ }
44
+ }
45
+ const parentDir = resolve(currentDir, "..");
46
+ if (parentDir === currentDir) break;
47
+ currentDir = parentDir;
48
+ }
49
+ return null;
50
+ };
51
+ export const createBiomeConfig = async (configPath, integrationType) => {
52
+ logger.info(`\u{1F4DD} Creating biome.json at ${configPath}`);
53
+ const baseConfig = {
54
+ $schema: "./node_modules/@biomejs/biome/configuration_schema.json",
55
+ extends: ["ultracite"],
56
+ files: {
57
+ includes: [
58
+ "**",
59
+ "!**/.js",
60
+ "!**/.d.ts",
61
+ "!**/_generated",
62
+ "!**/.next",
63
+ "!**/.react-email",
64
+ "!**/.source",
65
+ "!**/.turbo",
66
+ "!**/.vercel",
67
+ "!**/.wrangler",
68
+ "!**/.zed",
69
+ "!**/dev-dist",
70
+ "!**/dist-*",
71
+ "!**/dist",
72
+ "!**/drizzle/migrations",
73
+ "!**/node_modules"
74
+ ],
75
+ ignoreUnknown: false
76
+ },
77
+ linter: {
78
+ enabled: true,
79
+ rules: {
80
+ recommended: true,
81
+ // Add integration-specific rules if needed
82
+ ...integrationType === "nextjs" && {
83
+ a11y: {
84
+ useHtmlLang: "warn",
85
+ noHeaderScope: "warn"
86
+ }
87
+ }
88
+ }
89
+ },
90
+ formatter: {
91
+ enabled: true,
92
+ indentStyle: "space",
93
+ indentWidth: 2,
94
+ lineWidth: 80
95
+ },
96
+ javascript: {
97
+ globals: ["Bun"],
98
+ formatter: {
99
+ enabled: true,
100
+ lineEnding: "lf",
101
+ jsxQuoteStyle: "double",
102
+ quoteProperties: "asNeeded",
103
+ trailingCommas: "all",
104
+ lineWidth: 80,
105
+ indentWidth: 2,
106
+ indentStyle: "space",
107
+ semicolons: "always",
108
+ arrowParentheses: "always",
109
+ bracketSpacing: true,
110
+ bracketSameLine: false,
111
+ quoteStyle: "double",
112
+ attributePosition: "auto"
113
+ }
114
+ },
115
+ assist: {
116
+ enabled: true,
117
+ actions: {
118
+ source: {
119
+ organizeImports: "on"
120
+ }
121
+ }
122
+ },
123
+ vcs: {
124
+ enabled: false,
125
+ clientKind: "git",
126
+ useIgnoreFile: false
127
+ }
128
+ };
129
+ await writeJsonFile(configPath, baseConfig);
130
+ };
131
+ export const updateBiomeConfig = async (configPath, content) => {
132
+ logger.info(`\u{1F4DD} Updating biome.json at ${configPath}`);
133
+ if (!content.extends || !Array.isArray(content.extends)) {
134
+ content.extends = [];
135
+ }
136
+ if (!content.extends.includes("ultracite")) {
137
+ content.extends.unshift("ultracite");
138
+ }
139
+ await writeJsonFile(configPath, content);
140
+ };
@@ -0,0 +1,3 @@
1
+ import type { PackageInfo, ProjectContext } from "../types.js";
2
+ export declare const detectProjectContext: (cwd?: string) => Promise<ProjectContext>;
3
+ export declare const selectTargetPackage: (packages: PackageInfo[]) => Promise<PackageInfo>;
@@ -0,0 +1,111 @@
1
+ import { existsSync } from "node:fs";
2
+ import { join, resolve } from "node:path";
3
+ import { logger } from "@reliverse/dler-logger";
4
+ import {
5
+ getWorkspacePatterns,
6
+ hasWorkspaces,
7
+ readPackageJSON
8
+ } from "@reliverse/dler-pkg-tsc";
9
+ import { askQuestion } from "@reliverse/dler-prompt";
10
+ export const detectProjectContext = async (cwd) => {
11
+ const startDir = resolve(cwd ?? process.cwd());
12
+ const monorepoRoot = await findMonorepoRoot(startDir);
13
+ if (monorepoRoot) {
14
+ logger.info("\u{1F50D} Detected monorepo project");
15
+ const packages = await getWorkspacePackages(monorepoRoot);
16
+ return {
17
+ type: "monorepo",
18
+ rootPath: monorepoRoot,
19
+ targetPath: monorepoRoot,
20
+ // Will be updated when package is selected
21
+ packages
22
+ };
23
+ }
24
+ logger.info("\u{1F50D} Detected standalone project");
25
+ return {
26
+ type: "single-repo",
27
+ rootPath: startDir,
28
+ targetPath: startDir
29
+ };
30
+ };
31
+ const findMonorepoRoot = async (startDir) => {
32
+ let currentDir = resolve(startDir);
33
+ while (currentDir !== "/") {
34
+ const pkgPath = join(currentDir, "package.json");
35
+ if (existsSync(pkgPath)) {
36
+ const pkg = await readPackageJSON(currentDir);
37
+ if (pkg && hasWorkspaces(pkg)) {
38
+ return currentDir;
39
+ }
40
+ }
41
+ const parentDir = resolve(currentDir, "..");
42
+ if (parentDir === currentDir) break;
43
+ currentDir = parentDir;
44
+ }
45
+ return null;
46
+ };
47
+ const getWorkspacePackages = async (monorepoRoot) => {
48
+ const rootPkg = await readPackageJSON(monorepoRoot);
49
+ if (!rootPkg) {
50
+ throw new Error("\u274C Could not read root package.json");
51
+ }
52
+ const patterns = getWorkspacePatterns(rootPkg);
53
+ if (!patterns.length) {
54
+ throw new Error("\u274C No workspace patterns found in package.json");
55
+ }
56
+ const packages = [];
57
+ const seenPaths = /* @__PURE__ */ new Set();
58
+ for (const pattern of patterns) {
59
+ const glob = new Bun.Glob(pattern);
60
+ const matches = glob.scanSync({ cwd: monorepoRoot, onlyFiles: false });
61
+ for (const match of matches) {
62
+ const packagePath = resolve(monorepoRoot, match);
63
+ if (seenPaths.has(packagePath)) continue;
64
+ seenPaths.add(packagePath);
65
+ const pkgInfo = await resolvePackageInfo(packagePath);
66
+ if (pkgInfo) {
67
+ packages.push(pkgInfo);
68
+ }
69
+ }
70
+ }
71
+ return packages;
72
+ };
73
+ const resolvePackageInfo = async (packagePath) => {
74
+ try {
75
+ const packageJsonPath = join(packagePath, "package.json");
76
+ if (!existsSync(packageJsonPath)) return null;
77
+ const packageJson = await readPackageJSON(packagePath);
78
+ if (!packageJson || !packageJson.name) return null;
79
+ return {
80
+ name: packageJson.name,
81
+ path: packagePath,
82
+ packageJson
83
+ };
84
+ } catch {
85
+ return null;
86
+ }
87
+ };
88
+ export const selectTargetPackage = async (packages) => {
89
+ if (packages.length === 0) {
90
+ throw new Error("\u274C No packages found in workspace");
91
+ }
92
+ if (packages.length === 1) {
93
+ logger.info(`\u{1F4E6} Using package: ${packages[0]?.name}`);
94
+ return packages[0];
95
+ }
96
+ logger.info("\n\u{1F4E6} Available packages:");
97
+ packages.forEach((pkg, index) => {
98
+ logger.log(` ${index + 1}. ${pkg.name}`);
99
+ });
100
+ while (true) {
101
+ const answer = await askQuestion(
102
+ `Select target package (1-${packages.length})`,
103
+ "1"
104
+ );
105
+ const index = parseInt(answer, 10) - 1;
106
+ if (index >= 0 && index < packages.length) {
107
+ return packages[index];
108
+ }
109
+ logger.error("\u274C Invalid selection. Please try again.");
110
+ }
111
+ };
@@ -0,0 +1,3 @@
1
+ import type { TempDirectory } from "../types.js";
2
+ export declare const createTempDirectory: () => Promise<TempDirectory>;
3
+ export declare const createIntegrationTempDir: (tempDir: TempDirectory, integrationName: string) => Promise<string>;
@@ -0,0 +1,36 @@
1
+ import { existsSync, rmSync } from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import { join } from "node:path";
4
+ import { logger } from "@reliverse/dler-logger";
5
+ import { ensureDir } from "../../init/impl/utils.js";
6
+ export const createTempDirectory = async () => {
7
+ const timestamp = Date.now();
8
+ const tempPath = join(
9
+ homedir(),
10
+ ".reliverse",
11
+ "dler",
12
+ "temp",
13
+ "integrate",
14
+ timestamp.toString()
15
+ );
16
+ await ensureDir(tempPath);
17
+ logger.debug(`\u{1F4C1} Created temp directory: ${tempPath}`);
18
+ return {
19
+ path: tempPath,
20
+ cleanup: async () => {
21
+ try {
22
+ if (existsSync(tempPath)) {
23
+ rmSync(tempPath, { recursive: true, force: true });
24
+ logger.debug(`\u{1F9F9} Cleaned up temp directory: ${tempPath}`);
25
+ }
26
+ } catch (error) {
27
+ logger.warn(`\u26A0\uFE0F Failed to clean up temp directory: ${error}`);
28
+ }
29
+ }
30
+ };
31
+ };
32
+ export const createIntegrationTempDir = async (tempDir, integrationName) => {
33
+ const integrationPath = join(tempDir.path, `${integrationName}-temp`);
34
+ await ensureDir(integrationPath);
35
+ return integrationPath;
36
+ };
@@ -0,0 +1,20 @@
1
+ import type { BundleAnalysisResult } from "../types.js";
2
+ export interface BundleAnalysisOptions {
3
+ target: string;
4
+ verbose?: boolean;
5
+ includeSourceMaps?: boolean;
6
+ analyzeDependencies?: boolean;
7
+ }
8
+ export declare class BundleAnalyzer {
9
+ private options;
10
+ constructor(options: BundleAnalysisOptions);
11
+ analyze(): Promise<BundleAnalysisResult>;
12
+ private findBundleFiles;
13
+ private analyzeFile;
14
+ private getFileType;
15
+ private extractModules;
16
+ private findDuplicates;
17
+ private calculateCompressionPotential;
18
+ }
19
+ export declare const analyzeBundle: (options: BundleAnalysisOptions) => Promise<BundleAnalysisResult>;
20
+ export declare const createBundleAnalyzer: (options: BundleAnalysisOptions) => BundleAnalyzer;
@@ -0,0 +1,225 @@
1
+ import { existsSync, readFileSync, statSync } from "node:fs";
2
+ import { extname, join, resolve } from "node:path";
3
+ import { logger } from "@reliverse/dler-logger";
4
+ export class BundleAnalyzer {
5
+ options;
6
+ constructor(options) {
7
+ this.options = options;
8
+ }
9
+ async analyze() {
10
+ const startTime = Date.now();
11
+ const { target, verbose } = this.options;
12
+ if (verbose) {
13
+ logger.info(`\u{1F50D} Analyzing bundle: ${target}`);
14
+ }
15
+ const targetPath = resolve(target);
16
+ if (!existsSync(targetPath)) {
17
+ throw new Error(`Target not found: ${target}`);
18
+ }
19
+ const stat = statSync(targetPath);
20
+ let files = [];
21
+ if (stat.isDirectory()) {
22
+ files = await this.findBundleFiles(targetPath);
23
+ } else {
24
+ files = [targetPath];
25
+ }
26
+ if (files.length === 0) {
27
+ throw new Error(`No bundle files found in: ${target}`);
28
+ }
29
+ if (verbose) {
30
+ logger.info(` Found ${files.length} bundle files`);
31
+ }
32
+ const fileSizes = [];
33
+ const modules = [];
34
+ const duplicates = [];
35
+ for (const file of files) {
36
+ const fileSize = await this.analyzeFile(file);
37
+ fileSizes.push(fileSize);
38
+ if (this.options.analyzeDependencies) {
39
+ const fileModules = await this.extractModules(file);
40
+ modules.push(...fileModules);
41
+ }
42
+ }
43
+ fileSizes.sort((a, b) => b.size - a.size);
44
+ if (this.options.analyzeDependencies) {
45
+ const duplicateMap = this.findDuplicates(modules);
46
+ duplicates.push(...duplicateMap);
47
+ }
48
+ const totalSize = fileSizes.reduce((sum, file) => sum + file.size, 0);
49
+ const fileCount = fileSizes.length;
50
+ const compressionPotential = this.calculateCompressionPotential(files);
51
+ fileSizes.forEach((file) => {
52
+ file.percentage = file.size / totalSize * 100;
53
+ });
54
+ const analysisTime = Date.now() - startTime;
55
+ if (verbose) {
56
+ logger.info(` Analysis completed in ${analysisTime}ms`);
57
+ }
58
+ return {
59
+ target,
60
+ totalSize,
61
+ fileCount,
62
+ largestFiles: fileSizes.slice(0, 10),
63
+ // Top 10
64
+ modules: modules.slice(0, 20),
65
+ // Top 20 modules
66
+ duplicates: duplicates.slice(0, 10),
67
+ // Top 10 duplicates
68
+ compressionPotential,
69
+ analysisTime
70
+ };
71
+ }
72
+ async findBundleFiles(dir) {
73
+ const bundleExtensions = [".js", ".mjs", ".cjs", ".ts", ".jsx", ".tsx"];
74
+ const files = [];
75
+ try {
76
+ const glob = new Bun.Glob("**/*");
77
+ const matches = glob.scanSync({ cwd: dir, onlyFiles: true });
78
+ for (const match of matches) {
79
+ const fullPath = join(dir, match);
80
+ const ext = extname(match);
81
+ if (bundleExtensions.includes(ext)) {
82
+ files.push(fullPath);
83
+ }
84
+ }
85
+ } catch (error) {
86
+ logger.warn(`Error scanning directory ${dir}:`, error);
87
+ }
88
+ return files;
89
+ }
90
+ async analyzeFile(filePath) {
91
+ const stat = statSync(filePath);
92
+ const ext = extname(filePath);
93
+ return {
94
+ path: filePath,
95
+ size: stat.size,
96
+ percentage: 0,
97
+ // Will be calculated later
98
+ type: this.getFileType(ext)
99
+ };
100
+ }
101
+ getFileType(extension) {
102
+ const typeMap = {
103
+ ".js": "JavaScript",
104
+ ".mjs": "ES Module",
105
+ ".cjs": "CommonJS",
106
+ ".ts": "TypeScript",
107
+ ".jsx": "React JSX",
108
+ ".tsx": "React TSX",
109
+ ".json": "JSON",
110
+ ".css": "CSS",
111
+ ".scss": "SCSS",
112
+ ".sass": "Sass",
113
+ ".less": "Less",
114
+ ".html": "HTML",
115
+ ".svg": "SVG",
116
+ ".png": "PNG",
117
+ ".jpg": "JPEG",
118
+ ".jpeg": "JPEG",
119
+ ".gif": "GIF",
120
+ ".webp": "WebP",
121
+ ".woff": "WOFF",
122
+ ".woff2": "WOFF2",
123
+ ".ttf": "TrueType",
124
+ ".eot": "EOT",
125
+ ".map": "Source Map"
126
+ };
127
+ return typeMap[extension] ?? "Unknown";
128
+ }
129
+ async extractModules(filePath) {
130
+ const modules = [];
131
+ try {
132
+ const content = readFileSync(filePath, "utf-8");
133
+ const importRegex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
134
+ const requireRegex = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
135
+ const dynamicImportRegex = /import\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
136
+ const dependencies = /* @__PURE__ */ new Set();
137
+ let match;
138
+ while ((match = importRegex.exec(content)) !== null) {
139
+ dependencies.add(match[1]);
140
+ }
141
+ while ((match = requireRegex.exec(content)) !== null) {
142
+ dependencies.add(match[1]);
143
+ }
144
+ while ((match = dynamicImportRegex.exec(content)) !== null) {
145
+ dependencies.add(match[1]);
146
+ }
147
+ for (const dep of dependencies) {
148
+ const isExternal = !dep.startsWith(".") && !dep.startsWith("/");
149
+ modules.push({
150
+ name: dep,
151
+ size: 0,
152
+ // Would need to resolve actual size
153
+ percentage: 0,
154
+ dependencies: [],
155
+ isExternal
156
+ });
157
+ }
158
+ } catch (error) {
159
+ logger.warn(`Error extracting modules from ${filePath}:`, error);
160
+ }
161
+ return modules;
162
+ }
163
+ findDuplicates(modules) {
164
+ const moduleMap = /* @__PURE__ */ new Map();
165
+ for (const module of modules) {
166
+ const key = module.name;
167
+ const existing = moduleMap.get(key);
168
+ if (existing) {
169
+ existing.count++;
170
+ existing.totalSize += module.size;
171
+ existing.locations.push(module.name);
172
+ } else {
173
+ moduleMap.set(key, {
174
+ count: 1,
175
+ totalSize: module.size,
176
+ locations: [module.name]
177
+ });
178
+ }
179
+ }
180
+ const duplicates = [];
181
+ for (const [name, info] of moduleMap) {
182
+ if (info.count > 1) {
183
+ duplicates.push({
184
+ name,
185
+ count: info.count,
186
+ totalSize: info.totalSize,
187
+ locations: info.locations
188
+ });
189
+ }
190
+ }
191
+ return duplicates.sort((a, b) => b.totalSize - a.totalSize);
192
+ }
193
+ calculateCompressionPotential(files) {
194
+ let totalSize = 0;
195
+ let compressibleSize = 0;
196
+ for (const file of files) {
197
+ const stat = statSync(file);
198
+ const ext = extname(file);
199
+ totalSize += stat.size;
200
+ const compressibleExtensions = [
201
+ ".js",
202
+ ".ts",
203
+ ".jsx",
204
+ ".tsx",
205
+ ".json",
206
+ ".css",
207
+ ".html",
208
+ ".svg"
209
+ ];
210
+ if (compressibleExtensions.includes(ext)) {
211
+ compressibleSize += stat.size;
212
+ }
213
+ }
214
+ if (totalSize === 0) return 0;
215
+ const estimatedCompression = compressibleSize * 0.7;
216
+ return estimatedCompression / totalSize * 100;
217
+ }
218
+ }
219
+ export const analyzeBundle = async (options) => {
220
+ const analyzer = new BundleAnalyzer(options);
221
+ return analyzer.analyze();
222
+ };
223
+ export const createBundleAnalyzer = (options) => {
224
+ return new BundleAnalyzer(options);
225
+ };
@@ -0,0 +1,27 @@
1
+ import type { FileSystemAnalysisResult } from "../types.js";
2
+ export interface FileSystemAnalysisOptions {
3
+ target: string;
4
+ verbose?: boolean;
5
+ maxDepth?: number;
6
+ includeHidden?: boolean;
7
+ excludePatterns?: string[];
8
+ }
9
+ export declare class FileSystemAnalyzer {
10
+ private options;
11
+ private fileCount;
12
+ private totalSize;
13
+ private directoryCount;
14
+ private maxDepth;
15
+ private files;
16
+ private directories;
17
+ private fileTypes;
18
+ constructor(options: FileSystemAnalysisOptions);
19
+ analyze(): Promise<FileSystemAnalysisResult>;
20
+ private analyzeFile;
21
+ private analyzeDirectory;
22
+ private shouldExclude;
23
+ private getFileType;
24
+ private calculateCompressionPotential;
25
+ }
26
+ export declare const analyzeFileSystem: (options: FileSystemAnalysisOptions) => Promise<FileSystemAnalysisResult>;
27
+ export declare const createFileSystemAnalyzer: (options: FileSystemAnalysisOptions) => FileSystemAnalyzer;