pkg-scaffold 3.3.2 β 3.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/README.md +63 -22
- package/bin/cli.js +5 -5
- package/package.json +45 -25
- package/pnpm-workspace.yaml +2 -0
- package/src/EngineContext.js +14 -0
- package/src/ast/ASTAnalyzer.js +243 -116
- package/src/ast/BarrelParser.js +29 -17
- package/src/ast/DeadCodeDetector.js +73 -0
- package/src/ast/MagicDetector.js +3 -1
- package/src/ast/OxcAnalyzer.js +193 -81
- package/src/index.js +10 -11
- package/src/plugins/PluginRegistry.js +1 -0
- package/src/plugins/ecosystems/MorePlugins.js +184 -0
- package/src/plugins/ecosystems/PluginLoader.js +20 -0
- package/src/resolution/CircularDetector.js +3 -34
- package/src/resolution/ConfigLoader.js +34 -6
- package/src/resolution/WorkSpaceGraph.js +15 -1
package/README.md
CHANGED
|
@@ -1,41 +1,82 @@
|
|
|
1
|
-
#
|
|
1
|
+
# π¦ pkg-scaffold
|
|
2
2
|
|
|
3
3
|

|
|
4
4
|
|
|
5
|
-
**The Ultimate Enterprise Codebase Janitor
|
|
5
|
+
> **The Ultimate Enterprise Codebase Janitor.** Faster than Knip with OXC integration, type-aware analysis, and self-healing capabilities. Fully standalone - solving what Knip cannot.
|
|
6
6
|
|
|
7
|
-
  
|
|
8
8
|
|
|
9
|
-
`pkg-scaffold` is
|
|
9
|
+
`pkg-scaffold` is a next-generation tool designed to declutter your JavaScript and TypeScript projects. It finds unused files, unused dependencies, dead code, circular dependencies, and more. It is built to be a direct and superior competitor to `knip.dev`.
|
|
10
10
|
|
|
11
|
-
##
|
|
11
|
+
## π Why pkg-scaffold over Knip?
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
* **β‘ Blazing Fast:** Powered by `oxc-parser` (Rust-based) for lightning-fast AST traversal. Fallback to TypeScript compiler API when needed.
|
|
14
|
+
* **π Massive Plugin Ecosystem:** Over 20+ built-in plugins (Next.js, Nuxt, SvelteKit, Tailwind, Jest, Vitest, Playwright, GitHub Actions, Webpack, Babel, Rollup, ESLint, Prettier, Husky, and many more).
|
|
15
|
+
* **π True Dead Code Detection:** Advanced graph-based reachability analysis to find truly dead files and unused exports, even deep within your codebase.
|
|
16
|
+
* **π Circular Dependency Detection:** High-performance Tarjan-based algorithm to detect and report circular dependencies.
|
|
17
|
+
* **π‘οΈ Supply Chain Guard:** Detects typosquatting and verifies integrity lockfile hashes.
|
|
18
|
+
* **π Secret Detection:** Scans for hardcoded secrets (API keys, tokens) using AST and Regex.
|
|
19
|
+
* **π οΈ Self-Healing:** Not just reporting, but automatically fixing structural issues (removing dead files, pruning unused dependencies).
|
|
20
|
+
* **βοΈ Flexible Configuration:** Supports `pkg-scaffold.json`, `pkg-scaffold.ts`, `scaffold.config.js`, and more.
|
|
17
21
|
|
|
18
|
-
##
|
|
19
|
-
|
|
20
|
-
### Installation
|
|
22
|
+
## π¦ Installation
|
|
21
23
|
|
|
22
24
|
```bash
|
|
23
|
-
npm install -
|
|
25
|
+
npm install -D pkg-scaffold
|
|
26
|
+
# or
|
|
27
|
+
pnpm add -D pkg-scaffold
|
|
28
|
+
# or
|
|
29
|
+
yarn add -D pkg-scaffold
|
|
24
30
|
```
|
|
25
31
|
|
|
26
|
-
|
|
32
|
+
## π Usage
|
|
33
|
+
|
|
34
|
+
Run the CLI at the root of your project:
|
|
27
35
|
|
|
28
36
|
```bash
|
|
29
|
-
pkg-scaffold
|
|
30
|
-
pkg-scaffold --fix --test-command 'npm test'
|
|
37
|
+
npx pkg-scaffold --run
|
|
31
38
|
```
|
|
32
39
|
|
|
33
|
-
|
|
40
|
+
### CLI Options
|
|
41
|
+
|
|
42
|
+
* `-c, --cwd <path>`: Specify the execution context root directory.
|
|
43
|
+
* `--fix`: Enable atomic code updates, structural file pruning, and active type sanitization.
|
|
44
|
+
* `--no-fix`: Disable direct file manipulation (dry-run reporting mode).
|
|
45
|
+
* `--tsconfig <filename>`: Specify path to custom layout configurations.
|
|
46
|
+
* `--verbose`: Toggle expanded trace telemetry for debug operational diagnostics.
|
|
47
|
+
* `-r, --run`: Execute the primary operational pipeline loop.
|
|
48
|
+
* `-y, --yes`: Skip confirmation prompts.
|
|
49
|
+
|
|
50
|
+
## βοΈ Configuration
|
|
51
|
+
|
|
52
|
+
Create a `pkg-scaffold.json` (or `.js`, `.ts`) in your project root:
|
|
53
|
+
|
|
54
|
+
```json
|
|
55
|
+
{
|
|
56
|
+
"entryPoints": ["src/index.ts"],
|
|
57
|
+
"exclude": ["node_modules/**", "dist/**", "**/*.test.ts"],
|
|
58
|
+
"rules": {
|
|
59
|
+
"no-unused-exports": "error",
|
|
60
|
+
"no-dead-code": "error"
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## π Supported Plugins
|
|
66
|
+
|
|
67
|
+
`pkg-scaffold` automatically detects your ecosystem and enables the relevant plugins:
|
|
68
|
+
|
|
69
|
+
* **Frameworks:** Next.js, Nuxt, Remix, SvelteKit, Astro, Vue, Angular
|
|
70
|
+
* **Testing:** Jest, Vitest, Playwright, Cypress
|
|
71
|
+
* **Build Tools:** Webpack, Rollup, Babel, PostCSS, TailwindCSS
|
|
72
|
+
* **Linters/Formatters:** ESLint, Prettier, Commitlint, Lint-Staged, Husky
|
|
73
|
+
* **CI/CD:** GitHub Actions
|
|
74
|
+
* **And more!**
|
|
75
|
+
|
|
76
|
+
## π€ Contributing
|
|
34
77
|
|
|
35
|
-
|
|
36
|
-
- [guide](https://dreamlongyt.github.io/pkg-scaffold/guide)
|
|
37
|
-
- [references](https://dreamlongyt.github.io/pkg-scaffold/reference)
|
|
78
|
+
Contributions are welcome! Please open an issue or submit a pull request.
|
|
38
79
|
|
|
39
|
-
## License
|
|
80
|
+
## π License
|
|
40
81
|
|
|
41
|
-
|
|
82
|
+
Apache-2.0 License.
|
package/bin/cli.js
CHANGED
|
@@ -105,9 +105,9 @@ async function bootstrap() {
|
|
|
105
105
|
// Load local config if available
|
|
106
106
|
let localConfig = {};
|
|
107
107
|
try {
|
|
108
|
-
const
|
|
109
|
-
const
|
|
110
|
-
localConfig =
|
|
108
|
+
const { ConfigLoader } = await import('../src/resolution/ConfigLoader.js');
|
|
109
|
+
const loader = new ConfigLoader(targetCwd);
|
|
110
|
+
localConfig = await loader.loadConfig(targetCwd);
|
|
111
111
|
} catch (e) {}
|
|
112
112
|
|
|
113
113
|
// Merge options with local config
|
|
@@ -132,7 +132,7 @@ async function bootstrap() {
|
|
|
132
132
|
|
|
133
133
|
console.log(ansis.bold.green(`\nπ¦ pkg-scaffold v${packageJsonContent.version || '3.3.2'} Engine Activation`));
|
|
134
134
|
console.log(ansis.dim('------------------------------------------------------------'));
|
|
135
|
-
console.log(`${ansis.bold('Target Workspace Root :')} ${ansis.blue(
|
|
135
|
+
console.log(`${ansis.bold('Target Workspace Root :')} ${ansis.blue(targetCwd)}`);
|
|
136
136
|
console.log(`${ansis.bold('Refactoring Mode :')} ${options.fix ? ansis.yellow('Active Fixing & Self-Healing Enabled') : ansis.gray('Dry-Run Reporting Only')}`);
|
|
137
137
|
console.log(`${ansis.bold('Validation Sandbox :')} ${ansis.magenta(options.testCommand)}`);
|
|
138
138
|
console.log(ansis.dim('------------------------------------------------------------\n'));
|
|
@@ -140,7 +140,7 @@ async function bootstrap() {
|
|
|
140
140
|
const { RefactoringEngine } = await import('../src/index.js');
|
|
141
141
|
|
|
142
142
|
const engine = new RefactoringEngine({
|
|
143
|
-
cwd:
|
|
143
|
+
cwd: targetCwd,
|
|
144
144
|
autoFix: options.fix,
|
|
145
145
|
tsconfig: options.tsconfig,
|
|
146
146
|
testCommand: options.testCommand,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pkg-scaffold",
|
|
3
|
-
"version": "3.3.
|
|
3
|
+
"version": "3.3.4",
|
|
4
4
|
"description": "The Ultimate Enterprise Codebase Janitor. Faster than Knip with OXC integration, type-aware analysis, and self-healing capabilities. Fully standalone - solving what Knip cannot.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
@@ -13,28 +13,51 @@
|
|
|
13
13
|
"test": "echo \"Error: no test specified\" && exit 0",
|
|
14
14
|
"test:stability": "npm run test",
|
|
15
15
|
"docs:dev": "vitepress dev docs",
|
|
16
|
-
"docs:build": "vitepress build docs && cp docs/sitemap.xml docs/.vitepress/dist/ && cp docs/robots.txt docs/.vitepress/dist",
|
|
16
|
+
"docs:build": "vitepress build docs && cp docs/sitemap.xml docs/.vitepress/dist/ && cp docs/robots.txt docs/.vitepress/dist && cp logo.png docs/.vitepress/dist",
|
|
17
17
|
"docs:preview": "vitepress preview docs"
|
|
18
18
|
},
|
|
19
19
|
"keywords": [
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"setup",
|
|
24
|
-
"dx",
|
|
25
|
-
"cli",
|
|
20
|
+
"analysis",
|
|
21
|
+
"analyze",
|
|
22
|
+
"ast",
|
|
26
23
|
"automation",
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
24
|
+
"cli",
|
|
25
|
+
"gui",
|
|
26
|
+
"class",
|
|
27
|
+
"dead-code",
|
|
28
|
+
"dependencies",
|
|
30
29
|
"dependency-analysis",
|
|
31
30
|
"dependency-audit",
|
|
31
|
+
"detect",
|
|
32
|
+
"devDependencies",
|
|
33
|
+
"duplicate",
|
|
34
|
+
"entropy",
|
|
35
|
+
"enum",
|
|
36
|
+
"export",
|
|
37
|
+
"files",
|
|
38
|
+
"find",
|
|
39
|
+
"ghost-dependencies",
|
|
40
|
+
"javascript",
|
|
41
|
+
"maintenance",
|
|
42
|
+
"members",
|
|
43
|
+
"missing",
|
|
32
44
|
"missing-imports",
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"ast",
|
|
45
|
+
"monorepo",
|
|
46
|
+
"namespace",
|
|
36
47
|
"oxc",
|
|
37
|
-
"
|
|
48
|
+
"package.json",
|
|
49
|
+
"packages",
|
|
50
|
+
"scan",
|
|
51
|
+
"self-healing",
|
|
52
|
+
"setup",
|
|
53
|
+
"type",
|
|
54
|
+
"types",
|
|
55
|
+
"typescript",
|
|
56
|
+
"unreferenced",
|
|
57
|
+
"unresolved",
|
|
58
|
+
"unused",
|
|
59
|
+
"unused-packages",
|
|
60
|
+
"workspace"
|
|
38
61
|
],
|
|
39
62
|
"author": "DreamLongYT",
|
|
40
63
|
"license": "Apache-2.0",
|
|
@@ -54,20 +77,17 @@
|
|
|
54
77
|
"oxc-parser": "^0.135.0",
|
|
55
78
|
"oxc-resolver": "^11.20.0",
|
|
56
79
|
"ramda": "^0.29.1",
|
|
80
|
+
"typescript": "^5.0.0",
|
|
57
81
|
"yocto-spinner": "^0.1.0"
|
|
58
82
|
},
|
|
59
|
-
"devDepencies": {
|
|
60
|
-
"vitepress": "^1.0.0",
|
|
61
|
-
"vue": ">=3.5.0"
|
|
62
|
-
},
|
|
63
|
-
"engines": {
|
|
64
|
-
"node": ">=18.0.0"
|
|
65
|
-
},
|
|
66
83
|
"devDependencies": {
|
|
67
84
|
"@types/node": "^25.9.3",
|
|
68
85
|
"express": "^5.2.1",
|
|
69
86
|
"lodash": "^4.18.1",
|
|
70
|
-
"
|
|
71
|
-
"
|
|
87
|
+
"vitepress": "^1.6.4",
|
|
88
|
+
"vue": ">=3.5.0"
|
|
89
|
+
},
|
|
90
|
+
"engines": {
|
|
91
|
+
"node": ">=18.0.0"
|
|
72
92
|
}
|
|
73
|
-
}
|
|
93
|
+
}
|
package/src/EngineContext.js
CHANGED
|
@@ -25,6 +25,9 @@ export class GraphNode {
|
|
|
25
25
|
this.explicitImports = new Set();
|
|
26
26
|
this.dynamicImports = new Set();
|
|
27
27
|
this.importedSymbols = new Set(); // Format: 'specifier:symbol' or 'specifier:*'
|
|
28
|
+
this.jsxComponents = new Set();
|
|
29
|
+
this.jsxProps = new Set();
|
|
30
|
+
this.decorators = new Set();
|
|
28
31
|
|
|
29
32
|
// Internal API Exposed Interfaces (Symbol Name -> ExportMetadata)
|
|
30
33
|
this.internalExports = new Map();
|
|
@@ -87,6 +90,17 @@ export class GraphNode {
|
|
|
87
90
|
|
|
88
91
|
// Safe fallback lookup inside string reference caches (e.g., obj['databaseUrl'])
|
|
89
92
|
if (parentNode.rawStringReferences.has(symbolName)) return true;
|
|
93
|
+
|
|
94
|
+
// Check for JSX component usage
|
|
95
|
+
if (parentNode.jsxComponents.has(symbolName)) return true;
|
|
96
|
+
|
|
97
|
+
// Check for JSX prop usage (e.g., <MyComponent myProp={symbolName} />)
|
|
98
|
+
for (const jsxProp of parentNode.jsxProps) {
|
|
99
|
+
if (jsxProp.endsWith(`:${symbolName}`)) return true;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Check for decorator usage
|
|
103
|
+
if (parentNode.decorators.has(symbolName)) return true;
|
|
90
104
|
}
|
|
91
105
|
|
|
92
106
|
return false;
|