@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.
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +3 -0
- package/dist/cmds/build/cmd.d.ts +2 -0
- package/dist/cmds/build/cmd.js +564 -0
- package/dist/cmds/clean/cmd.d.ts +2 -0
- package/dist/cmds/clean/cmd.js +146 -0
- package/dist/cmds/clean/impl.d.ts +2 -0
- package/dist/cmds/clean/impl.js +627 -0
- package/dist/cmds/clean/presets.d.ts +10 -0
- package/dist/cmds/clean/presets.js +112 -0
- package/dist/cmds/clean/types.d.ts +62 -0
- package/dist/cmds/clean/types.js +0 -0
- package/dist/cmds/init/cmd.d.ts +3 -0
- package/dist/cmds/init/cmd.js +56 -0
- package/dist/cmds/init/impl/config.d.ts +45 -0
- package/dist/cmds/init/impl/config.js +99 -0
- package/dist/cmds/init/impl/generators.d.ts +6 -0
- package/dist/cmds/init/impl/generators.js +178 -0
- package/dist/cmds/init/impl/prompts.d.ts +2 -0
- package/dist/cmds/init/impl/prompts.js +98 -0
- package/dist/cmds/init/impl/types.d.ts +22 -0
- package/dist/cmds/init/impl/types.js +0 -0
- package/dist/cmds/init/impl/utils.d.ts +4 -0
- package/dist/cmds/init/impl/utils.js +11 -0
- package/dist/cmds/init/impl/validators.d.ts +4 -0
- package/dist/cmds/init/impl/validators.js +42 -0
- package/dist/cmds/integrate/cmd.d.ts +3 -0
- package/dist/cmds/integrate/cmd.js +70 -0
- package/dist/cmds/integrate/impl.d.ts +7 -0
- package/dist/cmds/integrate/impl.js +127 -0
- package/dist/cmds/integrate/integrations/base.d.ts +13 -0
- package/dist/cmds/integrate/integrations/base.js +41 -0
- package/dist/cmds/integrate/integrations/nextjs.d.ts +16 -0
- package/dist/cmds/integrate/integrations/nextjs.js +167 -0
- package/dist/cmds/integrate/integrations/registry.d.ts +7 -0
- package/dist/cmds/integrate/integrations/registry.js +31 -0
- package/dist/cmds/integrate/integrations/ultracite.d.ts +11 -0
- package/dist/cmds/integrate/integrations/ultracite.js +40 -0
- package/dist/cmds/integrate/types.d.ts +39 -0
- package/dist/cmds/integrate/types.js +0 -0
- package/dist/cmds/integrate/utils/biome.d.ts +4 -0
- package/dist/cmds/integrate/utils/biome.js +140 -0
- package/dist/cmds/integrate/utils/context.d.ts +3 -0
- package/dist/cmds/integrate/utils/context.js +111 -0
- package/dist/cmds/integrate/utils/temp.d.ts +3 -0
- package/dist/cmds/integrate/utils/temp.js +36 -0
- package/dist/cmds/perf/analysis/bundle.d.ts +20 -0
- package/dist/cmds/perf/analysis/bundle.js +225 -0
- package/dist/cmds/perf/analysis/filesystem.d.ts +27 -0
- package/dist/cmds/perf/analysis/filesystem.js +246 -0
- package/dist/cmds/perf/analysis/monorepo.d.ts +29 -0
- package/dist/cmds/perf/analysis/monorepo.js +307 -0
- package/dist/cmds/perf/benchmarks/command.d.ts +21 -0
- package/dist/cmds/perf/benchmarks/command.js +162 -0
- package/dist/cmds/perf/benchmarks/memory.d.ts +41 -0
- package/dist/cmds/perf/benchmarks/memory.js +169 -0
- package/dist/cmds/perf/benchmarks/runner.d.ts +22 -0
- package/dist/cmds/perf/benchmarks/runner.js +157 -0
- package/dist/cmds/perf/cmd.d.ts +2 -0
- package/dist/cmds/perf/cmd.js +238 -0
- package/dist/cmds/perf/impl.d.ts +24 -0
- package/dist/cmds/perf/impl.js +304 -0
- package/dist/cmds/perf/reporters/console.d.ts +12 -0
- package/dist/cmds/perf/reporters/console.js +257 -0
- package/dist/cmds/perf/reporters/html.d.ts +27 -0
- package/dist/cmds/perf/reporters/html.js +881 -0
- package/dist/cmds/perf/reporters/json.d.ts +9 -0
- package/dist/cmds/perf/reporters/json.js +32 -0
- package/dist/cmds/perf/types.d.ts +184 -0
- package/dist/cmds/perf/types.js +0 -0
- package/dist/cmds/perf/utils/cache.d.ts +23 -0
- package/dist/cmds/perf/utils/cache.js +171 -0
- package/dist/cmds/perf/utils/formatter.d.ts +17 -0
- package/dist/cmds/perf/utils/formatter.js +134 -0
- package/dist/cmds/perf/utils/stats.d.ts +15 -0
- package/dist/cmds/perf/utils/stats.js +101 -0
- package/dist/cmds/publish/cmd.d.ts +3 -0
- package/dist/cmds/publish/cmd.js +189 -0
- package/dist/cmds/shell/cmd.d.ts +3 -0
- package/dist/cmds/shell/cmd.js +50 -0
- package/dist/cmds/tsc/cache.d.ts +27 -0
- package/dist/cmds/tsc/cache.js +160 -0
- package/dist/cmds/tsc/cmd.d.ts +2 -0
- package/dist/cmds/tsc/cmd.js +111 -0
- package/dist/cmds/tsc/impl.d.ts +41 -0
- package/dist/cmds/tsc/impl.js +572 -0
- package/dist/cmds/tsc/types.d.ts +57 -0
- package/dist/cmds/tsc/types.js +0 -0
- package/package.json +4 -11
- package/src/cli.ts +8 -0
- package/src/cmds/build/cmd.ts +582 -0
- package/src/cmds/clean/cmd.ts +166 -0
- package/src/cmds/clean/impl.ts +900 -0
- package/src/cmds/clean/presets.ts +158 -0
- package/src/cmds/clean/types.ts +71 -0
- package/src/cmds/init/cmd.ts +68 -0
- package/src/cmds/init/impl/config.ts +105 -0
- package/src/cmds/init/impl/generators.ts +220 -0
- package/src/cmds/init/impl/prompts.ts +137 -0
- package/src/cmds/init/impl/types.ts +25 -0
- package/src/cmds/init/impl/utils.ts +17 -0
- package/src/cmds/init/impl/validators.ts +55 -0
- package/src/cmds/integrate/cmd.ts +82 -0
- package/src/cmds/integrate/impl.ts +204 -0
- package/src/cmds/integrate/integrations/base.ts +69 -0
- package/src/cmds/integrate/integrations/nextjs.ts +227 -0
- package/src/cmds/integrate/integrations/registry.ts +45 -0
- package/src/cmds/integrate/integrations/ultracite.ts +53 -0
- package/src/cmds/integrate/types.ts +48 -0
- package/src/cmds/integrate/utils/biome.ts +173 -0
- package/src/cmds/integrate/utils/context.ts +148 -0
- package/src/cmds/integrate/utils/temp.ts +47 -0
- package/src/cmds/perf/analysis/bundle.ts +311 -0
- package/src/cmds/perf/analysis/filesystem.ts +324 -0
- package/src/cmds/perf/analysis/monorepo.ts +439 -0
- package/src/cmds/perf/benchmarks/command.ts +230 -0
- package/src/cmds/perf/benchmarks/memory.ts +249 -0
- package/src/cmds/perf/benchmarks/runner.ts +220 -0
- package/src/cmds/perf/cmd.ts +285 -0
- package/src/cmds/perf/impl.ts +411 -0
- package/src/cmds/perf/reporters/console.ts +331 -0
- package/src/cmds/perf/reporters/html.ts +984 -0
- package/src/cmds/perf/reporters/json.ts +42 -0
- package/src/cmds/perf/types.ts +220 -0
- package/src/cmds/perf/utils/cache.ts +234 -0
- package/src/cmds/perf/utils/formatter.ts +190 -0
- package/src/cmds/perf/utils/stats.ts +153 -0
- package/src/cmds/publish/cmd.ts +215 -0
- package/src/cmds/shell/cmd.ts +61 -0
- package/src/cmds/tsc/cache.ts +237 -0
- package/src/cmds/tsc/cmd.ts +139 -0
- package/src/cmds/tsc/impl.ts +855 -0
- package/src/cmds/tsc/types.ts +66 -0
- package/tsconfig.json +9 -0
- package/cli.js +0 -1316
|
@@ -0,0 +1,855 @@
|
|
|
1
|
+
// apps/dler/src/cmds/tsc/impl.ts
|
|
2
|
+
|
|
3
|
+
import { existsSync } from "node:fs";
|
|
4
|
+
import { cpus } from "node:os";
|
|
5
|
+
import { join, relative, resolve } from "node:path";
|
|
6
|
+
import { writeErrorLines } from "@reliverse/dler-helpers";
|
|
7
|
+
import { logger } from "@reliverse/dler-logger";
|
|
8
|
+
import pMap from "@reliverse/dler-mapper";
|
|
9
|
+
import { createIgnoreFilter, normalizePatterns } from "@reliverse/dler-matcher";
|
|
10
|
+
import {
|
|
11
|
+
getWorkspacePatterns,
|
|
12
|
+
hasWorkspaces,
|
|
13
|
+
readPackageJSON,
|
|
14
|
+
} from "@reliverse/dler-pkg-tsc";
|
|
15
|
+
import clipboard from "clipboardy";
|
|
16
|
+
import { TscCache } from "./cache";
|
|
17
|
+
import type { PackageDiscoveryResult } from "./types";
|
|
18
|
+
|
|
19
|
+
const DEFAULT_CONCURRENCY = Math.max(4, cpus().length);
|
|
20
|
+
const DISCOVERY_CONCURRENCY = 10;
|
|
21
|
+
|
|
22
|
+
// ============================================================================
|
|
23
|
+
// Types
|
|
24
|
+
// ============================================================================
|
|
25
|
+
|
|
26
|
+
export interface PackageInfo {
|
|
27
|
+
name: string;
|
|
28
|
+
path: string;
|
|
29
|
+
hasTsConfig: boolean;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
interface TscResult {
|
|
33
|
+
package: PackageInfo;
|
|
34
|
+
success: boolean;
|
|
35
|
+
skipped: boolean;
|
|
36
|
+
cached: boolean;
|
|
37
|
+
totalErrors: number;
|
|
38
|
+
totalWarnings: number;
|
|
39
|
+
filteredErrors: number;
|
|
40
|
+
filteredWarnings: number;
|
|
41
|
+
output: string;
|
|
42
|
+
filteredOutput: string;
|
|
43
|
+
executionTime: number;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
interface TscSummary {
|
|
47
|
+
totalPackages: number;
|
|
48
|
+
failedPackages: number;
|
|
49
|
+
successfulPackages: number;
|
|
50
|
+
skippedPackages: number;
|
|
51
|
+
totalErrors: number;
|
|
52
|
+
totalWarnings: number;
|
|
53
|
+
hasErrors: boolean;
|
|
54
|
+
results: TscResult[];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
interface TscOptions {
|
|
58
|
+
concurrency?: number;
|
|
59
|
+
stopOnError?: boolean;
|
|
60
|
+
verbose?: boolean;
|
|
61
|
+
copyLogs?: boolean;
|
|
62
|
+
cache?: boolean;
|
|
63
|
+
incremental?: boolean;
|
|
64
|
+
autoConcurrency?: boolean;
|
|
65
|
+
skipUnchanged?: boolean;
|
|
66
|
+
buildMode?: boolean;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
interface SpawnResult {
|
|
70
|
+
stdout: string;
|
|
71
|
+
stderr: string;
|
|
72
|
+
exitCode: number;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// ============================================================================
|
|
76
|
+
// Constants
|
|
77
|
+
// ============================================================================
|
|
78
|
+
|
|
79
|
+
const TS_ERROR_REGEX = /\([0-9]+,[0-9]+\): (error|warning) TS[0-9]+:/;
|
|
80
|
+
|
|
81
|
+
// ============================================================================
|
|
82
|
+
// Package Discovery
|
|
83
|
+
// ============================================================================
|
|
84
|
+
|
|
85
|
+
const findMonorepoRoot = async (startDir?: string): Promise<string | null> => {
|
|
86
|
+
let currentDir = resolve(startDir ?? process.cwd());
|
|
87
|
+
|
|
88
|
+
while (currentDir !== "/") {
|
|
89
|
+
const pkgPath = join(currentDir, "package.json");
|
|
90
|
+
|
|
91
|
+
if (existsSync(pkgPath)) {
|
|
92
|
+
const pkg = await readPackageJSON(currentDir);
|
|
93
|
+
|
|
94
|
+
if (pkg && hasWorkspaces(pkg)) {
|
|
95
|
+
return currentDir;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const parentDir = resolve(currentDir, "..");
|
|
100
|
+
if (parentDir === currentDir) break;
|
|
101
|
+
currentDir = parentDir;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return null;
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
const resolvePackageInfo = async (
|
|
108
|
+
packagePath: string,
|
|
109
|
+
): Promise<PackageInfo | null> => {
|
|
110
|
+
const pkgJsonPath = join(packagePath, "package.json");
|
|
111
|
+
const tsConfigPath = join(packagePath, "tsconfig.json");
|
|
112
|
+
|
|
113
|
+
// Early skip if no package.json
|
|
114
|
+
if (!existsSync(pkgJsonPath)) {
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Early skip if no tsconfig.json (cheaper check first)
|
|
119
|
+
if (!existsSync(tsConfigPath)) {
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
try {
|
|
124
|
+
const pkg = await readPackageJSON(packagePath);
|
|
125
|
+
|
|
126
|
+
if (!pkg?.name) {
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return {
|
|
131
|
+
name: pkg.name,
|
|
132
|
+
path: packagePath,
|
|
133
|
+
hasTsConfig: true, // We already checked this above
|
|
134
|
+
};
|
|
135
|
+
} catch {
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
const getWorkspacePackages = async (
|
|
141
|
+
cwd?: string,
|
|
142
|
+
): Promise<PackageDiscoveryResult> => {
|
|
143
|
+
const startTime = Date.now();
|
|
144
|
+
const monorepoRoot = await findMonorepoRoot(cwd);
|
|
145
|
+
|
|
146
|
+
if (!monorepoRoot) {
|
|
147
|
+
throw new Error(
|
|
148
|
+
"ā No monorepo found. Ensure package.json has 'workspaces' field.",
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const rootPkg = await readPackageJSON(monorepoRoot);
|
|
153
|
+
if (!rootPkg) {
|
|
154
|
+
throw new Error("ā Could not read root package.json");
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const patterns = getWorkspacePatterns(rootPkg);
|
|
158
|
+
|
|
159
|
+
if (!patterns.length) {
|
|
160
|
+
throw new Error("ā No workspace patterns found in package.json");
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Collect all potential package paths first
|
|
164
|
+
const allPackagePaths: string[] = [];
|
|
165
|
+
const seenPaths = new Set<string>();
|
|
166
|
+
|
|
167
|
+
for (const pattern of patterns) {
|
|
168
|
+
// Check if pattern contains wildcards
|
|
169
|
+
if (pattern.includes('*')) {
|
|
170
|
+
// Pattern with wildcards - use glob
|
|
171
|
+
const glob = new Bun.Glob(pattern);
|
|
172
|
+
const matches = glob.scanSync({ cwd: monorepoRoot, onlyFiles: false });
|
|
173
|
+
|
|
174
|
+
for (const match of matches) {
|
|
175
|
+
const packagePath = resolve(monorepoRoot, match);
|
|
176
|
+
|
|
177
|
+
if (seenPaths.has(packagePath)) continue;
|
|
178
|
+
seenPaths.add(packagePath);
|
|
179
|
+
allPackagePaths.push(packagePath);
|
|
180
|
+
}
|
|
181
|
+
} else {
|
|
182
|
+
// Direct package path (no wildcards)
|
|
183
|
+
const packagePath = resolve(monorepoRoot, pattern);
|
|
184
|
+
|
|
185
|
+
if (seenPaths.has(packagePath)) continue;
|
|
186
|
+
seenPaths.add(packagePath);
|
|
187
|
+
allPackagePaths.push(packagePath);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Resolve package info in parallel
|
|
192
|
+
const packageResults = await pMap(
|
|
193
|
+
allPackagePaths,
|
|
194
|
+
async (packagePath) => {
|
|
195
|
+
const pkgInfo = await resolvePackageInfo(packagePath);
|
|
196
|
+
return { packagePath, pkgInfo };
|
|
197
|
+
},
|
|
198
|
+
{ concurrency: DISCOVERY_CONCURRENCY },
|
|
199
|
+
);
|
|
200
|
+
|
|
201
|
+
const packages = packageResults
|
|
202
|
+
.filter((result) => result.pkgInfo !== null)
|
|
203
|
+
.map((result) => result.pkgInfo!);
|
|
204
|
+
|
|
205
|
+
const discoveryTime = Date.now() - startTime;
|
|
206
|
+
|
|
207
|
+
return {
|
|
208
|
+
packages,
|
|
209
|
+
monorepoRoot,
|
|
210
|
+
discoveryTime,
|
|
211
|
+
cacheHits: 0, // Will be updated by cache layer
|
|
212
|
+
cacheMisses: packages.length,
|
|
213
|
+
};
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
// ============================================================================
|
|
217
|
+
// Package Filtering
|
|
218
|
+
// ============================================================================
|
|
219
|
+
|
|
220
|
+
const filterPackages = (
|
|
221
|
+
packages: PackageInfo[],
|
|
222
|
+
ignore?: string | string[],
|
|
223
|
+
): PackageInfo[] => {
|
|
224
|
+
// Always ignore @reliverse/dler-v1 package
|
|
225
|
+
const alwaysIgnored = ["@reliverse/dler-v1"];
|
|
226
|
+
|
|
227
|
+
// Combine user-provided ignore patterns with always ignored packages
|
|
228
|
+
const combinedIgnore = ignore
|
|
229
|
+
? Array.isArray(ignore)
|
|
230
|
+
? [...alwaysIgnored, ...ignore]
|
|
231
|
+
: [...alwaysIgnored, ignore]
|
|
232
|
+
: alwaysIgnored;
|
|
233
|
+
|
|
234
|
+
const ignoreFilter = createIgnoreFilter(combinedIgnore);
|
|
235
|
+
return ignoreFilter(packages);
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
// ============================================================================
|
|
239
|
+
// TypeScript Execution
|
|
240
|
+
// ============================================================================
|
|
241
|
+
|
|
242
|
+
const hasProjectReferences = async (packagePath: string): Promise<boolean> => {
|
|
243
|
+
try {
|
|
244
|
+
const tsConfigPath = join(packagePath, "tsconfig.json");
|
|
245
|
+
if (!existsSync(tsConfigPath)) return false;
|
|
246
|
+
|
|
247
|
+
const content = await Bun.file(tsConfigPath).text();
|
|
248
|
+
const config = JSON.parse(content);
|
|
249
|
+
return !!(
|
|
250
|
+
config.references &&
|
|
251
|
+
Array.isArray(config.references) &&
|
|
252
|
+
config.references.length > 0
|
|
253
|
+
);
|
|
254
|
+
} catch {
|
|
255
|
+
return false;
|
|
256
|
+
}
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
const runTscCommand = async (
|
|
260
|
+
packagePath: string,
|
|
261
|
+
options: { incremental?: boolean; buildMode?: boolean } = {},
|
|
262
|
+
): Promise<SpawnResult> => {
|
|
263
|
+
try {
|
|
264
|
+
const { incremental = true, buildMode = false } = options;
|
|
265
|
+
|
|
266
|
+
let args: string[];
|
|
267
|
+
|
|
268
|
+
if (buildMode && (await hasProjectReferences(packagePath))) {
|
|
269
|
+
// Use tsc --build for project references (faster for multi-package setups)
|
|
270
|
+
args = ["tsc", "--build"];
|
|
271
|
+
if (incremental) {
|
|
272
|
+
args.push("--incremental");
|
|
273
|
+
}
|
|
274
|
+
} else {
|
|
275
|
+
// Use regular tsc --noEmit for single packages
|
|
276
|
+
args = ["tsc", "--noEmit"];
|
|
277
|
+
if (incremental) {
|
|
278
|
+
args.push("--incremental");
|
|
279
|
+
// Add tsbuildinfo file path for incremental compilation
|
|
280
|
+
const tsBuildInfoPath = join(
|
|
281
|
+
packagePath,
|
|
282
|
+
"node_modules/.cache/dler-tsc",
|
|
283
|
+
`${packagePath.split(/[/\\]/).pop()}.tsbuildinfo`,
|
|
284
|
+
);
|
|
285
|
+
args.push("--tsBuildInfoFile", tsBuildInfoPath);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
const proc = Bun.spawn(args, {
|
|
290
|
+
cwd: packagePath,
|
|
291
|
+
stdout: "pipe",
|
|
292
|
+
stderr: "pipe",
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
const [stdout, stderr] = await Promise.all([
|
|
296
|
+
new Response(proc.stdout).text(),
|
|
297
|
+
new Response(proc.stderr).text(),
|
|
298
|
+
]);
|
|
299
|
+
|
|
300
|
+
const exitCode = await proc.exited;
|
|
301
|
+
|
|
302
|
+
return { stdout, stderr, exitCode };
|
|
303
|
+
} catch (error) {
|
|
304
|
+
throw new Error(
|
|
305
|
+
`Failed to spawn tsc: ${error instanceof Error ? error.message : String(error)}`,
|
|
306
|
+
);
|
|
307
|
+
}
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
// ============================================================================
|
|
311
|
+
// Output Filtering
|
|
312
|
+
// ============================================================================
|
|
313
|
+
|
|
314
|
+
const countErrorsAndWarnings = (
|
|
315
|
+
output: string,
|
|
316
|
+
): { errors: number; warnings: number } => {
|
|
317
|
+
const lines = output.split("\n");
|
|
318
|
+
let errors = 0;
|
|
319
|
+
let warnings = 0;
|
|
320
|
+
|
|
321
|
+
for (const line of lines) {
|
|
322
|
+
if (TS_ERROR_REGEX.test(line)) {
|
|
323
|
+
if (line.includes(": error TS")) {
|
|
324
|
+
errors++;
|
|
325
|
+
} else if (line.includes(": warning TS")) {
|
|
326
|
+
warnings++;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
return { errors, warnings };
|
|
332
|
+
};
|
|
333
|
+
|
|
334
|
+
const filterOutputLines = (output: string, packagePath: string, monorepoRoot: string): string => {
|
|
335
|
+
const lines = output.split("\n");
|
|
336
|
+
const filtered: string[] = [];
|
|
337
|
+
const normalizedPackagePath = resolve(packagePath);
|
|
338
|
+
|
|
339
|
+
for (const line of lines) {
|
|
340
|
+
// Keep non-error lines
|
|
341
|
+
if (!TS_ERROR_REGEX.test(line)) {
|
|
342
|
+
filtered.push(line);
|
|
343
|
+
continue;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// Extract file path from error line and convert to full path
|
|
347
|
+
const match = line.match(/^(.+?)\(/);
|
|
348
|
+
|
|
349
|
+
if (match && match[1]) {
|
|
350
|
+
const relativePath = match[1];
|
|
351
|
+
const fullPath = resolve(packagePath, relativePath);
|
|
352
|
+
const normalizedFilePath = resolve(fullPath);
|
|
353
|
+
|
|
354
|
+
// Check if error is from another package
|
|
355
|
+
const isCrossPackageError = line.includes("../") || line.includes("..\\");
|
|
356
|
+
|
|
357
|
+
if (isCrossPackageError) {
|
|
358
|
+
// Only include if file is within current package
|
|
359
|
+
if (normalizedFilePath.startsWith(normalizedPackagePath)) {
|
|
360
|
+
// Convert relative path to full path from monorepo root
|
|
361
|
+
const relativeToMonorepo = relative(monorepoRoot, normalizedFilePath);
|
|
362
|
+
const updatedLine = line.replace(relativePath, relativeToMonorepo);
|
|
363
|
+
filtered.push(updatedLine);
|
|
364
|
+
}
|
|
365
|
+
} else {
|
|
366
|
+
// For same-package errors, also convert to full path from monorepo root
|
|
367
|
+
const relativeToMonorepo = relative(monorepoRoot, normalizedFilePath);
|
|
368
|
+
const updatedLine = line.replace(relativePath, relativeToMonorepo);
|
|
369
|
+
filtered.push(updatedLine);
|
|
370
|
+
}
|
|
371
|
+
} else {
|
|
372
|
+
filtered.push(line);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
return filtered.join("\n");
|
|
377
|
+
};
|
|
378
|
+
|
|
379
|
+
// ============================================================================
|
|
380
|
+
// Package Processing
|
|
381
|
+
// ============================================================================
|
|
382
|
+
|
|
383
|
+
const runTscOnPackage = async (
|
|
384
|
+
pkg: PackageInfo,
|
|
385
|
+
monorepoRoot: string,
|
|
386
|
+
options: {
|
|
387
|
+
verbose?: boolean;
|
|
388
|
+
cache?: TscCache;
|
|
389
|
+
incremental?: boolean;
|
|
390
|
+
buildMode?: boolean;
|
|
391
|
+
} = {},
|
|
392
|
+
): Promise<TscResult> => {
|
|
393
|
+
const {
|
|
394
|
+
verbose = false,
|
|
395
|
+
cache,
|
|
396
|
+
incremental = true,
|
|
397
|
+
buildMode = false,
|
|
398
|
+
} = options;
|
|
399
|
+
const startTime = Date.now();
|
|
400
|
+
|
|
401
|
+
if (!pkg.hasTsConfig) {
|
|
402
|
+
if (verbose) {
|
|
403
|
+
logger.info(`āļø Skipping ${pkg.name} (no tsconfig.json)`);
|
|
404
|
+
}
|
|
405
|
+
return {
|
|
406
|
+
package: pkg,
|
|
407
|
+
success: true,
|
|
408
|
+
skipped: true,
|
|
409
|
+
cached: false,
|
|
410
|
+
totalErrors: 0,
|
|
411
|
+
totalWarnings: 0,
|
|
412
|
+
filteredErrors: 0,
|
|
413
|
+
filteredWarnings: 0,
|
|
414
|
+
output: "",
|
|
415
|
+
filteredOutput: "",
|
|
416
|
+
executionTime: Date.now() - startTime,
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
// Check cache first
|
|
421
|
+
if (cache) {
|
|
422
|
+
const shouldSkip = await cache.shouldSkipPackage(pkg);
|
|
423
|
+
if (shouldSkip) {
|
|
424
|
+
if (verbose) {
|
|
425
|
+
logger.info(`ā” Skipping ${pkg.name} (no changes since last check)`);
|
|
426
|
+
}
|
|
427
|
+
const cachedResult = await cache.getCachedResult(pkg);
|
|
428
|
+
return {
|
|
429
|
+
package: pkg,
|
|
430
|
+
success: !cachedResult?.hasErrors,
|
|
431
|
+
skipped: false,
|
|
432
|
+
cached: true,
|
|
433
|
+
totalErrors: cachedResult?.errorCount ?? 0,
|
|
434
|
+
totalWarnings: cachedResult?.warningCount ?? 0,
|
|
435
|
+
filteredErrors: cachedResult?.errorCount ?? 0,
|
|
436
|
+
filteredWarnings: cachedResult?.warningCount ?? 0,
|
|
437
|
+
output: cachedResult?.output ?? "Cached result",
|
|
438
|
+
filteredOutput: cachedResult?.filteredOutput ?? "Cached result",
|
|
439
|
+
executionTime: Date.now() - startTime,
|
|
440
|
+
};
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
if (verbose) {
|
|
445
|
+
logger.info(`š Checking ${pkg.name}...`);
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
try {
|
|
449
|
+
const result = await runTscCommand(pkg.path, { incremental, buildMode });
|
|
450
|
+
const output = result.stdout + result.stderr;
|
|
451
|
+
const filteredOutput = filterOutputLines(output, pkg.path, monorepoRoot);
|
|
452
|
+
|
|
453
|
+
const totalCounts = countErrorsAndWarnings(output);
|
|
454
|
+
const filteredCounts = countErrorsAndWarnings(filteredOutput);
|
|
455
|
+
|
|
456
|
+
if (verbose) {
|
|
457
|
+
const status = filteredCounts.errors === 0 ? "ā
" : "ā";
|
|
458
|
+
logger.log(
|
|
459
|
+
`${status} ${pkg.name}: ${filteredCounts.errors} errors, ${filteredCounts.warnings} warnings`,
|
|
460
|
+
);
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
const tscResult: TscResult = {
|
|
464
|
+
package: pkg,
|
|
465
|
+
success: filteredCounts.errors === 0,
|
|
466
|
+
skipped: false,
|
|
467
|
+
cached: false,
|
|
468
|
+
totalErrors: totalCounts.errors,
|
|
469
|
+
totalWarnings: totalCounts.warnings,
|
|
470
|
+
filteredErrors: filteredCounts.errors,
|
|
471
|
+
filteredWarnings: filteredCounts.warnings,
|
|
472
|
+
output,
|
|
473
|
+
filteredOutput,
|
|
474
|
+
executionTime: Date.now() - startTime,
|
|
475
|
+
};
|
|
476
|
+
|
|
477
|
+
// Update cache
|
|
478
|
+
if (cache) {
|
|
479
|
+
await cache.updatePackageCache(pkg, {
|
|
480
|
+
success: tscResult.success,
|
|
481
|
+
errorCount: tscResult.filteredErrors,
|
|
482
|
+
warningCount: tscResult.filteredWarnings,
|
|
483
|
+
output: tscResult.output,
|
|
484
|
+
filteredOutput: tscResult.filteredOutput,
|
|
485
|
+
});
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
return tscResult;
|
|
489
|
+
} catch (error) {
|
|
490
|
+
logger.error(
|
|
491
|
+
`ā ${pkg.name}: Failed to run tsc - ${error instanceof Error ? error.message : String(error)}`,
|
|
492
|
+
);
|
|
493
|
+
return {
|
|
494
|
+
package: pkg,
|
|
495
|
+
success: false,
|
|
496
|
+
skipped: false,
|
|
497
|
+
cached: false,
|
|
498
|
+
totalErrors: 1,
|
|
499
|
+
totalWarnings: 0,
|
|
500
|
+
filteredErrors: 1,
|
|
501
|
+
filteredWarnings: 0,
|
|
502
|
+
output: error instanceof Error ? error.message : String(error),
|
|
503
|
+
filteredOutput: error instanceof Error ? error.message : String(error),
|
|
504
|
+
executionTime: Date.now() - startTime,
|
|
505
|
+
};
|
|
506
|
+
}
|
|
507
|
+
};
|
|
508
|
+
|
|
509
|
+
// ============================================================================
|
|
510
|
+
// Result Collection
|
|
511
|
+
// ============================================================================
|
|
512
|
+
|
|
513
|
+
const collectAllResults = async (
|
|
514
|
+
packages: PackageInfo[],
|
|
515
|
+
monorepoRoot: string,
|
|
516
|
+
options: TscOptions = {},
|
|
517
|
+
cache?: TscCache,
|
|
518
|
+
): Promise<TscSummary> => {
|
|
519
|
+
const {
|
|
520
|
+
concurrency = DEFAULT_CONCURRENCY,
|
|
521
|
+
stopOnError = false,
|
|
522
|
+
verbose = false,
|
|
523
|
+
incremental = true,
|
|
524
|
+
buildMode = false,
|
|
525
|
+
} = options;
|
|
526
|
+
|
|
527
|
+
// Log progress for package processing
|
|
528
|
+
if (!verbose) {
|
|
529
|
+
logger.info(`Processing ${packages.length} packages...`);
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
try {
|
|
533
|
+
const tscResults = await pMap(
|
|
534
|
+
packages,
|
|
535
|
+
async (pkg, index) => {
|
|
536
|
+
if (!verbose) {
|
|
537
|
+
logger.info(
|
|
538
|
+
`Processing ${pkg.name} (${index + 1}/${packages.length})...`,
|
|
539
|
+
);
|
|
540
|
+
}
|
|
541
|
+
return runTscOnPackage(pkg, monorepoRoot, {
|
|
542
|
+
verbose,
|
|
543
|
+
cache,
|
|
544
|
+
incremental,
|
|
545
|
+
buildMode,
|
|
546
|
+
});
|
|
547
|
+
},
|
|
548
|
+
{
|
|
549
|
+
concurrency,
|
|
550
|
+
stopOnError,
|
|
551
|
+
},
|
|
552
|
+
);
|
|
553
|
+
|
|
554
|
+
const failedPackages = tscResults.filter(
|
|
555
|
+
(r) => !r.success && !r.skipped,
|
|
556
|
+
).length;
|
|
557
|
+
const successfulPackages = tscResults.filter((r) => r.success).length;
|
|
558
|
+
const skippedPackages = tscResults.filter((r) => r.skipped).length;
|
|
559
|
+
const totalErrors = tscResults.reduce(
|
|
560
|
+
(sum, r) => sum + r.filteredErrors,
|
|
561
|
+
0,
|
|
562
|
+
);
|
|
563
|
+
const totalWarnings = tscResults.reduce(
|
|
564
|
+
(sum, r) => sum + r.filteredWarnings,
|
|
565
|
+
0,
|
|
566
|
+
);
|
|
567
|
+
|
|
568
|
+
return {
|
|
569
|
+
totalPackages: packages.length,
|
|
570
|
+
failedPackages,
|
|
571
|
+
successfulPackages,
|
|
572
|
+
skippedPackages,
|
|
573
|
+
totalErrors,
|
|
574
|
+
totalWarnings,
|
|
575
|
+
hasErrors: failedPackages > 0,
|
|
576
|
+
results: tscResults,
|
|
577
|
+
};
|
|
578
|
+
} catch (error) {
|
|
579
|
+
// Handle aggregate errors from pMap when stopOnError is false
|
|
580
|
+
if (error instanceof AggregateError) {
|
|
581
|
+
const tscResults: TscResult[] = error.errors.map((err, index) => {
|
|
582
|
+
const pkg = packages[index];
|
|
583
|
+
if (!pkg) {
|
|
584
|
+
throw new Error(`Package at index ${index} not found`);
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
if (verbose) {
|
|
588
|
+
logger.error(
|
|
589
|
+
`ā ${pkg.name}: Aggregate error - ${err instanceof Error ? err.message : String(err)}`,
|
|
590
|
+
);
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
return {
|
|
594
|
+
package: pkg,
|
|
595
|
+
success: false,
|
|
596
|
+
skipped: false,
|
|
597
|
+
cached: false,
|
|
598
|
+
totalErrors: 1,
|
|
599
|
+
totalWarnings: 0,
|
|
600
|
+
filteredErrors: 1,
|
|
601
|
+
filteredWarnings: 0,
|
|
602
|
+
output: err instanceof Error ? err.message : String(err),
|
|
603
|
+
filteredOutput: err instanceof Error ? err.message : String(err),
|
|
604
|
+
executionTime: 0,
|
|
605
|
+
};
|
|
606
|
+
});
|
|
607
|
+
|
|
608
|
+
const failedPackages = tscResults.filter(
|
|
609
|
+
(r) => !r.success && !r.skipped,
|
|
610
|
+
).length;
|
|
611
|
+
const successfulPackages = tscResults.filter((r) => r.success).length;
|
|
612
|
+
const skippedPackages = tscResults.filter((r) => r.skipped).length;
|
|
613
|
+
const totalErrors = tscResults.reduce(
|
|
614
|
+
(sum, r) => sum + r.filteredErrors,
|
|
615
|
+
0,
|
|
616
|
+
);
|
|
617
|
+
const totalWarnings = tscResults.reduce(
|
|
618
|
+
(sum, r) => sum + r.filteredWarnings,
|
|
619
|
+
0,
|
|
620
|
+
);
|
|
621
|
+
|
|
622
|
+
return {
|
|
623
|
+
totalPackages: packages.length,
|
|
624
|
+
failedPackages,
|
|
625
|
+
successfulPackages,
|
|
626
|
+
skippedPackages,
|
|
627
|
+
totalErrors,
|
|
628
|
+
totalWarnings,
|
|
629
|
+
hasErrors: failedPackages > 0,
|
|
630
|
+
results: tscResults,
|
|
631
|
+
};
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
// Re-throw other errors
|
|
635
|
+
throw error;
|
|
636
|
+
}
|
|
637
|
+
};
|
|
638
|
+
|
|
639
|
+
// ============================================================================
|
|
640
|
+
// Clipboard Functionality
|
|
641
|
+
// ============================================================================
|
|
642
|
+
|
|
643
|
+
const collectFailedPackageLogs = (summary: TscSummary): string => {
|
|
644
|
+
const failed = summary.results.filter((r) => !r.success && !r.skipped);
|
|
645
|
+
|
|
646
|
+
if (failed.length === 0) {
|
|
647
|
+
return "";
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
const logs: string[] = [];
|
|
651
|
+
logs.push(
|
|
652
|
+
"I received the following TypeScript errors (please analyse the related code for each and correct them):",
|
|
653
|
+
);
|
|
654
|
+
logs.push("```");
|
|
655
|
+
logs.push("TypeScript Check (bun dler tsc)");
|
|
656
|
+
logs.push("");
|
|
657
|
+
|
|
658
|
+
for (const result of failed) {
|
|
659
|
+
logs.push(`š¦ ${result.package.name}`);
|
|
660
|
+
logs.push(
|
|
661
|
+
` Errors: ${result.filteredErrors}, Warnings: ${result.filteredWarnings}`,
|
|
662
|
+
);
|
|
663
|
+
logs.push(" " + "ā".repeat(30));
|
|
664
|
+
|
|
665
|
+
if (result.filteredOutput.trim()) {
|
|
666
|
+
const lines = result.filteredOutput
|
|
667
|
+
.trim()
|
|
668
|
+
.split("\n")
|
|
669
|
+
.map((line) => ` ${line}`);
|
|
670
|
+
logs.push(...lines);
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
logs.push("```");
|
|
674
|
+
logs.push("");
|
|
675
|
+
logs.push("");
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
return logs.join("\n");
|
|
679
|
+
};
|
|
680
|
+
|
|
681
|
+
const copyLogsToClipboard = async (summary: TscSummary): Promise<void> => {
|
|
682
|
+
try {
|
|
683
|
+
const logs = collectFailedPackageLogs(summary);
|
|
684
|
+
|
|
685
|
+
if (!logs) {
|
|
686
|
+
logger.info("ā¹ļø No failed packages to copy to clipboard");
|
|
687
|
+
return;
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
await clipboard.write(logs);
|
|
691
|
+
logger.success("š Failed package logs copied to clipboard!");
|
|
692
|
+
} catch (error) {
|
|
693
|
+
logger.error("ā Failed to copy logs to clipboard:");
|
|
694
|
+
if (error instanceof Error) {
|
|
695
|
+
logger.error(error.message);
|
|
696
|
+
} else {
|
|
697
|
+
logger.error(String(error));
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
};
|
|
701
|
+
|
|
702
|
+
// ============================================================================
|
|
703
|
+
// Output Formatting
|
|
704
|
+
// ============================================================================
|
|
705
|
+
|
|
706
|
+
const formatOutput = (summary: TscSummary, verbose: boolean): void => {
|
|
707
|
+
const { totalPackages, failedPackages, successfulPackages, skippedPackages } =
|
|
708
|
+
summary;
|
|
709
|
+
|
|
710
|
+
// Summary header
|
|
711
|
+
logger.log("ā".repeat(60));
|
|
712
|
+
logger.log(`š TypeScript Check Summary:`);
|
|
713
|
+
logger.log(` Total packages: ${totalPackages}`);
|
|
714
|
+
logger.log(` ā
Passed: ${successfulPackages}`);
|
|
715
|
+
logger.log(` ā Failed: ${failedPackages}`);
|
|
716
|
+
logger.log(` āļø Skipped: ${skippedPackages}`);
|
|
717
|
+
logger.log(` š Total errors: ${summary.totalErrors}`);
|
|
718
|
+
logger.log(` ā ļø Total warnings: ${summary.totalWarnings}`);
|
|
719
|
+
logger.log("ā".repeat(60));
|
|
720
|
+
|
|
721
|
+
// Failed packages
|
|
722
|
+
const failed = summary.results.filter((r) => !r.success && !r.skipped);
|
|
723
|
+
|
|
724
|
+
if (failed.length > 0) {
|
|
725
|
+
logger.error("\nā Failed Packages:\n");
|
|
726
|
+
|
|
727
|
+
for (const result of failed) {
|
|
728
|
+
logger.error(`š¦ ${result.package.name}`);
|
|
729
|
+
logger.error(
|
|
730
|
+
` Errors: ${result.filteredErrors}, Warnings: ${result.filteredWarnings}`,
|
|
731
|
+
);
|
|
732
|
+
|
|
733
|
+
if (result.filteredOutput.trim()) {
|
|
734
|
+
logger.error(" ā".repeat(30));
|
|
735
|
+
const lines = result.filteredOutput
|
|
736
|
+
.trim()
|
|
737
|
+
.split("\n")
|
|
738
|
+
.map((line) => ` ${line}`);
|
|
739
|
+
writeErrorLines(lines);
|
|
740
|
+
logger.error("");
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
if (verbose) {
|
|
746
|
+
// Successful packages
|
|
747
|
+
const successful = summary.results.filter((r) => r.success && !r.skipped);
|
|
748
|
+
|
|
749
|
+
if (successful.length > 0) {
|
|
750
|
+
logger.success("\nā
Successful Packages:\n");
|
|
751
|
+
for (const result of successful) {
|
|
752
|
+
logger.success(` ⢠${result.package.name}`);
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
// Skipped packages
|
|
757
|
+
const skipped = summary.results.filter((r) => r.skipped);
|
|
758
|
+
|
|
759
|
+
if (skipped.length > 0) {
|
|
760
|
+
logger.info("\nāļø Skipped Packages (no tsconfig.json):\n");
|
|
761
|
+
for (const result of skipped) {
|
|
762
|
+
logger.info(` ⢠${result.package.name}`);
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
logger.log("");
|
|
767
|
+
}
|
|
768
|
+
};
|
|
769
|
+
|
|
770
|
+
// ============================================================================
|
|
771
|
+
// Main Entry Point
|
|
772
|
+
// ============================================================================
|
|
773
|
+
|
|
774
|
+
export const runTscOnAllPackages = async (
|
|
775
|
+
ignore?: string | string[],
|
|
776
|
+
cwd?: string,
|
|
777
|
+
options: TscOptions = {},
|
|
778
|
+
): Promise<TscSummary> => {
|
|
779
|
+
const {
|
|
780
|
+
verbose = false,
|
|
781
|
+
copyLogs = false,
|
|
782
|
+
cache: enableCache = true,
|
|
783
|
+
autoConcurrency = false,
|
|
784
|
+
} = options;
|
|
785
|
+
|
|
786
|
+
return (async () => {
|
|
787
|
+
// Initialize cache
|
|
788
|
+
const cache = enableCache ? new TscCache() : undefined;
|
|
789
|
+
if (cache) {
|
|
790
|
+
await cache.initialize();
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
// Discover packages with timing
|
|
794
|
+
const discoveryResult = await getWorkspacePackages(cwd);
|
|
795
|
+
const { packages: allPackages, discoveryTime } = discoveryResult;
|
|
796
|
+
|
|
797
|
+
if (verbose) {
|
|
798
|
+
logger.info(
|
|
799
|
+
` Found ${allPackages.length} packages (${discoveryTime}ms)`,
|
|
800
|
+
);
|
|
801
|
+
logger.info(" Packages found:");
|
|
802
|
+
for (const pkg of allPackages) {
|
|
803
|
+
const configStatus = pkg.hasTsConfig ? "ā
" : "āļø";
|
|
804
|
+
logger.info(` ${configStatus} ${pkg.name} (${pkg.path})`);
|
|
805
|
+
}
|
|
806
|
+
logger.info("");
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
// Apply filters
|
|
810
|
+
const packages = filterPackages(allPackages, ignore);
|
|
811
|
+
const ignoredCount = allPackages.length - packages.length;
|
|
812
|
+
|
|
813
|
+
if (ignoredCount > 0) {
|
|
814
|
+
// Always ignore @reliverse/dler-v1 package
|
|
815
|
+
const alwaysIgnored = ["@reliverse/dler-v1"];
|
|
816
|
+
const combinedIgnore = ignore
|
|
817
|
+
? Array.isArray(ignore)
|
|
818
|
+
? [...alwaysIgnored, ...ignore]
|
|
819
|
+
: [...alwaysIgnored, ignore]
|
|
820
|
+
: alwaysIgnored;
|
|
821
|
+
|
|
822
|
+
const patterns = normalizePatterns(combinedIgnore);
|
|
823
|
+
logger.info(
|
|
824
|
+
` Ignoring ${ignoredCount} packages matching: ${patterns.join(", ")}`,
|
|
825
|
+
);
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
// Auto-detect concurrency if requested
|
|
829
|
+
let concurrency = options.concurrency ?? DEFAULT_CONCURRENCY;
|
|
830
|
+
if (autoConcurrency) {
|
|
831
|
+
concurrency = Math.max(4, cpus().length * 2);
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
const { stopOnError = false } = options;
|
|
835
|
+
logger.info(
|
|
836
|
+
` Checking ${packages.length} packages (concurrency: ${concurrency}, stopOnError: ${stopOnError})...\n`,
|
|
837
|
+
);
|
|
838
|
+
|
|
839
|
+
if (verbose) {
|
|
840
|
+
logger.info("š Starting TypeScript checks...\n");
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
const summary = await collectAllResults(packages, discoveryResult.monorepoRoot, options, cache);
|
|
844
|
+
|
|
845
|
+
// Display results
|
|
846
|
+
formatOutput(summary, verbose);
|
|
847
|
+
|
|
848
|
+
// Copy logs to clipboard if requested and there are errors
|
|
849
|
+
if (copyLogs && summary.hasErrors) {
|
|
850
|
+
await copyLogsToClipboard(summary);
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
return summary;
|
|
854
|
+
})();
|
|
855
|
+
};
|