@macrulez/devtoolz 0.1.0 → 0.2.0
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/README.md +164 -3
- package/dist/cli.js +233 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/circular-imports/core.d.ts +15 -0
- package/dist/commands/circular-imports/core.js +95 -0
- package/dist/commands/circular-imports/core.js.map +1 -0
- package/dist/commands/circular-imports/report.d.ts +3 -0
- package/dist/commands/circular-imports/report.js +41 -0
- package/dist/commands/circular-imports/report.js.map +1 -0
- package/dist/commands/circular-imports/run.d.ts +19 -0
- package/dist/commands/circular-imports/run.js +29 -0
- package/dist/commands/circular-imports/run.js.map +1 -0
- package/dist/commands/dead-exports/core.d.ts +1 -1
- package/dist/commands/dead-exports/core.js +2 -2
- package/dist/commands/dead-exports/core.js.map +1 -1
- package/dist/commands/dead-exports/entry.d.ts +0 -1
- package/dist/commands/dead-exports/entry.js +1 -14
- package/dist/commands/dead-exports/entry.js.map +1 -1
- package/dist/commands/dead-exports/run.js +3 -2
- package/dist/commands/dead-exports/run.js.map +1 -1
- package/dist/commands/empty-catch/core.d.ts +8 -0
- package/dist/commands/empty-catch/core.js +61 -0
- package/dist/commands/empty-catch/core.js.map +1 -0
- package/dist/commands/empty-catch/report.d.ts +3 -0
- package/dist/commands/empty-catch/report.js +27 -0
- package/dist/commands/empty-catch/report.js.map +1 -0
- package/dist/commands/empty-catch/run.d.ts +17 -0
- package/dist/commands/empty-catch/run.js +34 -0
- package/dist/commands/empty-catch/run.js.map +1 -0
- package/dist/commands/empty-catch/vue.d.ts +2 -0
- package/dist/commands/empty-catch/vue.js +16 -0
- package/dist/commands/empty-catch/vue.js.map +1 -0
- package/dist/commands/orphan-tests/core.d.ts +9 -0
- package/dist/commands/orphan-tests/core.js +42 -0
- package/dist/commands/orphan-tests/core.js.map +1 -0
- package/dist/commands/orphan-tests/report.d.ts +3 -0
- package/dist/commands/orphan-tests/report.js +30 -0
- package/dist/commands/orphan-tests/report.js.map +1 -0
- package/dist/commands/orphan-tests/run.d.ts +25 -0
- package/dist/commands/orphan-tests/run.js +55 -0
- package/dist/commands/orphan-tests/run.js.map +1 -0
- package/dist/commands/readme-check/run.js +8 -3
- package/dist/commands/readme-check/run.js.map +1 -1
- package/dist/commands/scripts-check/core.d.ts +18 -0
- package/dist/commands/scripts-check/core.js +121 -0
- package/dist/commands/scripts-check/core.js.map +1 -0
- package/dist/commands/scripts-check/report.d.ts +3 -0
- package/dist/commands/scripts-check/report.js +34 -0
- package/dist/commands/scripts-check/report.js.map +1 -0
- package/dist/commands/scripts-check/run.d.ts +15 -0
- package/dist/commands/scripts-check/run.js +81 -0
- package/dist/commands/scripts-check/run.js.map +1 -0
- package/dist/commands/stale-ts-ignore/check.d.ts +23 -0
- package/dist/commands/stale-ts-ignore/check.js +104 -0
- package/dist/commands/stale-ts-ignore/check.js.map +1 -0
- package/dist/commands/stale-ts-ignore/core.d.ts +11 -0
- package/dist/commands/stale-ts-ignore/core.js +42 -0
- package/dist/commands/stale-ts-ignore/core.js.map +1 -0
- package/dist/commands/stale-ts-ignore/report.d.ts +3 -0
- package/dist/commands/stale-ts-ignore/report.js +30 -0
- package/dist/commands/stale-ts-ignore/report.js.map +1 -0
- package/dist/commands/stale-ts-ignore/run.d.ts +23 -0
- package/dist/commands/stale-ts-ignore/run.js +101 -0
- package/dist/commands/stale-ts-ignore/run.js.map +1 -0
- package/dist/commands/stale-ts-ignore/vue.d.ts +9 -0
- package/dist/commands/stale-ts-ignore/vue.js +16 -0
- package/dist/commands/stale-ts-ignore/vue.js.map +1 -0
- package/dist/commands/strip-comments/core.js +2 -56
- package/dist/commands/strip-comments/core.js.map +1 -1
- package/dist/commands/todo-report/core.d.ts +16 -0
- package/dist/commands/todo-report/core.js +112 -0
- package/dist/commands/todo-report/core.js.map +1 -0
- package/dist/commands/todo-report/report.d.ts +3 -0
- package/dist/commands/todo-report/report.js +31 -0
- package/dist/commands/todo-report/report.js.map +1 -0
- package/dist/commands/todo-report/run.d.ts +22 -0
- package/dist/commands/todo-report/run.js +41 -0
- package/dist/commands/todo-report/run.js.map +1 -0
- package/dist/commands/todo-report/vue.d.ts +2 -0
- package/dist/commands/todo-report/vue.js +71 -0
- package/dist/commands/todo-report/vue.js.map +1 -0
- package/dist/commands/unused-deps/config-files.d.ts +9 -0
- package/dist/commands/unused-deps/config-files.js +64 -0
- package/dist/commands/unused-deps/config-files.js.map +1 -0
- package/dist/commands/unused-deps/core.d.ts +25 -0
- package/dist/commands/unused-deps/core.js +121 -0
- package/dist/commands/unused-deps/core.js.map +1 -0
- package/dist/commands/unused-deps/disk-resolve.d.ts +11 -0
- package/dist/commands/unused-deps/disk-resolve.js +40 -0
- package/dist/commands/unused-deps/disk-resolve.js.map +1 -0
- package/dist/commands/unused-deps/package-name.d.ts +8 -0
- package/dist/commands/unused-deps/package-name.js +20 -0
- package/dist/commands/unused-deps/package-name.js.map +1 -0
- package/dist/commands/unused-deps/report.d.ts +3 -0
- package/dist/commands/unused-deps/report.js +32 -0
- package/dist/commands/unused-deps/report.js.map +1 -0
- package/dist/commands/unused-deps/run.d.ts +18 -0
- package/dist/commands/unused-deps/run.js +68 -0
- package/dist/commands/unused-deps/run.js.map +1 -0
- package/dist/index.d.ts +51 -5
- package/dist/index.js +33 -3
- package/dist/index.js.map +1 -1
- package/dist/utils/escape-regexp.d.ts +1 -0
- package/dist/utils/escape-regexp.js +4 -0
- package/dist/utils/escape-regexp.js.map +1 -0
- package/dist/utils/find-comments.d.ts +10 -0
- package/dist/utils/find-comments.js +62 -0
- package/dist/utils/find-comments.js.map +1 -0
- package/dist/utils/find-package-dir.d.ts +2 -0
- package/dist/utils/find-package-dir.js +15 -0
- package/dist/utils/find-package-dir.js.map +1 -0
- package/dist/utils/line-of.d.ts +2 -0
- package/dist/utils/line-of.js +12 -0
- package/dist/utils/line-of.js.map +1 -0
- package/dist/utils/load-tsconfig.d.ts +20 -0
- package/dist/utils/load-tsconfig.js +33 -0
- package/dist/utils/load-tsconfig.js.map +1 -0
- package/dist/utils/parse-module.d.ts +32 -0
- package/dist/utils/parse-module.js +178 -0
- package/dist/utils/parse-module.js.map +1 -0
- package/dist/utils/resolve-specifier.d.ts +15 -0
- package/dist/utils/resolve-specifier.js +63 -0
- package/dist/utils/resolve-specifier.js.map +1 -0
- package/dist/utils/walk.js +20 -1
- package/dist/utils/walk.js.map +1 -1
- package/dist/utils/workspace.d.ts +14 -0
- package/dist/utils/workspace.js +101 -0
- package/dist/utils/workspace.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// `.vue` handling, same split as strip-comments/vue.ts: the `<script>`
|
|
2
|
+
// block goes through the real TS-parser path (core.ts), and the
|
|
3
|
+
// `<template>` block's `<!-- -->` comments are matched by regex — no full
|
|
4
|
+
// SFC template parser here, so a `<!-- -->`-looking sequence inside a
|
|
5
|
+
// bound attribute string would be misread as a real comment. Same known,
|
|
6
|
+
// documented limitation as strip-comments.
|
|
7
|
+
import { analyzeTodoReport, buildTagMatcher, collectNoteText, DEFAULT_TAGS, } from './core.js';
|
|
8
|
+
const SCRIPT_RE = /(<script[^>]*>)([\s\S]*?)(<\/script>)/;
|
|
9
|
+
const TEMPLATE_RE = /(<template[^>]*>)([\s\S]*?)(<\/template>)/;
|
|
10
|
+
const TEMPLATE_COMMENT_RE = /<!--[\s\S]*?-->/g;
|
|
11
|
+
function lineAt(text, index) {
|
|
12
|
+
return (text.slice(0, index).match(/\n/g) ?? []).length;
|
|
13
|
+
}
|
|
14
|
+
function cleanTemplateLine(line) {
|
|
15
|
+
return line
|
|
16
|
+
.replace(/^\s*<!--/, '')
|
|
17
|
+
.replace(/-->\s*$/, '')
|
|
18
|
+
.trim();
|
|
19
|
+
}
|
|
20
|
+
function findTemplateTodos(body, tags) {
|
|
21
|
+
const findings = [];
|
|
22
|
+
const { pattern, canonical } = buildTagMatcher(tags);
|
|
23
|
+
for (const match of body.matchAll(TEMPLATE_COMMENT_RE)) {
|
|
24
|
+
const start = match.index;
|
|
25
|
+
const rawLines = match[0].split('\n');
|
|
26
|
+
let lineStart = start;
|
|
27
|
+
let i = 0;
|
|
28
|
+
while (i < rawLines.length) {
|
|
29
|
+
const rawLine = rawLines[i];
|
|
30
|
+
const m = pattern.exec(rawLine);
|
|
31
|
+
if (m) {
|
|
32
|
+
const { text: noteText, consumedThrough } = collectNoteText(rawLines, i, cleanTemplateLine, pattern);
|
|
33
|
+
findings.push({
|
|
34
|
+
line: lineAt(body, lineStart + m.index) + 1,
|
|
35
|
+
column: lineStart + m.index - body.lastIndexOf('\n', lineStart + m.index),
|
|
36
|
+
tag: canonical.get(m[0].toLowerCase()) ?? m[0],
|
|
37
|
+
text: noteText,
|
|
38
|
+
});
|
|
39
|
+
for (let k = i; k < consumedThrough; k++)
|
|
40
|
+
lineStart += rawLines[k].length + 1;
|
|
41
|
+
i = consumedThrough;
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
lineStart += rawLine.length + 1;
|
|
45
|
+
i++;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return findings;
|
|
49
|
+
}
|
|
50
|
+
export function analyzeTodoReportVue(text, file, tags = DEFAULT_TAGS) {
|
|
51
|
+
const findings = [];
|
|
52
|
+
const scriptMatch = text.match(SCRIPT_RE);
|
|
53
|
+
if (scriptMatch) {
|
|
54
|
+
const [, , body] = scriptMatch;
|
|
55
|
+
const offset = lineAt(text, scriptMatch.index);
|
|
56
|
+
for (const f of analyzeTodoReport(body, file.replace(/\.vue$/, '.ts'), tags)) {
|
|
57
|
+
findings.push({ ...f, line: f.line + offset });
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const templateMatch = text.match(TEMPLATE_RE);
|
|
61
|
+
if (templateMatch) {
|
|
62
|
+
const [, , body] = templateMatch;
|
|
63
|
+
const offset = lineAt(text, templateMatch.index);
|
|
64
|
+
for (const f of findTemplateTodos(body, tags)) {
|
|
65
|
+
findings.push({ ...f, line: f.line + offset });
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
findings.sort((a, b) => a.line - b.line || a.column - b.column);
|
|
69
|
+
return findings;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=vue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vue.js","sourceRoot":"","sources":["../../../src/commands/todo-report/vue.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare function readConfigFilesText(packageDir: string): string;
|
|
2
|
+
/**
|
|
3
|
+
* Whether `name` appears as its own token anywhere in `text` — either
|
|
4
|
+
* quoted (`extends: 'stylelint-config-standard'`) or a bare identifier
|
|
5
|
+
* (`plugins: { autoprefixer: {} }`). Bounded on both sides so a
|
|
6
|
+
* different package that merely contains `name` as a substring
|
|
7
|
+
* (`autoprefixer-wrapper`, `@scope/autoprefixer`) doesn't count.
|
|
8
|
+
*/
|
|
9
|
+
export declare function textReferencesPackage(text: string, name: string): boolean;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { escapeRegExp } from '../../utils/escape-regexp.js';
|
|
4
|
+
// Config files commonly reference a dependency by name — a vitest.config.ts's
|
|
5
|
+
// `environment: 'happy-dom'` (a quoted string), a postcss.config.js's
|
|
6
|
+
// `plugins: { autoprefixer: {} }` (a bare object key), never a JS
|
|
7
|
+
// `import`. No import-statement parse can see either shape; this is a
|
|
8
|
+
// deliberately narrow, explicit-filename text scan instead of guessing
|
|
9
|
+
// at every possible config format. Only the package root is checked
|
|
10
|
+
// (not recursive) — the overwhelming common location for all of these
|
|
11
|
+
// in a real project.
|
|
12
|
+
const CONFIG_FILENAMES = [
|
|
13
|
+
'vitest.config.ts',
|
|
14
|
+
'vitest.config.js',
|
|
15
|
+
'vitest.config.mts',
|
|
16
|
+
'vitest.config.mjs',
|
|
17
|
+
'vite.config.ts',
|
|
18
|
+
'vite.config.js',
|
|
19
|
+
'vite.config.mts',
|
|
20
|
+
'.eslintrc.json',
|
|
21
|
+
'.eslintrc.js',
|
|
22
|
+
'.eslintrc.cjs',
|
|
23
|
+
'eslint.config.js',
|
|
24
|
+
'eslint.config.mjs',
|
|
25
|
+
'eslint.config.ts',
|
|
26
|
+
'.stylelintrc',
|
|
27
|
+
'.stylelintrc.json',
|
|
28
|
+
'.stylelintrc.js',
|
|
29
|
+
'stylelint.config.js',
|
|
30
|
+
'stylelint.config.mjs',
|
|
31
|
+
'postcss.config.js',
|
|
32
|
+
'postcss.config.cjs',
|
|
33
|
+
'postcss.config.mjs',
|
|
34
|
+
'nuxt.config.ts',
|
|
35
|
+
'tsconfig.json',
|
|
36
|
+
'tsconfig.build.json',
|
|
37
|
+
];
|
|
38
|
+
export function readConfigFilesText(packageDir) {
|
|
39
|
+
const chunks = [];
|
|
40
|
+
for (const filename of CONFIG_FILENAMES) {
|
|
41
|
+
const path = join(packageDir, filename);
|
|
42
|
+
if (!existsSync(path))
|
|
43
|
+
continue;
|
|
44
|
+
try {
|
|
45
|
+
chunks.push(readFileSync(path, 'utf8'));
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
// unreadable — skip rather than fail the whole command over one config file
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return chunks.join('\n');
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Whether `name` appears as its own token anywhere in `text` — either
|
|
55
|
+
* quoted (`extends: 'stylelint-config-standard'`) or a bare identifier
|
|
56
|
+
* (`plugins: { autoprefixer: {} }`). Bounded on both sides so a
|
|
57
|
+
* different package that merely contains `name` as a substring
|
|
58
|
+
* (`autoprefixer-wrapper`, `@scope/autoprefixer`) doesn't count.
|
|
59
|
+
*/
|
|
60
|
+
export function textReferencesPackage(text, name) {
|
|
61
|
+
const pattern = new RegExp(`(?<![\\w@./-])${escapeRegExp(name)}(?![\\w-])`);
|
|
62
|
+
return pattern.test(text);
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=config-files.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-files.js","sourceRoot":"","sources":["../../../src/commands/unused-deps/config-files.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAClD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAE3D,8EAA8E;AAC9E,sEAAsE;AACtE,kEAAkE;AAClE,sEAAsE;AACtE,uEAAuE;AACvE,oEAAoE;AACpE,sEAAsE;AACtE,qBAAqB;AACrB,MAAM,gBAAgB,GAAG;IACvB,kBAAkB;IAClB,kBAAkB;IAClB,mBAAmB;IACnB,mBAAmB;IACnB,gBAAgB;IAChB,gBAAgB;IAChB,iBAAiB;IACjB,gBAAgB;IAChB,cAAc;IACd,eAAe;IACf,kBAAkB;IAClB,mBAAmB;IACnB,kBAAkB;IAClB,cAAc;IACd,mBAAmB;IACnB,iBAAiB;IACjB,qBAAqB;IACrB,sBAAsB;IACtB,mBAAmB;IACnB,oBAAoB;IACpB,oBAAoB;IACpB,gBAAgB;IAChB,eAAe;IACf,qBAAqB;CACtB,CAAA;AAED,MAAM,UAAU,mBAAmB,CAAC,UAAkB;IACpD,MAAM,MAAM,GAAa,EAAE,CAAA;IAC3B,KAAK,MAAM,QAAQ,IAAI,gBAAgB,EAAE,CAAC;QACxC,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAA;QACvC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,SAAQ;QAC/B,IAAI,CAAC;YACH,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAA;QACzC,CAAC;QAAC,MAAM,CAAC;YACP,4EAA4E;QAC9E,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AAC1B,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAAY,EAAE,IAAY;IAC9D,MAAM,OAAO,GAAG,IAAI,MAAM,CAAC,iBAAiB,YAAY,CAAC,IAAI,CAAC,YAAY,CAAC,CAAA;IAC3E,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AAC3B,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
declare const DEPENDENCY_SECTIONS: readonly ["dependencies", "devDependencies", "optionalDependencies"];
|
|
2
|
+
type DependencySection = (typeof DEPENDENCY_SECTIONS)[number];
|
|
3
|
+
export interface UnusedDepsFinding {
|
|
4
|
+
kind: 'unused' | 'phantom';
|
|
5
|
+
name: string;
|
|
6
|
+
/** which package.json section an 'unused' finding was declared in */
|
|
7
|
+
section?: DependencySection;
|
|
8
|
+
/** where a 'phantom' finding actually resolved from on disk */
|
|
9
|
+
resolvedFrom?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface UnusedDepsAnalysis {
|
|
12
|
+
findings: UnusedDepsFinding[];
|
|
13
|
+
filesAnalyzed: number;
|
|
14
|
+
}
|
|
15
|
+
export interface AnalyzeOptions {
|
|
16
|
+
packageDir: string;
|
|
17
|
+
pkg: Record<string, unknown>;
|
|
18
|
+
/** also check packages that are structurally undetectable as "used" by any means this command can see. default false */
|
|
19
|
+
strict: boolean;
|
|
20
|
+
ignorePackages: Set<string>;
|
|
21
|
+
/** names of sibling packages in the same workspace — used-but-undeclared is expected for these, never "phantom" */
|
|
22
|
+
workspacePackageNames: Set<string>;
|
|
23
|
+
}
|
|
24
|
+
export declare function analyzeUnusedDeps(files: string[], options: AnalyzeOptions): UnusedDepsAnalysis;
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { analyzeFile } from '../../utils/parse-module.js';
|
|
3
|
+
import { packageNameFromSpecifier } from './package-name.js';
|
|
4
|
+
import { declaredBinNames, resolvePackageDir } from './disk-resolve.js';
|
|
5
|
+
import { readConfigFilesText, textReferencesPackage } from './config-files.js';
|
|
6
|
+
const DEPENDENCY_SECTIONS = ['dependencies', 'devDependencies', 'optionalDependencies'];
|
|
7
|
+
// Packages that are near-universally legitimate to have installed
|
|
8
|
+
// without ever appearing as an `import`, a script token, or even a
|
|
9
|
+
// string in a config file — either genuinely ambient (`@types/*`, picked
|
|
10
|
+
// up by TypeScript automatically) or inferred from a config VALUE by a
|
|
11
|
+
// tool's own naming convention rather than written out in full
|
|
12
|
+
// (`coverage: { provider: 'v8' }` in a vitest config makes vitest
|
|
13
|
+
// require `@vitest/coverage-v8` itself — the full package name is never
|
|
14
|
+
// actually written anywhere a text scan could find it). `--strict`
|
|
15
|
+
// checks these too, for a manual audit.
|
|
16
|
+
function isStructurallyImplicit(name) {
|
|
17
|
+
return (name.startsWith('@types/') ||
|
|
18
|
+
name === 'typescript' ||
|
|
19
|
+
name.startsWith('@vitest/coverage-') ||
|
|
20
|
+
name === '@vitest/ui' ||
|
|
21
|
+
// Ambient type augmentation for a Nuxt module's own config/types
|
|
22
|
+
// (`defineNuxtConfig`, module hooks) — never imported by name,
|
|
23
|
+
// same structural class as @types/*.
|
|
24
|
+
name === '@nuxt/schema' ||
|
|
25
|
+
// Vite's CSS preprocessors — auto-detected by file EXTENSION
|
|
26
|
+
// (a `.scss` import triggers Vite to require `sass` if it's
|
|
27
|
+
// installed) and postcss by config file PRESENCE, neither ever
|
|
28
|
+
// spelled out by name in the project's own files. Confirmed
|
|
29
|
+
// against two real, independent packages before adding this —
|
|
30
|
+
// not a guess.
|
|
31
|
+
name === 'postcss' ||
|
|
32
|
+
name === 'sass' ||
|
|
33
|
+
name === 'less' ||
|
|
34
|
+
name === 'stylus');
|
|
35
|
+
}
|
|
36
|
+
function tokenAppearsIn(values, token) {
|
|
37
|
+
const words = values.flatMap((s) => s.split(/\s+/));
|
|
38
|
+
return words.some((w) => w === token || w.endsWith(`/${token}`) || w.endsWith(`\\${token}`));
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* A dependency invoked only by its bin name from tooling config embedded
|
|
42
|
+
* directly in package.json (`scripts`, and `lint-staged` — commonly
|
|
43
|
+
* inlined there rather than its own file) counts as used, same as an
|
|
44
|
+
* import. Checked by the package's own name AND (if installed) its
|
|
45
|
+
* declared `bin` keys, since `tsc`/`vitest`/`eslint` etc. don't always
|
|
46
|
+
* match their package name.
|
|
47
|
+
*/
|
|
48
|
+
function usedViaPackageJsonTooling(pkg, packageDir, name) {
|
|
49
|
+
const scripts = pkg.scripts && typeof pkg.scripts === 'object'
|
|
50
|
+
? Object.values(pkg.scripts)
|
|
51
|
+
: [];
|
|
52
|
+
const lintStaged = pkg['lint-staged'] && typeof pkg['lint-staged'] === 'object'
|
|
53
|
+
? Object.values(pkg['lint-staged']).flatMap((v) => Array.isArray(v) ? v : typeof v === 'string' ? [v] : [])
|
|
54
|
+
: [];
|
|
55
|
+
const values = [...scripts, ...lintStaged];
|
|
56
|
+
if (tokenAppearsIn(values, name))
|
|
57
|
+
return true;
|
|
58
|
+
return declaredBinNames(packageDir, name).some((bin) => tokenAppearsIn(values, bin));
|
|
59
|
+
}
|
|
60
|
+
export function analyzeUnusedDeps(files, options) {
|
|
61
|
+
const usedPackageNames = new Set();
|
|
62
|
+
for (const file of files) {
|
|
63
|
+
const text = readFileSync(file, 'utf8');
|
|
64
|
+
const analysis = analyzeFile(text, file);
|
|
65
|
+
for (const imp of analysis.imports) {
|
|
66
|
+
const name = packageNameFromSpecifier(imp.from);
|
|
67
|
+
if (name)
|
|
68
|
+
usedPackageNames.add(name);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
const declared = new Map();
|
|
72
|
+
const allDeclaredNames = new Set();
|
|
73
|
+
for (const section of DEPENDENCY_SECTIONS) {
|
|
74
|
+
const value = options.pkg[section];
|
|
75
|
+
if (!value || typeof value !== 'object')
|
|
76
|
+
continue;
|
|
77
|
+
for (const name of Object.keys(value)) {
|
|
78
|
+
declared.set(name, section);
|
|
79
|
+
allDeclaredNames.add(name);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
const peerDeps = options.pkg.peerDependencies && typeof options.pkg.peerDependencies === 'object'
|
|
83
|
+
? Object.keys(options.pkg.peerDependencies)
|
|
84
|
+
: [];
|
|
85
|
+
for (const name of peerDeps)
|
|
86
|
+
allDeclaredNames.add(name);
|
|
87
|
+
// A package importing itself by its own published name (the same
|
|
88
|
+
// self-reference readme-check resolves) is never a phantom dependency
|
|
89
|
+
// — it can't sensibly be its own devDependency, so it's exempted
|
|
90
|
+
// explicitly rather than expected to appear in package.json at all.
|
|
91
|
+
if (typeof options.pkg.name === 'string')
|
|
92
|
+
allDeclaredNames.add(options.pkg.name);
|
|
93
|
+
const configText = readConfigFilesText(options.packageDir);
|
|
94
|
+
const findings = [];
|
|
95
|
+
for (const [name, section] of declared) {
|
|
96
|
+
if (usedPackageNames.has(name))
|
|
97
|
+
continue;
|
|
98
|
+
if (options.ignorePackages.has(name))
|
|
99
|
+
continue;
|
|
100
|
+
if (!options.strict && isStructurallyImplicit(name))
|
|
101
|
+
continue;
|
|
102
|
+
if (usedViaPackageJsonTooling(options.pkg, options.packageDir, name))
|
|
103
|
+
continue;
|
|
104
|
+
if (textReferencesPackage(configText, name))
|
|
105
|
+
continue;
|
|
106
|
+
findings.push({ kind: 'unused', name, section });
|
|
107
|
+
}
|
|
108
|
+
for (const name of usedPackageNames) {
|
|
109
|
+
if (allDeclaredNames.has(name))
|
|
110
|
+
continue;
|
|
111
|
+
if (options.ignorePackages.has(name))
|
|
112
|
+
continue;
|
|
113
|
+
if (options.workspacePackageNames.has(name))
|
|
114
|
+
continue;
|
|
115
|
+
const resolvedFrom = resolvePackageDir(options.packageDir, name);
|
|
116
|
+
if (resolvedFrom)
|
|
117
|
+
findings.push({ kind: 'phantom', name, resolvedFrom });
|
|
118
|
+
}
|
|
119
|
+
return { findings, filesAnalyzed: files.length };
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=core.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core.js","sourceRoot":"","sources":["../../../src/commands/unused-deps/core.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Walks up from `fromDir` looking for `node_modules/<packageName>` —
|
|
3
|
+
* npm/yarn/pnpm all create this top-level symlink/directory for a
|
|
4
|
+
* package that's actually installed and resolvable, even when pnpm's
|
|
5
|
+
* real content lives in a `.pnpm` store elsewhere. Returns the resolved
|
|
6
|
+
* directory, or null if the package isn't installed anywhere up the
|
|
7
|
+
* tree (a broken import, not this command's concern — see core.ts).
|
|
8
|
+
*/
|
|
9
|
+
export declare function resolvePackageDir(fromDir: string, packageName: string): string | null;
|
|
10
|
+
/** The bin command name(s) a package declares in its own package.json, if it's installed and readable. */
|
|
11
|
+
export declare function declaredBinNames(fromDir: string, packageName: string): string[];
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { dirname, join, resolve } from 'node:path';
|
|
3
|
+
/**
|
|
4
|
+
* Walks up from `fromDir` looking for `node_modules/<packageName>` —
|
|
5
|
+
* npm/yarn/pnpm all create this top-level symlink/directory for a
|
|
6
|
+
* package that's actually installed and resolvable, even when pnpm's
|
|
7
|
+
* real content lives in a `.pnpm` store elsewhere. Returns the resolved
|
|
8
|
+
* directory, or null if the package isn't installed anywhere up the
|
|
9
|
+
* tree (a broken import, not this command's concern — see core.ts).
|
|
10
|
+
*/
|
|
11
|
+
export function resolvePackageDir(fromDir, packageName) {
|
|
12
|
+
let dir = resolve(fromDir);
|
|
13
|
+
for (;;) {
|
|
14
|
+
const candidate = join(dir, 'node_modules', packageName);
|
|
15
|
+
if (existsSync(candidate))
|
|
16
|
+
return candidate;
|
|
17
|
+
const parent = dirname(dir);
|
|
18
|
+
if (parent === dir)
|
|
19
|
+
return null;
|
|
20
|
+
dir = parent;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/** The bin command name(s) a package declares in its own package.json, if it's installed and readable. */
|
|
24
|
+
export function declaredBinNames(fromDir, packageName) {
|
|
25
|
+
const pkgDir = resolvePackageDir(fromDir, packageName);
|
|
26
|
+
if (!pkgDir)
|
|
27
|
+
return [];
|
|
28
|
+
try {
|
|
29
|
+
const pkg = JSON.parse(readFileSync(join(pkgDir, 'package.json'), 'utf8'));
|
|
30
|
+
if (typeof pkg.bin === 'string')
|
|
31
|
+
return [packageName];
|
|
32
|
+
if (pkg.bin && typeof pkg.bin === 'object')
|
|
33
|
+
return Object.keys(pkg.bin);
|
|
34
|
+
return [];
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return [];
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=disk-resolve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"disk-resolve.js","sourceRoot":"","sources":["../../../src/commands/unused-deps/disk-resolve.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAClD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAElD;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAe,EAAE,WAAmB;IACpE,IAAI,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IAC1B,SAAS,CAAC;QACR,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,cAAc,EAAE,WAAW,CAAC,CAAA;QACxD,IAAI,UAAU,CAAC,SAAS,CAAC;YAAE,OAAO,SAAS,CAAA;QAC3C,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAA;QAC3B,IAAI,MAAM,KAAK,GAAG;YAAE,OAAO,IAAI,CAAA;QAC/B,GAAG,GAAG,MAAM,CAAA;IACd,CAAC;AACH,CAAC;AAED,0GAA0G;AAC1G,MAAM,UAAU,gBAAgB,CAAC,OAAe,EAAE,WAAmB;IACnE,MAAM,MAAM,GAAG,iBAAiB,CAAC,OAAO,EAAE,WAAW,CAAC,CAAA;IACtD,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,CAAA;IACtB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CAGxE,CAAA;QACD,IAAI,OAAO,GAAG,CAAC,GAAG,KAAK,QAAQ;YAAE,OAAO,CAAC,WAAW,CAAC,CAAA;QACrD,IAAI,GAAG,CAAC,GAAG,IAAI,OAAO,GAAG,CAAC,GAAG,KAAK,QAAQ;YACxC,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,GAA8B,CAAC,CAAA;QACxD,OAAO,EAAE,CAAA;IACX,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAA;IACX,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extracts the real npm package name a bare import specifier resolves
|
|
3
|
+
* to — `lodash/debounce` -> `lodash`, `@scope/name/sub/path` ->
|
|
4
|
+
* `@scope/name`. Returns null for a relative/absolute specifier or a
|
|
5
|
+
* Node builtin (`fs`, `node:fs`) — neither is ever a real dependency of
|
|
6
|
+
* this project.
|
|
7
|
+
*/
|
|
8
|
+
export declare function packageNameFromSpecifier(specifier: string): string | null;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { isBuiltin } from 'node:module';
|
|
2
|
+
/**
|
|
3
|
+
* Extracts the real npm package name a bare import specifier resolves
|
|
4
|
+
* to — `lodash/debounce` -> `lodash`, `@scope/name/sub/path` ->
|
|
5
|
+
* `@scope/name`. Returns null for a relative/absolute specifier or a
|
|
6
|
+
* Node builtin (`fs`, `node:fs`) — neither is ever a real dependency of
|
|
7
|
+
* this project.
|
|
8
|
+
*/
|
|
9
|
+
export function packageNameFromSpecifier(specifier) {
|
|
10
|
+
if (specifier.startsWith('.') || specifier.startsWith('/'))
|
|
11
|
+
return null;
|
|
12
|
+
if (isBuiltin(specifier))
|
|
13
|
+
return null;
|
|
14
|
+
const parts = specifier.split('/');
|
|
15
|
+
if (specifier.startsWith('@')) {
|
|
16
|
+
return parts.length >= 2 ? `${parts[0]}/${parts[1]}` : null;
|
|
17
|
+
}
|
|
18
|
+
return parts[0] ?? null;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=package-name.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package-name.js","sourceRoot":"","sources":["../../../src/commands/unused-deps/package-name.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAEvC;;;;;;GAMG;AACH,MAAM,UAAU,wBAAwB,CAAC,SAAiB;IACxD,IAAI,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAA;IACvE,IAAI,SAAS,CAAC,SAAS,CAAC;QAAE,OAAO,IAAI,CAAA;IAErC,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAClC,IAAI,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA;IAC7D,CAAC;IACD,OAAO,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,CAAA;AACzB,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { banner, cleanCelebration } from '../../format/vibes.js';
|
|
2
|
+
import { formatFindingsRows } from '../../format/findings-list.js';
|
|
3
|
+
export function renderUnusedDepsReport(report, options = {}) {
|
|
4
|
+
if (report.error) {
|
|
5
|
+
const lines = [];
|
|
6
|
+
if (!options.quiet && !options.plain)
|
|
7
|
+
lines.push(banner(), '');
|
|
8
|
+
lines.push(`Could not run unused-deps: ${report.error}`);
|
|
9
|
+
return lines.join('\n');
|
|
10
|
+
}
|
|
11
|
+
const isClean = report.findings.length === 0;
|
|
12
|
+
if (options.quiet && isClean)
|
|
13
|
+
return '';
|
|
14
|
+
const lines = [];
|
|
15
|
+
if (!options.quiet && !options.plain)
|
|
16
|
+
lines.push(banner(), '');
|
|
17
|
+
lines.push(`Scanned ${report.filesScanned} file${report.filesScanned === 1 ? '' : 's'}.`, '');
|
|
18
|
+
if (isClean) {
|
|
19
|
+
lines.push(cleanCelebration(options));
|
|
20
|
+
return lines.join('\n');
|
|
21
|
+
}
|
|
22
|
+
lines.push(`${report.findings.length} problem${report.findings.length === 1 ? '' : 's'} found:`);
|
|
23
|
+
lines.push(...formatFindingsRows(report.findings.map((f) => ({
|
|
24
|
+
location: f.kind,
|
|
25
|
+
name: f.name,
|
|
26
|
+
tag: f.kind === 'unused'
|
|
27
|
+
? `(${f.section}, not imported anywhere)`
|
|
28
|
+
: `resolves from ${f.resolvedFrom} — not declared in package.json`,
|
|
29
|
+
})), options));
|
|
30
|
+
return lines.join('\n');
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=report.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.js","sourceRoot":"","sources":["../../../src/commands/unused-deps/report.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAqB,MAAM,uBAAuB,CAAA;AACnF,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAA;AAGlE,MAAM,UAAU,sBAAsB,CACpC,MAAwB,EACxB,UAAwB,EAAE;IAE1B,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,MAAM,KAAK,GAAa,EAAE,CAAA;QAC1B,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,KAAK;YAAE,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,CAAC,CAAA;QAC9D,KAAK,CAAC,IAAI,CAAC,8BAA8B,MAAM,CAAC,KAAK,EAAE,CAAC,CAAA;QACxD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACzB,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAA;IAC5C,IAAI,OAAO,CAAC,KAAK,IAAI,OAAO;QAAE,OAAO,EAAE,CAAA;IAEvC,MAAM,KAAK,GAAa,EAAE,CAAA;IAC1B,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,KAAK;QAAE,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,CAAC,CAAA;IAE9D,KAAK,CAAC,IAAI,CAAC,WAAW,MAAM,CAAC,YAAY,QAAQ,MAAM,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,EAAE,EAAE,CAAC,CAAA;IAE7F,IAAI,OAAO,EAAE,CAAC;QACZ,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAA;QACrC,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACzB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,WAAW,MAAM,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAA;IAChG,KAAK,CAAC,IAAI,CACR,GAAG,kBAAkB,CACnB,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC1B,QAAQ,EAAE,CAAC,CAAC,IAAI;QAChB,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,GAAG,EACD,CAAC,CAAC,IAAI,KAAK,QAAQ;YACjB,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,0BAA0B;YACzC,CAAC,CAAC,iBAAiB,CAAC,CAAC,YAAY,iCAAiC;KACvE,CAAC,CAAC,EACH,OAAO,CACR,CACF,CAAA;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACzB,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type UnusedDepsFinding } from './core.js';
|
|
2
|
+
export interface UnusedDepsRunOptions {
|
|
3
|
+
/** package directory to check — both the scan root and where package.json is looked up from, deliberately the same value (see below) */
|
|
4
|
+
dir: string;
|
|
5
|
+
extensions?: string[];
|
|
6
|
+
ignoreGlobs?: string[];
|
|
7
|
+
respectGitignore?: boolean;
|
|
8
|
+
strict?: boolean;
|
|
9
|
+
ignorePackages?: string[];
|
|
10
|
+
}
|
|
11
|
+
export interface UnusedDepsReport {
|
|
12
|
+
filesScanned: number;
|
|
13
|
+
findings: UnusedDepsFinding[];
|
|
14
|
+
/** package.json couldn't be found/read at all — a different kind of problem than any single finding */
|
|
15
|
+
error: string | null;
|
|
16
|
+
exitCode: number;
|
|
17
|
+
}
|
|
18
|
+
export declare function runUnusedDeps(options: UnusedDepsRunOptions): UnusedDepsReport;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
import { walk } from '../../utils/walk.js';
|
|
4
|
+
import { findNearestPackageDir } from '../../utils/find-package-dir.js';
|
|
5
|
+
import { detectWorkspace } from '../../utils/workspace.js';
|
|
6
|
+
import { analyzeUnusedDeps } from './core.js';
|
|
7
|
+
const DEFAULT_EXTENSIONS = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs'];
|
|
8
|
+
// A single [dir] argument, not the [paths...] + --cwd shape most other
|
|
9
|
+
// commands use — deliberately. unused-deps compares a package.json's
|
|
10
|
+
// declared dependencies against real source usage, so scanning one
|
|
11
|
+
// directory tree while consulting a DIFFERENT one's package.json (e.g.
|
|
12
|
+
// `--cwd` still defaulted to wherever the CLI happened to be invoked
|
|
13
|
+
// from, while `paths` pointed somewhere else entirely) would silently
|
|
14
|
+
// check the wrong dependency list — caught for real while dogfooding
|
|
15
|
+
// against sibling packages from inside devtoolz's own checkout, not by
|
|
16
|
+
// a test: findings named devtoolz's OWN dependencies (`commander`,
|
|
17
|
+
// `diff`, `ignore`) against a completely different package's source.
|
|
18
|
+
// One shared root removes the possibility entirely.
|
|
19
|
+
export function runUnusedDeps(options) {
|
|
20
|
+
const scanRoot = resolve(options.dir);
|
|
21
|
+
const packageDir = findNearestPackageDir(scanRoot);
|
|
22
|
+
if (!packageDir) {
|
|
23
|
+
return {
|
|
24
|
+
filesScanned: 0,
|
|
25
|
+
findings: [],
|
|
26
|
+
error: `no package.json found at or above ${scanRoot}`,
|
|
27
|
+
exitCode: 1,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
let pkg;
|
|
31
|
+
try {
|
|
32
|
+
pkg = JSON.parse(readFileSync(`${packageDir}/package.json`, 'utf8'));
|
|
33
|
+
}
|
|
34
|
+
catch (err) {
|
|
35
|
+
return {
|
|
36
|
+
filesScanned: 0,
|
|
37
|
+
findings: [],
|
|
38
|
+
error: err instanceof Error ? err.message : String(err),
|
|
39
|
+
exitCode: 1,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
const extensions = options.extensions ?? DEFAULT_EXTENSIONS;
|
|
43
|
+
const files = walk(['.'], {
|
|
44
|
+
cwd: scanRoot,
|
|
45
|
+
extensions,
|
|
46
|
+
ignoreGlobs: options.ignoreGlobs ?? [],
|
|
47
|
+
...(options.respectGitignore !== undefined
|
|
48
|
+
? { respectGitignore: options.respectGitignore }
|
|
49
|
+
: {}),
|
|
50
|
+
});
|
|
51
|
+
const workspace = detectWorkspace(scanRoot);
|
|
52
|
+
const workspacePackageNames = new Set(workspace?.packages.map((p) => p.name) ?? []);
|
|
53
|
+
const analysis = analyzeUnusedDeps(files, {
|
|
54
|
+
packageDir,
|
|
55
|
+
pkg,
|
|
56
|
+
strict: options.strict ?? false,
|
|
57
|
+
ignorePackages: new Set(options.ignorePackages ?? []),
|
|
58
|
+
workspacePackageNames,
|
|
59
|
+
});
|
|
60
|
+
const findings = [...analysis.findings].sort((a, b) => a.kind.localeCompare(b.kind) || a.name.localeCompare(b.name));
|
|
61
|
+
return {
|
|
62
|
+
filesScanned: analysis.filesAnalyzed,
|
|
63
|
+
findings,
|
|
64
|
+
error: null,
|
|
65
|
+
exitCode: findings.length > 0 ? 1 : 0,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../../src/commands/unused-deps/run.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -15,9 +15,26 @@ export type { DeadExportFinding, DeadExportsAnalysis, AnalyzeOptions, } from './
|
|
|
15
15
|
export { runDeadExports } from './commands/dead-exports/run.js';
|
|
16
16
|
export type { DeadExportsRunOptions, DeadExportsReport } from './commands/dead-exports/run.js';
|
|
17
17
|
export { renderDeadExportsReport } from './commands/dead-exports/report.js';
|
|
18
|
-
export { detectWorkspace } from './
|
|
19
|
-
export type { WorkspaceInfo, WorkspacePackage } from './
|
|
20
|
-
export {
|
|
18
|
+
export { detectWorkspace } from './utils/workspace.js';
|
|
19
|
+
export type { WorkspaceInfo, WorkspacePackage } from './utils/workspace.js';
|
|
20
|
+
export { analyzeCircularImports } from './commands/circular-imports/core.js';
|
|
21
|
+
export type { CircularImportFinding, CircularImportsAnalysis, CircularImportsAnalyzeOptions, } from './commands/circular-imports/core.js';
|
|
22
|
+
export { runCircularImports } from './commands/circular-imports/run.js';
|
|
23
|
+
export type { CircularImportsRunOptions, CircularImportsFileFinding, CircularImportsReport, } from './commands/circular-imports/run.js';
|
|
24
|
+
export { renderCircularImportsReport } from './commands/circular-imports/report.js';
|
|
25
|
+
export { analyzeUnusedDeps } from './commands/unused-deps/core.js';
|
|
26
|
+
export type { UnusedDepsFinding, UnusedDepsAnalysis } from './commands/unused-deps/core.js';
|
|
27
|
+
export type { AnalyzeOptions as UnusedDepsAnalyzeOptions } from './commands/unused-deps/core.js';
|
|
28
|
+
export { runUnusedDeps } from './commands/unused-deps/run.js';
|
|
29
|
+
export type { UnusedDepsRunOptions, UnusedDepsReport } from './commands/unused-deps/run.js';
|
|
30
|
+
export { renderUnusedDepsReport } from './commands/unused-deps/report.js';
|
|
31
|
+
export { packageNameFromSpecifier } from './commands/unused-deps/package-name.js';
|
|
32
|
+
export { resolvePackageDir, declaredBinNames } from './commands/unused-deps/disk-resolve.js';
|
|
33
|
+
export { analyzeFile } from './utils/parse-module.js';
|
|
34
|
+
export type { FileAnalysis, ExportedName, ReexportEntry, ImportedName, } from './utils/parse-module.js';
|
|
35
|
+
export { resolveRelativeSpecifier } from './utils/resolve-specifier.js';
|
|
36
|
+
export { resolvePublicEntries } from './commands/dead-exports/entry.js';
|
|
37
|
+
export { findNearestPackageDir } from './utils/find-package-dir.js';
|
|
21
38
|
export { checkSpecifierCase } from './commands/case-check/resolve-case.js';
|
|
22
39
|
export type { CaseCheckOutcome } from './commands/case-check/resolve-case.js';
|
|
23
40
|
export { checkFile } from './commands/case-check/core.js';
|
|
@@ -36,12 +53,41 @@ export { extractCodeBlocks } from './commands/readme-check/extract.js';
|
|
|
36
53
|
export type { CodeBlock } from './commands/readme-check/extract.js';
|
|
37
54
|
export { typecheckBlock } from './commands/readme-check/typecheck.js';
|
|
38
55
|
export type { BlockDiagnostic } from './commands/readme-check/typecheck.js';
|
|
39
|
-
export {
|
|
40
|
-
export type {
|
|
56
|
+
export { loadTsconfig } from './utils/load-tsconfig.js';
|
|
57
|
+
export type { LoadedTsconfig, LoadTsconfigResult } from './utils/load-tsconfig.js';
|
|
41
58
|
export { checkMarkdownFile } from './commands/readme-check/core.js';
|
|
42
59
|
export type { ReadmeCheckFinding, ReadmeCheckFileResult } from './commands/readme-check/core.js';
|
|
43
60
|
export { runReadmeCheck } from './commands/readme-check/run.js';
|
|
44
61
|
export type { ReadmeCheckRunOptions, ReadmeCheckReport } from './commands/readme-check/run.js';
|
|
45
62
|
export { renderReadmeCheckReport } from './commands/readme-check/report.js';
|
|
63
|
+
export { analyzeEmptyCatch } from './commands/empty-catch/core.js';
|
|
64
|
+
export type { EmptyCatchFinding } from './commands/empty-catch/core.js';
|
|
65
|
+
export { analyzeEmptyCatchVue } from './commands/empty-catch/vue.js';
|
|
66
|
+
export { runEmptyCatch } from './commands/empty-catch/run.js';
|
|
67
|
+
export type { EmptyCatchRunOptions, EmptyCatchFileFinding, EmptyCatchReport, } from './commands/empty-catch/run.js';
|
|
68
|
+
export { renderEmptyCatchReport } from './commands/empty-catch/report.js';
|
|
69
|
+
export { analyzeTodoReport, buildTagMatcher, DEFAULT_TAGS } from './commands/todo-report/core.js';
|
|
70
|
+
export type { TodoFinding } from './commands/todo-report/core.js';
|
|
71
|
+
export { analyzeTodoReportVue } from './commands/todo-report/vue.js';
|
|
72
|
+
export { runTodoReport } from './commands/todo-report/run.js';
|
|
73
|
+
export type { TodoReportRunOptions, TodoFileFinding, TodoReportReport, } from './commands/todo-report/run.js';
|
|
74
|
+
export { renderTodoReportReport } from './commands/todo-report/report.js';
|
|
75
|
+
export { analyzeScriptsCheck, extractMentionedScripts, isScriptMentioned, isReservedLifecycleScript, } from './commands/scripts-check/core.js';
|
|
76
|
+
export type { ScriptsCheckFinding, ScriptSource } from './commands/scripts-check/core.js';
|
|
77
|
+
export { runScriptsCheck } from './commands/scripts-check/run.js';
|
|
78
|
+
export type { ScriptsCheckRunOptions, ScriptsCheckReport } from './commands/scripts-check/run.js';
|
|
79
|
+
export { renderScriptsCheckReport } from './commands/scripts-check/report.js';
|
|
80
|
+
export { parseTestFile, hasMatchingSource, candidateSourceDirs, } from './commands/orphan-tests/core.js';
|
|
81
|
+
export type { OrphanTestFinding } from './commands/orphan-tests/core.js';
|
|
82
|
+
export { runOrphanTests } from './commands/orphan-tests/run.js';
|
|
83
|
+
export type { OrphanTestsRunOptions, OrphanTestsReport } from './commands/orphan-tests/run.js';
|
|
84
|
+
export { renderOrphanTestsReport } from './commands/orphan-tests/report.js';
|
|
85
|
+
export { findTsIgnoreDirectives, blankDirectives } from './commands/stale-ts-ignore/core.js';
|
|
86
|
+
export type { TsIgnoreDirective } from './commands/stale-ts-ignore/core.js';
|
|
87
|
+
export { extractVueScript, findVueTsIgnoreDirectives, type VueScript, } from './commands/stale-ts-ignore/vue.js';
|
|
88
|
+
export { runProjectTypecheck, checkIsolatedFile } from './commands/stale-ts-ignore/check.js';
|
|
89
|
+
export { runStaleTsIgnore } from './commands/stale-ts-ignore/run.js';
|
|
90
|
+
export type { StaleTsIgnoreRunOptions, StaleTsIgnoreFinding, StaleTsIgnoreReport, } from './commands/stale-ts-ignore/run.js';
|
|
91
|
+
export { renderStaleTsIgnoreReport } from './commands/stale-ts-ignore/report.js';
|
|
46
92
|
export { walk } from './utils/walk.js';
|
|
47
93
|
export type { WalkOptions } from './utils/walk.js';
|