@reliverse/dler 2.3.2 → 2.3.4
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/cmds/add/cmd.d.ts +2 -0
- package/dist/cmds/add/cmd.js +153 -0
- package/dist/cmds/add/impl.d.ts +19 -0
- package/dist/cmds/add/impl.js +515 -0
- package/dist/cmds/biome/cmd.d.ts +1 -5
- package/dist/cmds/build/cmd.d.ts +1 -91
- package/dist/cmds/clean/cmd.d.ts +1 -14
- package/dist/cmds/clean/presets.js +7 -0
- package/dist/cmds/init/cmd.d.ts +1 -8
- package/dist/cmds/publish/cmd.d.ts +1 -32
- package/dist/cmds/rm/cmd.d.ts +2 -0
- package/dist/cmds/rm/cmd.js +133 -0
- package/dist/cmds/rm/impl.d.ts +17 -0
- package/dist/cmds/rm/impl.js +509 -0
- package/dist/cmds/senv/cmd.d.ts +1 -7
- package/dist/cmds/test/cmd.d.ts +1 -8
- package/dist/cmds/tsc/cache.d.ts +0 -1
- package/dist/cmds/tsc/cache.js +8 -19
- package/dist/cmds/tsc/cmd.d.ts +1 -14
- package/dist/cmds/tsc/impl.js +77 -61
- package/dist/cmds/unused/cmd.d.ts +2 -0
- package/dist/cmds/unused/cmd.js +105 -0
- package/dist/cmds/unused/impl.d.ts +16 -0
- package/dist/cmds/unused/impl.js +415 -0
- package/dist/cmds/update/cmd.d.ts +1 -11
- package/dist/cmds/update/cmd.js +113 -36
- package/dist/cmds/update/impl.d.ts +8 -2
- package/dist/cmds/update/impl.js +69 -8
- package/dist/cmds/update/utils.d.ts +19 -2
- package/dist/cmds/update/utils.js +149 -61
- package/dist/utils/cache.d.ts +31 -0
- package/dist/utils/cache.js +60 -0
- package/package.json +19 -18
package/dist/cmds/tsc/impl.js
CHANGED
|
@@ -153,47 +153,60 @@ const hasProjectReferences = async (packagePath) => {
|
|
|
153
153
|
return false;
|
|
154
154
|
}
|
|
155
155
|
};
|
|
156
|
-
const
|
|
157
|
-
const
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
156
|
+
const findTypeScriptExecutable = async (packagePath, preferTsgo = false) => {
|
|
157
|
+
const findExecutable = async (name) => {
|
|
158
|
+
const localPath = join(packagePath, "node_modules", ".bin", name);
|
|
159
|
+
if (existsSync(localPath)) {
|
|
160
|
+
return localPath;
|
|
161
|
+
}
|
|
162
|
+
let currentDir = resolve(packagePath, "..");
|
|
163
|
+
while (currentDir !== "/") {
|
|
164
|
+
const parentLocalPath = join(currentDir, "node_modules", ".bin", name);
|
|
165
|
+
if (existsSync(parentLocalPath)) {
|
|
166
|
+
return parentLocalPath;
|
|
167
|
+
}
|
|
168
|
+
const parentDir = resolve(currentDir, "..");
|
|
169
|
+
if (parentDir === currentDir) {
|
|
170
|
+
break;
|
|
171
|
+
}
|
|
172
|
+
currentDir = parentDir;
|
|
166
173
|
}
|
|
167
|
-
const
|
|
168
|
-
if (
|
|
169
|
-
|
|
174
|
+
const globalPath = await lookpath(name);
|
|
175
|
+
if (globalPath) {
|
|
176
|
+
return globalPath;
|
|
170
177
|
}
|
|
171
|
-
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
178
|
+
return null;
|
|
179
|
+
};
|
|
180
|
+
if (preferTsgo) {
|
|
181
|
+
const tsgoPath = await findExecutable("tsgo");
|
|
182
|
+
if (tsgoPath) {
|
|
183
|
+
return { executable: tsgoPath, usedTsgo: true };
|
|
184
|
+
}
|
|
185
|
+
const tscPath = await findExecutable("tsc");
|
|
186
|
+
return { executable: tscPath, usedTsgo: false };
|
|
187
|
+
} else {
|
|
188
|
+
const tscPath = await findExecutable("tsc");
|
|
189
|
+
return { executable: tscPath, usedTsgo: false };
|
|
176
190
|
}
|
|
177
|
-
return null;
|
|
178
191
|
};
|
|
179
192
|
const runTscCommand = async (packagePath, options = {}) => {
|
|
193
|
+
const { incremental = true, buildMode = false, preferTsgo = false } = options;
|
|
180
194
|
try {
|
|
181
|
-
const {
|
|
182
|
-
|
|
183
|
-
if (!tscExecutable) {
|
|
195
|
+
const { executable, usedTsgo } = await findTypeScriptExecutable(packagePath, preferTsgo);
|
|
196
|
+
if (!executable) {
|
|
184
197
|
throw new Error(
|
|
185
|
-
"
|
|
198
|
+
`${preferTsgo ? "tsgo" : "tsc"} not found. Skipping package (install ${preferTsgo ? "@typescript/native-preview" : "typescript"} locally or globally to enable type checking).`
|
|
186
199
|
);
|
|
187
200
|
}
|
|
188
201
|
let args;
|
|
189
202
|
if (buildMode && await hasProjectReferences(packagePath)) {
|
|
190
|
-
args = [
|
|
191
|
-
if (incremental) {
|
|
203
|
+
args = [executable, "--build"];
|
|
204
|
+
if (incremental && !usedTsgo) {
|
|
192
205
|
args.push("--incremental");
|
|
193
206
|
}
|
|
194
207
|
} else {
|
|
195
|
-
args = [
|
|
196
|
-
if (incremental) {
|
|
208
|
+
args = [executable, "--noEmit"];
|
|
209
|
+
if (incremental && !usedTsgo) {
|
|
197
210
|
args.push("--incremental");
|
|
198
211
|
const tsBuildInfoPath = join(
|
|
199
212
|
packagePath,
|
|
@@ -215,8 +228,18 @@ const runTscCommand = async (packagePath, options = {}) => {
|
|
|
215
228
|
const exitCode = await proc.exited;
|
|
216
229
|
return { stdout, stderr, exitCode };
|
|
217
230
|
} catch (error) {
|
|
231
|
+
if (preferTsgo && error instanceof Error && !error.message.includes("TypeScript not found")) {
|
|
232
|
+
try {
|
|
233
|
+
logger.warn(`\u26A0\uFE0F tsgo failed, falling back to tsc: ${error.message}`);
|
|
234
|
+
return runTscCommand(packagePath, { ...options, preferTsgo: false });
|
|
235
|
+
} catch (fallbackError) {
|
|
236
|
+
throw new Error(
|
|
237
|
+
`Failed to spawn TypeScript compiler (both tsgo and tsc): ${fallbackError instanceof Error ? fallbackError.message : String(fallbackError)}`
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
218
241
|
throw new Error(
|
|
219
|
-
`Failed to spawn
|
|
242
|
+
`Failed to spawn TypeScript compiler: ${error instanceof Error ? error.message : String(error)}`
|
|
220
243
|
);
|
|
221
244
|
}
|
|
222
245
|
};
|
|
@@ -271,15 +294,15 @@ const checkRequiredDependencies = async (packagePath) => {
|
|
|
271
294
|
try {
|
|
272
295
|
const pkg = await readPackageJSON(packagePath);
|
|
273
296
|
if (!pkg) {
|
|
274
|
-
return { hasTypeScript: false,
|
|
297
|
+
return { hasTypeScript: false, hasNativePreview: false };
|
|
275
298
|
}
|
|
276
299
|
const deps = pkg.dependencies && typeof pkg.dependencies === "object" ? pkg.dependencies : {};
|
|
277
300
|
const devDeps = pkg.devDependencies && typeof pkg.devDependencies === "object" ? pkg.devDependencies : {};
|
|
278
301
|
const hasTypeScript = "typescript" in deps || "typescript" in devDeps;
|
|
279
|
-
const
|
|
280
|
-
return { hasTypeScript,
|
|
302
|
+
const hasNativePreview = "@typescript/native-preview" in deps || "@typescript/native-preview" in devDeps;
|
|
303
|
+
return { hasTypeScript, hasNativePreview };
|
|
281
304
|
} catch {
|
|
282
|
-
return { hasTypeScript: false,
|
|
305
|
+
return { hasTypeScript: false, hasNativePreview: false };
|
|
283
306
|
}
|
|
284
307
|
};
|
|
285
308
|
const runTscOnPackage = async (pkg, monorepoRoot, options = {}) => {
|
|
@@ -303,19 +326,13 @@ const runTscOnPackage = async (pkg, monorepoRoot, options = {}) => {
|
|
|
303
326
|
executionTime: Date.now() - startTime
|
|
304
327
|
};
|
|
305
328
|
}
|
|
306
|
-
const { hasTypeScript,
|
|
307
|
-
if (!(
|
|
308
|
-
const missing = [];
|
|
309
|
-
if (!hasTypeScript) {
|
|
310
|
-
missing.push("typescript");
|
|
311
|
-
}
|
|
312
|
-
if (!hasTypesBun) {
|
|
313
|
-
missing.push("@types/bun");
|
|
314
|
-
}
|
|
329
|
+
const { hasTypeScript, hasNativePreview } = await checkRequiredDependencies(pkg.path);
|
|
330
|
+
if (!(hasNativePreview || hasTypeScript)) {
|
|
315
331
|
throw new Error(
|
|
316
|
-
`Package ${pkg.name} has tsconfig.json but
|
|
332
|
+
`Package ${pkg.name} has tsconfig.json but neither "@typescript/native-preview" nor "typescript" is listed in dependencies or devDependencies. Please add one of them to this package's package.json (then run bun install).`
|
|
317
333
|
);
|
|
318
334
|
}
|
|
335
|
+
const preferTsgo = hasNativePreview;
|
|
319
336
|
if (cache) {
|
|
320
337
|
const shouldSkip = await cache.shouldSkipPackage(pkg);
|
|
321
338
|
if (shouldSkip) {
|
|
@@ -342,32 +359,35 @@ const runTscOnPackage = async (pkg, monorepoRoot, options = {}) => {
|
|
|
342
359
|
logger.info(`\u{1F50D} Checking ${pkg.name}...`);
|
|
343
360
|
}
|
|
344
361
|
try {
|
|
345
|
-
const
|
|
346
|
-
|
|
362
|
+
const { executable: tsExecutable, usedTsgo } = await findTypeScriptExecutable(
|
|
363
|
+
pkg.path,
|
|
364
|
+
preferTsgo
|
|
365
|
+
);
|
|
366
|
+
if (!tsExecutable) {
|
|
347
367
|
throw new Error(
|
|
348
|
-
"
|
|
368
|
+
`${preferTsgo ? "tsgo" : "tsc"} not found. Skipping package (install ${preferTsgo ? "@typescript/native-preview" : "typescript"} locally or globally to enable type checking).`
|
|
349
369
|
);
|
|
350
370
|
}
|
|
351
371
|
if (verbose) {
|
|
352
|
-
const
|
|
372
|
+
const normalizedExecPath = resolve(tsExecutable);
|
|
353
373
|
const normalizedPackagePath = resolve(pkg.path);
|
|
354
374
|
const normalizedMonorepoRoot = resolve(monorepoRoot);
|
|
355
|
-
const relativeToPackage = relative(normalizedPackagePath,
|
|
356
|
-
const relativeToMonorepo = relative(normalizedMonorepoRoot,
|
|
375
|
+
const relativeToPackage = relative(normalizedPackagePath, normalizedExecPath);
|
|
376
|
+
const relativeToMonorepo = relative(normalizedMonorepoRoot, normalizedExecPath);
|
|
357
377
|
let source;
|
|
358
|
-
if (
|
|
378
|
+
if (normalizedExecPath.startsWith(normalizedPackagePath)) {
|
|
359
379
|
source = `local (${relativeToPackage})`;
|
|
360
|
-
} else if (
|
|
380
|
+
} else if (normalizedExecPath.startsWith(normalizedMonorepoRoot)) {
|
|
361
381
|
source = `monorepo root (${relativeToMonorepo})`;
|
|
362
382
|
} else {
|
|
363
|
-
source = `global (${
|
|
383
|
+
source = `global (${tsExecutable})`;
|
|
364
384
|
}
|
|
365
|
-
logger.info(` Using tsc: ${source}`);
|
|
385
|
+
logger.info(` Using ${usedTsgo ? "tsgo" : "tsc"}: ${source}`);
|
|
366
386
|
}
|
|
367
387
|
const result = await runTscCommand(pkg.path, {
|
|
368
388
|
incremental,
|
|
369
389
|
buildMode,
|
|
370
|
-
|
|
390
|
+
preferTsgo
|
|
371
391
|
});
|
|
372
392
|
const output = result.stdout + result.stderr;
|
|
373
393
|
const filteredOutput = filterOutputLines(output, pkg.path, monorepoRoot);
|
|
@@ -404,9 +424,9 @@ const runTscOnPackage = async (pkg, monorepoRoot, options = {}) => {
|
|
|
404
424
|
return tscResult;
|
|
405
425
|
} catch (error) {
|
|
406
426
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
407
|
-
if (errorMessage.includes("
|
|
427
|
+
if (errorMessage.includes(" not found") || errorMessage.includes("Executable not found")) {
|
|
408
428
|
if (verbose) {
|
|
409
|
-
logger.info(`\u23ED\uFE0F Skipping ${pkg.name} (TypeScript not installed in this package)`);
|
|
429
|
+
logger.info(`\u23ED\uFE0F Skipping ${pkg.name} (TypeScript compiler not installed in this package)`);
|
|
410
430
|
}
|
|
411
431
|
return {
|
|
412
432
|
package: pkg,
|
|
@@ -446,14 +466,11 @@ const collectAllResults = async (packages, monorepoRoot, options = {}, cache) =>
|
|
|
446
466
|
incremental = true,
|
|
447
467
|
buildMode = false
|
|
448
468
|
} = options;
|
|
449
|
-
if (!verbose) {
|
|
450
|
-
logger.info(`Processing ${packages.length} packages...`);
|
|
451
|
-
}
|
|
452
469
|
try {
|
|
453
470
|
const tscResults = await pMap(
|
|
454
471
|
packages,
|
|
455
472
|
async (pkg, index) => {
|
|
456
|
-
if (
|
|
473
|
+
if (verbose) {
|
|
457
474
|
logger.info(`Processing ${pkg.name} (${index + 1}/${packages.length})...`);
|
|
458
475
|
}
|
|
459
476
|
return runTscOnPackage(pkg, monorepoRoot, {
|
|
@@ -655,8 +672,7 @@ export const runTscOnAllPackages = async (ignore, cwd, options = {}) => {
|
|
|
655
672
|
}
|
|
656
673
|
const { stopOnError = false } = options;
|
|
657
674
|
logger.info(
|
|
658
|
-
`
|
|
659
|
-
`
|
|
675
|
+
`Checking ${packages.length} packages (concurrency: ${concurrency}, stopOnError: ${stopOnError})...`
|
|
660
676
|
);
|
|
661
677
|
if (verbose) {
|
|
662
678
|
logger.info("\u{1F680} Starting TypeScript checks...\n");
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { logger } from "@reliverse/relinka";
|
|
2
|
+
import { defineCommand, option } from "@reliverse/rempts-core";
|
|
3
|
+
import { type } from "arktype";
|
|
4
|
+
import { findUnusedDependencies } from "./impl.js";
|
|
5
|
+
export default defineCommand({
|
|
6
|
+
description: "Find unused dependencies in package.json files",
|
|
7
|
+
options: {
|
|
8
|
+
// Target package selection
|
|
9
|
+
target: option(type("string | undefined"), {
|
|
10
|
+
short: "t",
|
|
11
|
+
description: "Target workspace package(s) (from workspaces.packages). Use '.' for current directory package. Supports multiple packages (space-separated) and glob patterns."
|
|
12
|
+
}),
|
|
13
|
+
package: option(type("string | undefined"), {
|
|
14
|
+
description: "Target workspace package(s) (alias for --target). Use '.' for current directory package. Supports multiple packages (space-separated) and glob patterns."
|
|
15
|
+
}),
|
|
16
|
+
pkg: option(type("string | undefined"), {
|
|
17
|
+
description: "Target workspace package(s) (alias for --target). Use '.' for current directory package. Supports multiple packages (space-separated) and glob patterns."
|
|
18
|
+
}),
|
|
19
|
+
w: option(type("boolean | undefined"), {
|
|
20
|
+
description: "Check unused dependencies in root package.json"
|
|
21
|
+
}),
|
|
22
|
+
// Scope filtering
|
|
23
|
+
scope: option(type("'dev'|'prod'|'peer'|'optional' | undefined"), {
|
|
24
|
+
short: "s",
|
|
25
|
+
description: "Check specific dependency scope: dev, prod, peer, optional. If not specified, checks all scopes."
|
|
26
|
+
}),
|
|
27
|
+
dev: option(type("boolean | undefined"), {
|
|
28
|
+
short: "D",
|
|
29
|
+
description: "Check only devDependencies (shorthand for --scope dev)"
|
|
30
|
+
}),
|
|
31
|
+
prod: option(type("boolean | undefined"), {
|
|
32
|
+
short: "P",
|
|
33
|
+
description: "Check only dependencies (shorthand for --scope prod)"
|
|
34
|
+
}),
|
|
35
|
+
peer: option(type("boolean | undefined"), {
|
|
36
|
+
short: "R",
|
|
37
|
+
description: "Check only peerDependencies (shorthand for --scope peer)"
|
|
38
|
+
}),
|
|
39
|
+
optional: option(type("boolean | undefined"), {
|
|
40
|
+
short: "O",
|
|
41
|
+
description: "Check only optionalDependencies (shorthand for --scope optional)"
|
|
42
|
+
}),
|
|
43
|
+
// Analysis options
|
|
44
|
+
ignore: option(type("string | undefined"), {
|
|
45
|
+
short: "i",
|
|
46
|
+
description: "Comma-separated list of package names to ignore when checking for unused dependencies"
|
|
47
|
+
}),
|
|
48
|
+
includePeer: option(type("boolean | undefined"), {
|
|
49
|
+
description: "Include peerDependencies in the analysis (default: false)",
|
|
50
|
+
default: false
|
|
51
|
+
}),
|
|
52
|
+
// Other options
|
|
53
|
+
cwd: option(type("string | undefined"), {
|
|
54
|
+
description: "Working directory (monorepo root)"
|
|
55
|
+
}),
|
|
56
|
+
verbose: option(type("boolean | undefined"), {
|
|
57
|
+
short: "v",
|
|
58
|
+
description: "Verbose output"
|
|
59
|
+
})
|
|
60
|
+
},
|
|
61
|
+
handler: async ({ flags }) => {
|
|
62
|
+
try {
|
|
63
|
+
if (typeof process.versions.bun === "undefined") {
|
|
64
|
+
logger.error("\u274C This command requires Bun runtime.");
|
|
65
|
+
logger.error("Please run this command using Bun: bun dler unused");
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
logger.log("\u{1F50D} Finding unused dependencies...");
|
|
69
|
+
let scope;
|
|
70
|
+
if (flags.scope) {
|
|
71
|
+
scope = flags.scope;
|
|
72
|
+
} else if (flags.dev) {
|
|
73
|
+
scope = "dev";
|
|
74
|
+
} else if (flags.peer) {
|
|
75
|
+
scope = "peer";
|
|
76
|
+
} else if (flags.optional) {
|
|
77
|
+
scope = "optional";
|
|
78
|
+
}
|
|
79
|
+
const ignoreList = flags.ignore ? flags.ignore.split(",").map((pkg) => pkg.trim()).filter(Boolean) : void 0;
|
|
80
|
+
const options = {
|
|
81
|
+
target: flags.target || flags.package || flags.pkg,
|
|
82
|
+
w: flags.w,
|
|
83
|
+
scope,
|
|
84
|
+
ignore: ignoreList,
|
|
85
|
+
includePeer: flags.includePeer ?? false,
|
|
86
|
+
cwd: flags.cwd || void 0,
|
|
87
|
+
verbose: flags.verbose ?? false
|
|
88
|
+
};
|
|
89
|
+
await findUnusedDependencies(options);
|
|
90
|
+
} catch (error) {
|
|
91
|
+
logger.error("\n\u274C Failed to find unused dependencies:");
|
|
92
|
+
if (error instanceof Error) {
|
|
93
|
+
logger.error(error.message);
|
|
94
|
+
} else {
|
|
95
|
+
logger.error(String(error));
|
|
96
|
+
}
|
|
97
|
+
logger.log("");
|
|
98
|
+
logger.log("\u{1F4A1} Tips:");
|
|
99
|
+
logger.log(" \u2022 Ensure you're in a valid project directory with package.json");
|
|
100
|
+
logger.log(" \u2022 Use --verbose flag for more detailed output");
|
|
101
|
+
logger.log(" \u2022 Use --ignore flag to exclude specific packages from analysis");
|
|
102
|
+
process.exit(1);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface UnusedOptions {
|
|
2
|
+
target?: string;
|
|
3
|
+
w?: boolean;
|
|
4
|
+
scope?: "dev" | "prod" | "peer" | "optional";
|
|
5
|
+
ignore?: string[];
|
|
6
|
+
includePeer: boolean;
|
|
7
|
+
cwd?: string;
|
|
8
|
+
verbose: boolean;
|
|
9
|
+
}
|
|
10
|
+
export interface MonorepoInfo {
|
|
11
|
+
isMonorepo: boolean;
|
|
12
|
+
rootPath: string;
|
|
13
|
+
rootPackageJson: any;
|
|
14
|
+
workspacePackages?: string[];
|
|
15
|
+
}
|
|
16
|
+
export declare function findUnusedDependencies(options: UnusedOptions): Promise<void>;
|