@reliverse/dler 2.0.0 → 2.0.1

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,572 @@
1
+ import { existsSync } from "node:fs";
2
+ import { cpus } from "node:os";
3
+ import { join, relative, resolve } from "node:path";
4
+ import { writeErrorLines } from "@reliverse/dler-helpers";
5
+ import { logger } from "@reliverse/dler-logger";
6
+ import pMap from "@reliverse/dler-mapper";
7
+ import { createIgnoreFilter, normalizePatterns } from "@reliverse/dler-matcher";
8
+ import {
9
+ getWorkspacePatterns,
10
+ hasWorkspaces,
11
+ readPackageJSON
12
+ } from "@reliverse/dler-pkg-tsc";
13
+ import clipboard from "clipboardy";
14
+ import { TscCache } from "./cache.js";
15
+ const DEFAULT_CONCURRENCY = Math.max(4, cpus().length);
16
+ const DISCOVERY_CONCURRENCY = 10;
17
+ const TS_ERROR_REGEX = /\([0-9]+,[0-9]+\): (error|warning) TS[0-9]+:/;
18
+ const findMonorepoRoot = async (startDir) => {
19
+ let currentDir = resolve(startDir ?? process.cwd());
20
+ while (currentDir !== "/") {
21
+ const pkgPath = join(currentDir, "package.json");
22
+ if (existsSync(pkgPath)) {
23
+ const pkg = await readPackageJSON(currentDir);
24
+ if (pkg && hasWorkspaces(pkg)) {
25
+ return currentDir;
26
+ }
27
+ }
28
+ const parentDir = resolve(currentDir, "..");
29
+ if (parentDir === currentDir) break;
30
+ currentDir = parentDir;
31
+ }
32
+ return null;
33
+ };
34
+ const resolvePackageInfo = async (packagePath) => {
35
+ const pkgJsonPath = join(packagePath, "package.json");
36
+ const tsConfigPath = join(packagePath, "tsconfig.json");
37
+ if (!existsSync(pkgJsonPath)) {
38
+ return null;
39
+ }
40
+ if (!existsSync(tsConfigPath)) {
41
+ return null;
42
+ }
43
+ try {
44
+ const pkg = await readPackageJSON(packagePath);
45
+ if (!pkg?.name) {
46
+ return null;
47
+ }
48
+ return {
49
+ name: pkg.name,
50
+ path: packagePath,
51
+ hasTsConfig: true
52
+ // We already checked this above
53
+ };
54
+ } catch {
55
+ return null;
56
+ }
57
+ };
58
+ const getWorkspacePackages = async (cwd) => {
59
+ const startTime = Date.now();
60
+ const monorepoRoot = await findMonorepoRoot(cwd);
61
+ if (!monorepoRoot) {
62
+ throw new Error(
63
+ "\u274C No monorepo found. Ensure package.json has 'workspaces' field."
64
+ );
65
+ }
66
+ const rootPkg = await readPackageJSON(monorepoRoot);
67
+ if (!rootPkg) {
68
+ throw new Error("\u274C Could not read root package.json");
69
+ }
70
+ const patterns = getWorkspacePatterns(rootPkg);
71
+ if (!patterns.length) {
72
+ throw new Error("\u274C No workspace patterns found in package.json");
73
+ }
74
+ const allPackagePaths = [];
75
+ const seenPaths = /* @__PURE__ */ new Set();
76
+ for (const pattern of patterns) {
77
+ if (pattern.includes("*")) {
78
+ const glob = new Bun.Glob(pattern);
79
+ const matches = glob.scanSync({ cwd: monorepoRoot, onlyFiles: false });
80
+ for (const match of matches) {
81
+ const packagePath = resolve(monorepoRoot, match);
82
+ if (seenPaths.has(packagePath)) continue;
83
+ seenPaths.add(packagePath);
84
+ allPackagePaths.push(packagePath);
85
+ }
86
+ } else {
87
+ const packagePath = resolve(monorepoRoot, pattern);
88
+ if (seenPaths.has(packagePath)) continue;
89
+ seenPaths.add(packagePath);
90
+ allPackagePaths.push(packagePath);
91
+ }
92
+ }
93
+ const packageResults = await pMap(
94
+ allPackagePaths,
95
+ async (packagePath) => {
96
+ const pkgInfo = await resolvePackageInfo(packagePath);
97
+ return { packagePath, pkgInfo };
98
+ },
99
+ { concurrency: DISCOVERY_CONCURRENCY }
100
+ );
101
+ const packages = packageResults.filter((result) => result.pkgInfo !== null).map((result) => result.pkgInfo);
102
+ const discoveryTime = Date.now() - startTime;
103
+ return {
104
+ packages,
105
+ monorepoRoot,
106
+ discoveryTime,
107
+ cacheHits: 0,
108
+ // Will be updated by cache layer
109
+ cacheMisses: packages.length
110
+ };
111
+ };
112
+ const filterPackages = (packages, ignore) => {
113
+ const alwaysIgnored = ["@reliverse/dler-v1"];
114
+ const combinedIgnore = ignore ? Array.isArray(ignore) ? [...alwaysIgnored, ...ignore] : [...alwaysIgnored, ignore] : alwaysIgnored;
115
+ const ignoreFilter = createIgnoreFilter(combinedIgnore);
116
+ return ignoreFilter(packages);
117
+ };
118
+ const hasProjectReferences = async (packagePath) => {
119
+ try {
120
+ const tsConfigPath = join(packagePath, "tsconfig.json");
121
+ if (!existsSync(tsConfigPath)) return false;
122
+ const content = await Bun.file(tsConfigPath).text();
123
+ const config = JSON.parse(content);
124
+ return !!(config.references && Array.isArray(config.references) && config.references.length > 0);
125
+ } catch {
126
+ return false;
127
+ }
128
+ };
129
+ const runTscCommand = async (packagePath, options = {}) => {
130
+ try {
131
+ const { incremental = true, buildMode = false } = options;
132
+ let args;
133
+ if (buildMode && await hasProjectReferences(packagePath)) {
134
+ args = ["tsc", "--build"];
135
+ if (incremental) {
136
+ args.push("--incremental");
137
+ }
138
+ } else {
139
+ args = ["tsc", "--noEmit"];
140
+ if (incremental) {
141
+ args.push("--incremental");
142
+ const tsBuildInfoPath = join(
143
+ packagePath,
144
+ "node_modules/.cache/dler-tsc",
145
+ `${packagePath.split(/[/\\]/).pop()}.tsbuildinfo`
146
+ );
147
+ args.push("--tsBuildInfoFile", tsBuildInfoPath);
148
+ }
149
+ }
150
+ const proc = Bun.spawn(args, {
151
+ cwd: packagePath,
152
+ stdout: "pipe",
153
+ stderr: "pipe"
154
+ });
155
+ const [stdout, stderr] = await Promise.all([
156
+ new Response(proc.stdout).text(),
157
+ new Response(proc.stderr).text()
158
+ ]);
159
+ const exitCode = await proc.exited;
160
+ return { stdout, stderr, exitCode };
161
+ } catch (error) {
162
+ throw new Error(
163
+ `Failed to spawn tsc: ${error instanceof Error ? error.message : String(error)}`
164
+ );
165
+ }
166
+ };
167
+ const countErrorsAndWarnings = (output) => {
168
+ const lines = output.split("\n");
169
+ let errors = 0;
170
+ let warnings = 0;
171
+ for (const line of lines) {
172
+ if (TS_ERROR_REGEX.test(line)) {
173
+ if (line.includes(": error TS")) {
174
+ errors++;
175
+ } else if (line.includes(": warning TS")) {
176
+ warnings++;
177
+ }
178
+ }
179
+ }
180
+ return { errors, warnings };
181
+ };
182
+ const filterOutputLines = (output, packagePath, monorepoRoot) => {
183
+ const lines = output.split("\n");
184
+ const filtered = [];
185
+ const normalizedPackagePath = resolve(packagePath);
186
+ for (const line of lines) {
187
+ if (!TS_ERROR_REGEX.test(line)) {
188
+ filtered.push(line);
189
+ continue;
190
+ }
191
+ const match = line.match(/^(.+?)\(/);
192
+ if (match && match[1]) {
193
+ const relativePath = match[1];
194
+ const fullPath = resolve(packagePath, relativePath);
195
+ const normalizedFilePath = resolve(fullPath);
196
+ const isCrossPackageError = line.includes("../") || line.includes("..\\");
197
+ if (isCrossPackageError) {
198
+ if (normalizedFilePath.startsWith(normalizedPackagePath)) {
199
+ const relativeToMonorepo = relative(monorepoRoot, normalizedFilePath);
200
+ const updatedLine = line.replace(relativePath, relativeToMonorepo);
201
+ filtered.push(updatedLine);
202
+ }
203
+ } else {
204
+ const relativeToMonorepo = relative(monorepoRoot, normalizedFilePath);
205
+ const updatedLine = line.replace(relativePath, relativeToMonorepo);
206
+ filtered.push(updatedLine);
207
+ }
208
+ } else {
209
+ filtered.push(line);
210
+ }
211
+ }
212
+ return filtered.join("\n");
213
+ };
214
+ const runTscOnPackage = async (pkg, monorepoRoot, options = {}) => {
215
+ const {
216
+ verbose = false,
217
+ cache,
218
+ incremental = true,
219
+ buildMode = false
220
+ } = options;
221
+ const startTime = Date.now();
222
+ if (!pkg.hasTsConfig) {
223
+ if (verbose) {
224
+ logger.info(`\u23ED\uFE0F Skipping ${pkg.name} (no tsconfig.json)`);
225
+ }
226
+ return {
227
+ package: pkg,
228
+ success: true,
229
+ skipped: true,
230
+ cached: false,
231
+ totalErrors: 0,
232
+ totalWarnings: 0,
233
+ filteredErrors: 0,
234
+ filteredWarnings: 0,
235
+ output: "",
236
+ filteredOutput: "",
237
+ executionTime: Date.now() - startTime
238
+ };
239
+ }
240
+ if (cache) {
241
+ const shouldSkip = await cache.shouldSkipPackage(pkg);
242
+ if (shouldSkip) {
243
+ if (verbose) {
244
+ logger.info(`\u26A1 Skipping ${pkg.name} (no changes since last check)`);
245
+ }
246
+ const cachedResult = await cache.getCachedResult(pkg);
247
+ return {
248
+ package: pkg,
249
+ success: !cachedResult?.hasErrors,
250
+ skipped: false,
251
+ cached: true,
252
+ totalErrors: cachedResult?.errorCount ?? 0,
253
+ totalWarnings: cachedResult?.warningCount ?? 0,
254
+ filteredErrors: cachedResult?.errorCount ?? 0,
255
+ filteredWarnings: cachedResult?.warningCount ?? 0,
256
+ output: cachedResult?.output ?? "Cached result",
257
+ filteredOutput: cachedResult?.filteredOutput ?? "Cached result",
258
+ executionTime: Date.now() - startTime
259
+ };
260
+ }
261
+ }
262
+ if (verbose) {
263
+ logger.info(`\u{1F50D} Checking ${pkg.name}...`);
264
+ }
265
+ try {
266
+ const result = await runTscCommand(pkg.path, { incremental, buildMode });
267
+ const output = result.stdout + result.stderr;
268
+ const filteredOutput = filterOutputLines(output, pkg.path, monorepoRoot);
269
+ const totalCounts = countErrorsAndWarnings(output);
270
+ const filteredCounts = countErrorsAndWarnings(filteredOutput);
271
+ if (verbose) {
272
+ const status = filteredCounts.errors === 0 ? "\u2705" : "\u274C";
273
+ logger.log(
274
+ `${status} ${pkg.name}: ${filteredCounts.errors} errors, ${filteredCounts.warnings} warnings`
275
+ );
276
+ }
277
+ const tscResult = {
278
+ package: pkg,
279
+ success: filteredCounts.errors === 0,
280
+ skipped: false,
281
+ cached: false,
282
+ totalErrors: totalCounts.errors,
283
+ totalWarnings: totalCounts.warnings,
284
+ filteredErrors: filteredCounts.errors,
285
+ filteredWarnings: filteredCounts.warnings,
286
+ output,
287
+ filteredOutput,
288
+ executionTime: Date.now() - startTime
289
+ };
290
+ if (cache) {
291
+ await cache.updatePackageCache(pkg, {
292
+ success: tscResult.success,
293
+ errorCount: tscResult.filteredErrors,
294
+ warningCount: tscResult.filteredWarnings,
295
+ output: tscResult.output,
296
+ filteredOutput: tscResult.filteredOutput
297
+ });
298
+ }
299
+ return tscResult;
300
+ } catch (error) {
301
+ logger.error(
302
+ `\u274C ${pkg.name}: Failed to run tsc - ${error instanceof Error ? error.message : String(error)}`
303
+ );
304
+ return {
305
+ package: pkg,
306
+ success: false,
307
+ skipped: false,
308
+ cached: false,
309
+ totalErrors: 1,
310
+ totalWarnings: 0,
311
+ filteredErrors: 1,
312
+ filteredWarnings: 0,
313
+ output: error instanceof Error ? error.message : String(error),
314
+ filteredOutput: error instanceof Error ? error.message : String(error),
315
+ executionTime: Date.now() - startTime
316
+ };
317
+ }
318
+ };
319
+ const collectAllResults = async (packages, monorepoRoot, options = {}, cache) => {
320
+ const {
321
+ concurrency = DEFAULT_CONCURRENCY,
322
+ stopOnError = false,
323
+ verbose = false,
324
+ incremental = true,
325
+ buildMode = false
326
+ } = options;
327
+ if (!verbose) {
328
+ logger.info(`Processing ${packages.length} packages...`);
329
+ }
330
+ try {
331
+ const tscResults = await pMap(
332
+ packages,
333
+ async (pkg, index) => {
334
+ if (!verbose) {
335
+ logger.info(
336
+ `Processing ${pkg.name} (${index + 1}/${packages.length})...`
337
+ );
338
+ }
339
+ return runTscOnPackage(pkg, monorepoRoot, {
340
+ verbose,
341
+ cache,
342
+ incremental,
343
+ buildMode
344
+ });
345
+ },
346
+ {
347
+ concurrency,
348
+ stopOnError
349
+ }
350
+ );
351
+ const failedPackages = tscResults.filter(
352
+ (r) => !r.success && !r.skipped
353
+ ).length;
354
+ const successfulPackages = tscResults.filter((r) => r.success).length;
355
+ const skippedPackages = tscResults.filter((r) => r.skipped).length;
356
+ const totalErrors = tscResults.reduce(
357
+ (sum, r) => sum + r.filteredErrors,
358
+ 0
359
+ );
360
+ const totalWarnings = tscResults.reduce(
361
+ (sum, r) => sum + r.filteredWarnings,
362
+ 0
363
+ );
364
+ return {
365
+ totalPackages: packages.length,
366
+ failedPackages,
367
+ successfulPackages,
368
+ skippedPackages,
369
+ totalErrors,
370
+ totalWarnings,
371
+ hasErrors: failedPackages > 0,
372
+ results: tscResults
373
+ };
374
+ } catch (error) {
375
+ if (error instanceof AggregateError) {
376
+ const tscResults = error.errors.map((err, index) => {
377
+ const pkg = packages[index];
378
+ if (!pkg) {
379
+ throw new Error(`Package at index ${index} not found`);
380
+ }
381
+ if (verbose) {
382
+ logger.error(
383
+ `\u274C ${pkg.name}: Aggregate error - ${err instanceof Error ? err.message : String(err)}`
384
+ );
385
+ }
386
+ return {
387
+ package: pkg,
388
+ success: false,
389
+ skipped: false,
390
+ cached: false,
391
+ totalErrors: 1,
392
+ totalWarnings: 0,
393
+ filteredErrors: 1,
394
+ filteredWarnings: 0,
395
+ output: err instanceof Error ? err.message : String(err),
396
+ filteredOutput: err instanceof Error ? err.message : String(err),
397
+ executionTime: 0
398
+ };
399
+ });
400
+ const failedPackages = tscResults.filter(
401
+ (r) => !r.success && !r.skipped
402
+ ).length;
403
+ const successfulPackages = tscResults.filter((r) => r.success).length;
404
+ const skippedPackages = tscResults.filter((r) => r.skipped).length;
405
+ const totalErrors = tscResults.reduce(
406
+ (sum, r) => sum + r.filteredErrors,
407
+ 0
408
+ );
409
+ const totalWarnings = tscResults.reduce(
410
+ (sum, r) => sum + r.filteredWarnings,
411
+ 0
412
+ );
413
+ return {
414
+ totalPackages: packages.length,
415
+ failedPackages,
416
+ successfulPackages,
417
+ skippedPackages,
418
+ totalErrors,
419
+ totalWarnings,
420
+ hasErrors: failedPackages > 0,
421
+ results: tscResults
422
+ };
423
+ }
424
+ throw error;
425
+ }
426
+ };
427
+ const collectFailedPackageLogs = (summary) => {
428
+ const failed = summary.results.filter((r) => !r.success && !r.skipped);
429
+ if (failed.length === 0) {
430
+ return "";
431
+ }
432
+ const logs = [];
433
+ logs.push(
434
+ "I received the following TypeScript errors (please analyse the related code for each and correct them):"
435
+ );
436
+ logs.push("```");
437
+ logs.push("TypeScript Check (bun dler tsc)");
438
+ logs.push("");
439
+ for (const result of failed) {
440
+ logs.push(`\u{1F4E6} ${result.package.name}`);
441
+ logs.push(
442
+ ` Errors: ${result.filteredErrors}, Warnings: ${result.filteredWarnings}`
443
+ );
444
+ logs.push(" " + "\u2500".repeat(30));
445
+ if (result.filteredOutput.trim()) {
446
+ const lines = result.filteredOutput.trim().split("\n").map((line) => ` ${line}`);
447
+ logs.push(...lines);
448
+ }
449
+ logs.push("```");
450
+ logs.push("");
451
+ logs.push("");
452
+ }
453
+ return logs.join("\n");
454
+ };
455
+ const copyLogsToClipboard = async (summary) => {
456
+ try {
457
+ const logs = collectFailedPackageLogs(summary);
458
+ if (!logs) {
459
+ logger.info("\u2139\uFE0F No failed packages to copy to clipboard");
460
+ return;
461
+ }
462
+ await clipboard.write(logs);
463
+ logger.success("\u{1F4CB} Failed package logs copied to clipboard!");
464
+ } catch (error) {
465
+ logger.error("\u274C Failed to copy logs to clipboard:");
466
+ if (error instanceof Error) {
467
+ logger.error(error.message);
468
+ } else {
469
+ logger.error(String(error));
470
+ }
471
+ }
472
+ };
473
+ const formatOutput = (summary, verbose) => {
474
+ const { totalPackages, failedPackages, successfulPackages, skippedPackages } = summary;
475
+ logger.log("\u2501".repeat(60));
476
+ logger.log(`\u{1F4CA} TypeScript Check Summary:`);
477
+ logger.log(` Total packages: ${totalPackages}`);
478
+ logger.log(` \u2705 Passed: ${successfulPackages}`);
479
+ logger.log(` \u274C Failed: ${failedPackages}`);
480
+ logger.log(` \u23ED\uFE0F Skipped: ${skippedPackages}`);
481
+ logger.log(` \u{1F41B} Total errors: ${summary.totalErrors}`);
482
+ logger.log(` \u26A0\uFE0F Total warnings: ${summary.totalWarnings}`);
483
+ logger.log("\u2501".repeat(60));
484
+ const failed = summary.results.filter((r) => !r.success && !r.skipped);
485
+ if (failed.length > 0) {
486
+ logger.error("\n\u274C Failed Packages:\n");
487
+ for (const result of failed) {
488
+ logger.error(`\u{1F4E6} ${result.package.name}`);
489
+ logger.error(
490
+ ` Errors: ${result.filteredErrors}, Warnings: ${result.filteredWarnings}`
491
+ );
492
+ if (result.filteredOutput.trim()) {
493
+ logger.error(" \u2500".repeat(30));
494
+ const lines = result.filteredOutput.trim().split("\n").map((line) => ` ${line}`);
495
+ writeErrorLines(lines);
496
+ logger.error("");
497
+ }
498
+ }
499
+ }
500
+ if (verbose) {
501
+ const successful = summary.results.filter((r) => r.success && !r.skipped);
502
+ if (successful.length > 0) {
503
+ logger.success("\n\u2705 Successful Packages:\n");
504
+ for (const result of successful) {
505
+ logger.success(` \u2022 ${result.package.name}`);
506
+ }
507
+ }
508
+ const skipped = summary.results.filter((r) => r.skipped);
509
+ if (skipped.length > 0) {
510
+ logger.info("\n\u23ED\uFE0F Skipped Packages (no tsconfig.json):\n");
511
+ for (const result of skipped) {
512
+ logger.info(` \u2022 ${result.package.name}`);
513
+ }
514
+ }
515
+ logger.log("");
516
+ }
517
+ };
518
+ export const runTscOnAllPackages = async (ignore, cwd, options = {}) => {
519
+ const {
520
+ verbose = false,
521
+ copyLogs = false,
522
+ cache: enableCache = true,
523
+ autoConcurrency = false
524
+ } = options;
525
+ return (async () => {
526
+ const cache = enableCache ? new TscCache() : void 0;
527
+ if (cache) {
528
+ await cache.initialize();
529
+ }
530
+ const discoveryResult = await getWorkspacePackages(cwd);
531
+ const { packages: allPackages, discoveryTime } = discoveryResult;
532
+ if (verbose) {
533
+ logger.info(
534
+ ` Found ${allPackages.length} packages (${discoveryTime}ms)`
535
+ );
536
+ logger.info(" Packages found:");
537
+ for (const pkg of allPackages) {
538
+ const configStatus = pkg.hasTsConfig ? "\u2705" : "\u23ED\uFE0F";
539
+ logger.info(` ${configStatus} ${pkg.name} (${pkg.path})`);
540
+ }
541
+ logger.info("");
542
+ }
543
+ const packages = filterPackages(allPackages, ignore);
544
+ const ignoredCount = allPackages.length - packages.length;
545
+ if (ignoredCount > 0) {
546
+ const alwaysIgnored = ["@reliverse/dler-v1"];
547
+ const combinedIgnore = ignore ? Array.isArray(ignore) ? [...alwaysIgnored, ...ignore] : [...alwaysIgnored, ignore] : alwaysIgnored;
548
+ const patterns = normalizePatterns(combinedIgnore);
549
+ logger.info(
550
+ ` Ignoring ${ignoredCount} packages matching: ${patterns.join(", ")}`
551
+ );
552
+ }
553
+ let concurrency = options.concurrency ?? DEFAULT_CONCURRENCY;
554
+ if (autoConcurrency) {
555
+ concurrency = Math.max(4, cpus().length * 2);
556
+ }
557
+ const { stopOnError = false } = options;
558
+ logger.info(
559
+ ` Checking ${packages.length} packages (concurrency: ${concurrency}, stopOnError: ${stopOnError})...
560
+ `
561
+ );
562
+ if (verbose) {
563
+ logger.info("\u{1F680} Starting TypeScript checks...\n");
564
+ }
565
+ const summary = await collectAllResults(packages, discoveryResult.monorepoRoot, options, cache);
566
+ formatOutput(summary, verbose);
567
+ if (copyLogs && summary.hasErrors) {
568
+ await copyLogsToClipboard(summary);
569
+ }
570
+ return summary;
571
+ })();
572
+ };
@@ -0,0 +1,57 @@
1
+ import type { PackageInfo } from "./impl.js";
2
+ export interface CacheMetadata {
3
+ version: string;
4
+ lastUpdated: number;
5
+ packages: Record<string, PackageCacheEntry>;
6
+ }
7
+ export interface PackageCacheEntry {
8
+ lastCheck: number;
9
+ lastSuccess: number | null;
10
+ sourceFiles: SourceFileInfo[];
11
+ hasErrors: boolean;
12
+ errorCount: number;
13
+ warningCount: number;
14
+ output?: string;
15
+ filteredOutput?: string;
16
+ }
17
+ export interface SourceFileInfo {
18
+ path: string;
19
+ mtime: number;
20
+ size: number;
21
+ }
22
+ export interface TscCacheOptions {
23
+ enabled: boolean;
24
+ cacheDir: string;
25
+ maxAge: number;
26
+ }
27
+ export interface OptimizedTscOptions {
28
+ concurrency?: number;
29
+ stopOnError?: boolean;
30
+ verbose?: boolean;
31
+ copyLogs?: boolean;
32
+ cache?: boolean;
33
+ incremental?: boolean;
34
+ autoConcurrency?: boolean;
35
+ skipUnchanged?: boolean;
36
+ buildMode?: boolean;
37
+ }
38
+ export interface PackageDiscoveryResult {
39
+ packages: PackageInfo[];
40
+ monorepoRoot: string;
41
+ discoveryTime: number;
42
+ cacheHits: number;
43
+ cacheMisses: number;
44
+ }
45
+ export interface TscExecutionResult {
46
+ package: PackageInfo;
47
+ success: boolean;
48
+ skipped: boolean;
49
+ cached: boolean;
50
+ totalErrors: number;
51
+ totalWarnings: number;
52
+ filteredErrors: number;
53
+ filteredWarnings: number;
54
+ output: string;
55
+ filteredOutput: string;
56
+ executionTime: number;
57
+ }
File without changes
package/package.json CHANGED
@@ -2,25 +2,18 @@
2
2
  "name": "@reliverse/dler",
3
3
  "description": "@reliverse/dler is a framework which helps TypeScript and JavaScript developers create their libraries and CLI tools. It provides ready-to-use primitives, so you don't have to write them from scratch.",
4
4
  "author": "reliverse",
5
- "version": "2.0.0",
5
+ "version": "2.0.1",
6
6
  "private": false,
7
7
  "type": "module",
8
8
  "bin": {
9
9
  "dler": "dist/cli.js"
10
10
  },
11
- "exports": {
12
- ".": {
13
- "types": "./src/cli.ts",
14
- "default": "./src/cli.ts"
15
- }
16
- },
17
11
  "scripts": {
18
12
  "dler": "bun src/cli.ts"
19
13
  },
20
- "dependencies": {},
21
- "devDependencies": {
22
- "@biomejs/biome": "^2.3.0",
23
- "ultracite": "^5.6.4"
14
+ "dependencies": {
15
+ "c12": "^3.3.0",
16
+ "clipboardy": "^5.0.0"
24
17
  },
25
18
  "keywords": [
26
19
  "dler",
package/src/cli.ts ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bun
2
+
3
+ // 👉 bun dler <cmd> <args>
4
+ // 💡 dler === apps/dler/src/cli.ts
5
+
6
+ import { runLauncher } from "@reliverse/dler-launcher";
7
+
8
+ await runLauncher(import.meta.url);