optiprune 1.3.0 → 1.4.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 +35 -4
- package/dist/cli.js +4 -0
- package/dist/cli.js.map +1 -1
- package/dist/config-loader.js +2 -0
- package/dist/config-loader.js.map +1 -1
- package/dist/engine.d.ts +5 -4
- package/dist/engine.js +113 -53
- package/dist/engine.js.map +1 -1
- package/dist/framework-plugins.d.ts +16 -0
- package/dist/framework-plugins.js +108 -0
- package/dist/framework-plugins.js.map +1 -0
- package/dist/fs-utils.d.ts +1 -1
- package/dist/fs-utils.js +52 -39
- package/dist/fs-utils.js.map +1 -1
- package/dist/index.js +28 -8
- package/dist/index.js.map +1 -1
- package/dist/layer3.js +10 -3
- package/dist/layer3.js.map +1 -1
- package/dist/layer6.js +56 -30
- package/dist/layer6.js.map +1 -1
- package/dist/layer7.d.ts +28 -0
- package/dist/layer7.js +250 -0
- package/dist/layer7.js.map +1 -0
- package/dist/parser.js +17 -1
- package/dist/parser.js.map +1 -1
- package/dist/types.d.ts +27 -6
- package/dist/types.js.map +1 -1
- package/dist/workspace.js +22 -31
- package/dist/workspace.js.map +1 -1
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -13,18 +13,18 @@
|
|
|
13
13
|
|
|
14
14
|
## Key Features
|
|
15
15
|
|
|
16
|
-
* **Staged
|
|
16
|
+
* **Staged 7-Layer Engine:** From AST entry point resolution to SMT constraint solving, isolated V8 execution, implicit binding analysis, and unused package sweeping.
|
|
17
17
|
* **Schema & Contract Preserver (Layer 5):** Introspects Zod schemas (`z.*`), Class declarations (`*Schema`), Prisma models, decorators, and OpenAPI resolvers to prevent false positives on public interfaces.
|
|
18
18
|
* **Cross-Platform Path Normalization:** Flawless resolution across Windows drive letters, backslashes, and POSIX path specs.
|
|
19
19
|
* **Circular Dependency Resilient:** Iterative worklist analysis using Strongly Connected Components (SCCs) to resolve cyclical import paths accurately.
|
|
20
20
|
* **Monorepo & Package Sweeper (Layer 6):** Identifies unused root and package-level `node_modules` dependencies alongside dead code.
|
|
21
|
-
* **
|
|
21
|
+
* **Non-Standard Entry & Implicit Binding (Layer 7):** Maps DI topologies (NestJS/Inversify), event-driven contracts, and resolves dynamic import patterns.
|
|
22
22
|
|
|
23
23
|
---
|
|
24
24
|
|
|
25
25
|
## Architecture Overview
|
|
26
26
|
|
|
27
|
-
Optiprune runs code through a
|
|
27
|
+
Optiprune runs code through a 7-stage analysis pipeline:
|
|
28
28
|
|
|
29
29
|
| Layer | Stage | Focus |
|
|
30
30
|
| :--- | :--- | :--- |
|
|
@@ -34,6 +34,7 @@ Optiprune runs code through a 6-stage analysis pipeline:
|
|
|
34
34
|
| **Layer 4** | Isolated V8 Execution | Candidate validation inside sandboxed `isolated-vm` Isolates |
|
|
35
35
|
| **Layer 5** | AST Contract & Schema | Preserves Zod/Schema classes, decorators, and API boundaries |
|
|
36
36
|
| **Layer 6** | Unused Package Sweeper | Flags unused external dependencies in `package.json` |
|
|
37
|
+
| **Layer 7** | Non-Standard Entry | Implicit bindings (DI/Events) and Dynamic Specifier resolution |
|
|
37
38
|
|
|
38
39
|
---
|
|
39
40
|
|
|
@@ -46,4 +47,34 @@ pnpm add -D optiprune
|
|
|
46
47
|
# or
|
|
47
48
|
npm install --save-dev optiprune
|
|
48
49
|
# or
|
|
49
|
-
yarn add -D optiprune
|
|
50
|
+
yarn add -D optiprune
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Usage
|
|
55
|
+
|
|
56
|
+
Run Optiprune from your project root:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
npx optiprune
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### CLI Options
|
|
63
|
+
|
|
64
|
+
| Flag | Description | Default |
|
|
65
|
+
| :--- | :--- | :--- |
|
|
66
|
+
| `-r, --rootDir` | Project root directory | `process.cwd()` |
|
|
67
|
+
| `-e, --entry` | Entry point patterns (glob) | `[]` |
|
|
68
|
+
| `-i, --ignore` | Patterns to ignore | `[]` |
|
|
69
|
+
| `--no-report-unused-exports` | Disable unused export reporting | `false` |
|
|
70
|
+
| `--fail-on` | Fail on confidence (high/medium/low/none) | `high` |
|
|
71
|
+
| `--json` | Output as JSON | `false` |
|
|
72
|
+
| `--sarif` | Output as SARIF | `false` |
|
|
73
|
+
| `--skip-3` | Skip Layer 3 (SMT Constraint Solver) | `false` |
|
|
74
|
+
| `--skip-4` | Skip Layer 4 (Concolic Execution Proofs) | `false` |
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Contributing
|
|
79
|
+
|
|
80
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for local setup and development guides.
|
package/dist/cli.js
CHANGED
|
@@ -18,6 +18,8 @@ program
|
|
|
18
18
|
.option("--fail-on <confidence>", "Fail on findings with confidence level (high, medium, low, none)", "high")
|
|
19
19
|
.option("--json", "Output results as JSON")
|
|
20
20
|
.option("--sarif", "Output results in SARIF format")
|
|
21
|
+
.option("--skip-3", "Skip Layer 3 (SMT Constraint Solver)")
|
|
22
|
+
.option("--skip-4", "Skip Layer 4 (Concolic Execution Proofs)")
|
|
21
23
|
.action(async (options) => {
|
|
22
24
|
try {
|
|
23
25
|
const analyzerOptions = {
|
|
@@ -29,6 +31,8 @@ program
|
|
|
29
31
|
includeConventionalEntries: options.conventionalEntries,
|
|
30
32
|
failOn: options.failOn,
|
|
31
33
|
json: options.json || options.sarif,
|
|
34
|
+
skip3: options.skip3,
|
|
35
|
+
skip4: options.skip4,
|
|
32
36
|
};
|
|
33
37
|
const report = await analyze(analyzerOptions);
|
|
34
38
|
if (options.sarif) {
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAC9B,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAG7D,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,cAAc,CAAgC,CAAC;AAEnF,OAAO;KACJ,IAAI,CAAC,WAAW,CAAC;KACjB,OAAO,CAAC,QAAQ,IAAI,OAAO,QAAQ,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;KACtF,WAAW,CAAC,oDAAoD,CAAC;KACjE,MAAM,CAAC,sBAAsB,EAAE,+BAA+B,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;KAC9E,MAAM,CAAC,2BAA2B,EAAE,2CAA2C,EAAE,EAAE,CAAC;KACpF,MAAM,CAAC,4BAA4B,EAAE,4BAA4B,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;KAClG,MAAM,CAAC,4BAA4B,EAAE,wBAAwB,EAAE,EAAE,CAAC;KAClE,MAAM,CAAC,4BAA4B,EAAE,8BAA8B,CAAC;KACpE,MAAM,CAAC,2BAA2B,EAAE,+DAA+D,CAAC;KACpG,MAAM,CAAC,wBAAwB,EAAE,kEAAkE,EAAE,MAAM,CAAC;KAC5G,MAAM,CAAC,QAAQ,EAAE,wBAAwB,CAAC;KAC1C,MAAM,CAAC,SAAS,EAAE,gCAAgC,CAAC;KACnD,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;IACxB,IAAI,CAAC;QACH,MAAM,eAAe,GAAoB;YACvC,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,mBAAmB,EAAE,OAAO,CAAC,mBAAmB;YAChD,0BAA0B,EAAE,OAAO,CAAC,mBAAmB;YACvD,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,KAAK;
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/config-loader.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-loader.js","sourceRoot":"","sources":["../src/config-loader.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,OAAO,CAAC;AACzB,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAEtF,MAAM,CAAC,MAAM,cAAc,GAAoB;IAC7C,OAAO,EAAE,iBAAiB,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;IACzC,KAAK,EAAE,EAAE;IACT,UAAU,EAAE,kBAAkB;IAC9B,MAAM,EAAE,cAAc;IACtB,mBAAmB,EAAE,IAAI;IACzB,WAAW,EAAE,EAAE;IACf,MAAM,EAAE,MAAM;IACd,IAAI,EAAE,KAAK;IACX,0BAA0B,EAAE,IAAI;IAChC,iBAAiB,EAAE,EAAE;IACrB,WAAW,EAAE,IAAI,GAAG,EAAoB;IACxC,MAAM,EAAE;QACN,YAAY,EAAE,GAAG;QACjB,oBAAoB,EAAE,EAAE;QACxB,mBAAmB,EAAE,IAAI;
|
|
1
|
+
{"version":3,"file":"config-loader.js","sourceRoot":"","sources":["../src/config-loader.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,OAAO,CAAC;AACzB,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAEtF,MAAM,CAAC,MAAM,cAAc,GAAoB;IAC7C,OAAO,EAAE,iBAAiB,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;IACzC,KAAK,EAAE,EAAE;IACT,UAAU,EAAE,kBAAkB;IAC9B,MAAM,EAAE,cAAc;IACtB,mBAAmB,EAAE,IAAI;IACzB,WAAW,EAAE,EAAE;IACf,MAAM,EAAE,MAAM;IACd,IAAI,EAAE,KAAK;IACX,0BAA0B,EAAE,IAAI;IAChC,iBAAiB,EAAE,EAAE;IACrB,WAAW,EAAE,IAAI,GAAG,EAAoB;IACxC,MAAM,EAAE;QACN,YAAY,EAAE,GAAG;QACjB,oBAAoB,EAAE,EAAE;QACxB,mBAAmB,EAAE,IAAI;QACzB,KAAK,EAAE,KAAK;QACZ,KAAK,EAAE,KAAK;KACb;IACD,KAAK,EAAE;QACL,eAAe,EAAE,SAAS;QAC1B,kBAAkB,EAAE,SAAS;QAC7B,oBAAoB,EAAE,SAAS;QAC/B,0BAA0B,EAAE,SAAS;KACtC;CACF,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,OAAe;IAC9C,MAAM,WAAW,GAAG;QAClB,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,qBAAqB,CAAC;QACzC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,qBAAqB,CAAC;QACzC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,sBAAsB,CAAC;KAC3C,CAAC;IAEF,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;QACrC,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC9B,IAAI,CAAC;gBACH,4EAA4E;gBAC5E,6CAA6C;gBAC7C,MAAM,SAAS,GAAG,aAAa,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC;gBACjD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,CAAC;gBACvC,OAAO,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC;YAClC,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,OAAO,CAAC,IAAI,CAAC,uCAAuC,UAAU,GAAG,EAAE,CAAC,CAAC,CAAC;YACxE,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAqB,EAAE,UAAkB;IACnE,OAAO;QACL,GAAG,IAAI;QACP,GAAG,UAAU;QACb,MAAM,EAAE;YACN,GAAG,IAAI,CAAC,MAAM;YACd,GAAG,UAAU,CAAC,MAAM;SACrB;QACD,KAAK,EAAE;YACL,GAAG,IAAI,CAAC,KAAK;YACb,GAAG,UAAU,CAAC,KAAK;SACpB;QACD,iBAAiB,EAAE;YACjB,GAAG,IAAI,CAAC,iBAAiB;YACzB,GAAG,CAAC,UAAU,CAAC,iBAAiB,IAAI,EAAE,CAAC;SACxC;KACiB,CAAC;AACvB,CAAC"}
|
package/dist/engine.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { AnalysisContext, AnalyzerPlugin } from "./types.js";
|
|
1
|
+
import { AnalysisContext, AnalyzerPlugin, Finding } from "./types.js";
|
|
2
2
|
export declare class PluginEngine {
|
|
3
3
|
private plugins;
|
|
4
|
+
private findings;
|
|
4
5
|
register(plugin: AnalyzerPlugin): void;
|
|
5
|
-
|
|
6
|
+
run(context: AnalysisContext): Promise<Finding[]>;
|
|
7
|
+
private createAdapter;
|
|
6
8
|
}
|
|
7
9
|
/**
|
|
8
|
-
*
|
|
9
|
-
* A lightweight instruction set for identifying Zod schema usage.
|
|
10
|
+
* Legacy ZodPlugin refactored to new architecture
|
|
10
11
|
*/
|
|
11
12
|
export declare const ZodPlugin: AnalyzerPlugin;
|
package/dist/engine.js
CHANGED
|
@@ -1,85 +1,145 @@
|
|
|
1
1
|
import traverse from "@babel/traverse";
|
|
2
2
|
import * as t from "@babel/types";
|
|
3
|
+
import fs from "node:fs/promises";
|
|
4
|
+
import path from "pathe";
|
|
3
5
|
export class PluginEngine {
|
|
4
6
|
plugins = [];
|
|
7
|
+
findings = [];
|
|
5
8
|
register(plugin) {
|
|
6
9
|
this.plugins.push(plugin);
|
|
7
10
|
}
|
|
8
|
-
|
|
11
|
+
async run(context) {
|
|
12
|
+
const adapter = this.createAdapter(context);
|
|
13
|
+
// 1. Detection Phase
|
|
14
|
+
for (const plugin of this.plugins) {
|
|
15
|
+
if (plugin.detect) {
|
|
16
|
+
plugin.enabled = await plugin.detect(adapter);
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
plugin.enabled = true; // Enabled by default if no detect method
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
// 2. onProjectInit
|
|
23
|
+
for (const plugin of this.plugins) {
|
|
24
|
+
if (plugin.enabled && plugin.lifecycle.onProjectInit) {
|
|
25
|
+
await plugin.lifecycle.onProjectInit(adapter);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
// 2. File-level processing
|
|
9
29
|
for (const module of context.modules.values()) {
|
|
10
30
|
if (!module.ast)
|
|
11
31
|
continue;
|
|
12
|
-
//
|
|
32
|
+
// onFileStart
|
|
33
|
+
for (const plugin of this.plugins) {
|
|
34
|
+
if (plugin.enabled && plugin.lifecycle.onFileStart) {
|
|
35
|
+
await plugin.lifecycle.onFileStart(module.id, adapter);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
// onASTNode (Traversal)
|
|
13
39
|
const traverseFn = traverse.default || traverse;
|
|
14
40
|
traverseFn(module.ast, {
|
|
15
41
|
enter: (path) => {
|
|
16
|
-
// Layer 2: Dead Branch Pruning (Integrated into walk)
|
|
17
|
-
if (t.isIfStatement(path.node)) {
|
|
18
|
-
const test = path.node.test;
|
|
19
|
-
if (t.isBooleanLiteral(test) && test.value === false) {
|
|
20
|
-
path.skip();
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
if (t.isBinaryExpression(test) && t.isNumericLiteral(test.left) && t.isNumericLiteral(test.right)) {
|
|
24
|
-
if (test.operator === '===' && test.left.value !== test.right.value) {
|
|
25
|
-
path.skip();
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
42
|
for (const plugin of this.plugins) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const usedIdentifiers = instruction.identifyUsage(path.node, module, context);
|
|
34
|
-
usedIdentifiers.forEach(id => {
|
|
35
|
-
context.usedExports.add(`${module.id}:${id}`);
|
|
36
|
-
});
|
|
37
|
-
}
|
|
43
|
+
if (plugin.enabled && plugin.lifecycle.onASTNode) {
|
|
44
|
+
plugin.lifecycle.onASTNode(path.node, module.id, adapter);
|
|
38
45
|
}
|
|
39
46
|
}
|
|
40
47
|
}
|
|
41
48
|
});
|
|
42
49
|
}
|
|
50
|
+
// 4. onAnalysisComplete
|
|
51
|
+
for (const plugin of this.plugins) {
|
|
52
|
+
if (plugin.enabled && plugin.lifecycle.onAnalysisComplete) {
|
|
53
|
+
await plugin.lifecycle.onAnalysisComplete(adapter);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return this.findings;
|
|
57
|
+
}
|
|
58
|
+
createAdapter(context) {
|
|
59
|
+
return {
|
|
60
|
+
getAst: (fileId) => context.modules.get(fileId)?.ast,
|
|
61
|
+
getSymbol: (name, fileId) => {
|
|
62
|
+
const module = context.modules.get(fileId);
|
|
63
|
+
return module?.exports.find(e => e.name === name || e.exportedAs === name);
|
|
64
|
+
},
|
|
65
|
+
getType: (node) => {
|
|
66
|
+
// Simplified type inference
|
|
67
|
+
if (t.isStringLiteral(node))
|
|
68
|
+
return 'string';
|
|
69
|
+
if (t.isNumericLiteral(node))
|
|
70
|
+
return 'number';
|
|
71
|
+
if (t.isBooleanLiteral(node))
|
|
72
|
+
return 'boolean';
|
|
73
|
+
return undefined;
|
|
74
|
+
},
|
|
75
|
+
getDependencies: (fileId) => {
|
|
76
|
+
const module = context.modules.get(fileId);
|
|
77
|
+
return module?.edges.map(e => e.target).filter(Boolean) || [];
|
|
78
|
+
},
|
|
79
|
+
getConfig: () => context.options,
|
|
80
|
+
readFile: async (filename) => {
|
|
81
|
+
try {
|
|
82
|
+
const fullPath = path.isAbsolute(filename) ? filename : path.join(context.options.rootDir, filename);
|
|
83
|
+
return await fs.readFile(fullPath, 'utf8');
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
readJson: async (filename) => {
|
|
90
|
+
try {
|
|
91
|
+
const fullPath = path.isAbsolute(filename) ? filename : path.join(context.options.rootDir, filename);
|
|
92
|
+
const content = await fs.readFile(fullPath, 'utf8');
|
|
93
|
+
return JSON.parse(content);
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
emitFinding: (finding) => {
|
|
100
|
+
this.findings.push({
|
|
101
|
+
rule: 'plugin-finding', // default fallback
|
|
102
|
+
...finding, // overrides 'rule' if finding.rule was provided
|
|
103
|
+
});
|
|
104
|
+
},
|
|
105
|
+
markAsUsed: (fileId, symbol) => {
|
|
106
|
+
context.reachable.add(fileId);
|
|
107
|
+
if (symbol) {
|
|
108
|
+
context.usedExports.add(`${fileId}:${symbol}`);
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
attachMetadata: (node, key, value) => {
|
|
112
|
+
node.metadata = node.metadata || {};
|
|
113
|
+
node.metadata[key] = value;
|
|
114
|
+
}
|
|
115
|
+
};
|
|
43
116
|
}
|
|
44
117
|
}
|
|
45
118
|
/**
|
|
46
|
-
*
|
|
47
|
-
* A lightweight instruction set for identifying Zod schema usage.
|
|
119
|
+
* Legacy ZodPlugin refactored to new architecture
|
|
48
120
|
*/
|
|
49
121
|
export const ZodPlugin = {
|
|
50
122
|
name: "zod-plugin",
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
(t.isIdentifier(init.callee) && init.callee.name === 'z'));
|
|
63
|
-
if (isZod) {
|
|
64
|
-
used.push(node.id.name);
|
|
65
|
-
}
|
|
123
|
+
version: "2.0.0",
|
|
124
|
+
lifecycle: {
|
|
125
|
+
onASTNode: (node, fileId, adapter) => {
|
|
126
|
+
// Pattern: const User = z.object(...)
|
|
127
|
+
if (t.isVariableDeclarator(node) && t.isIdentifier(node.id)) {
|
|
128
|
+
const init = node.init;
|
|
129
|
+
const isZod = t.isCallExpression(init) &&
|
|
130
|
+
((t.isMemberExpression(init.callee) && t.isIdentifier(init.callee.object) && (init.callee.object.name === 'z' || init.callee.object.name === 'zod')) ||
|
|
131
|
+
(t.isIdentifier(init.callee) && init.callee.name === 'z'));
|
|
132
|
+
if (isZod) {
|
|
133
|
+
adapter.markAsUsed(fileId, node.id.name);
|
|
66
134
|
}
|
|
67
|
-
return used;
|
|
68
135
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
identifyUsage(node) {
|
|
74
|
-
const used = [];
|
|
75
|
-
if (t.isMemberExpression(node) && node.computed) {
|
|
76
|
-
if (t.isStringLiteral(node.property)) {
|
|
77
|
-
used.push(node.property.value);
|
|
78
|
-
}
|
|
136
|
+
// Dynamic property access: controller[method]()
|
|
137
|
+
if (t.isMemberExpression(node) && node.computed) {
|
|
138
|
+
if (t.isStringLiteral(node.property)) {
|
|
139
|
+
adapter.markAsUsed(fileId, node.property.value);
|
|
79
140
|
}
|
|
80
|
-
return used;
|
|
81
141
|
}
|
|
82
142
|
}
|
|
83
|
-
|
|
143
|
+
}
|
|
84
144
|
};
|
|
85
145
|
//# sourceMappingURL=engine.js.map
|
package/dist/engine.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AACA,OAAO,QAAQ,MAAM,iBAAiB,CAAC;AACvC,OAAO,KAAK,CAAC,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { AnalyzerPlugin } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* React Plugin
|
|
4
|
+
* Handles React-specific patterns like components and hooks.
|
|
5
|
+
*/
|
|
6
|
+
export declare const ReactPlugin: AnalyzerPlugin;
|
|
7
|
+
/**
|
|
8
|
+
* Next.js Plugin
|
|
9
|
+
* Handles Next.js specific entry points and conventions.
|
|
10
|
+
*/
|
|
11
|
+
export declare const NextjsPlugin: AnalyzerPlugin;
|
|
12
|
+
/**
|
|
13
|
+
* Nuxt Plugin
|
|
14
|
+
* Handles Nuxt-specific directory conventions and auto-imports.
|
|
15
|
+
*/
|
|
16
|
+
export declare const NuxtPlugin: AnalyzerPlugin;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import * as t from "@babel/types";
|
|
2
|
+
/**
|
|
3
|
+
* Utility to check for dependencies in package.json
|
|
4
|
+
*/
|
|
5
|
+
async function hasDependency(adapter, name) {
|
|
6
|
+
const pkg = await adapter.readJson('package.json');
|
|
7
|
+
if (!pkg)
|
|
8
|
+
return false;
|
|
9
|
+
return !!(pkg.dependencies?.[name] || pkg.devDependencies?.[name] || pkg.peerDependencies?.[name]);
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* React Plugin
|
|
13
|
+
* Handles React-specific patterns like components and hooks.
|
|
14
|
+
*/
|
|
15
|
+
export const ReactPlugin = {
|
|
16
|
+
name: "react-plugin",
|
|
17
|
+
version: "1.1.0",
|
|
18
|
+
detect: async (adapter) => {
|
|
19
|
+
return await hasDependency(adapter, 'react');
|
|
20
|
+
},
|
|
21
|
+
lifecycle: {
|
|
22
|
+
onASTNode: (node, fileId, adapter) => {
|
|
23
|
+
// 1. Detect React components (Functions starting with uppercase)
|
|
24
|
+
if (t.isFunctionDeclaration(node) && node.id && /^[A-Z]/.test(node.id.name)) {
|
|
25
|
+
adapter.markAsUsed(fileId, node.id.name);
|
|
26
|
+
}
|
|
27
|
+
// 2. Detect hooks (Functions starting with 'use')
|
|
28
|
+
if (t.isCallExpression(node) && t.isIdentifier(node.callee) && node.callee.name.startsWith('use')) {
|
|
29
|
+
adapter.markAsUsed(fileId);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Next.js Plugin
|
|
36
|
+
* Handles Next.js specific entry points and conventions.
|
|
37
|
+
*/
|
|
38
|
+
export const NextjsPlugin = {
|
|
39
|
+
name: "nextjs-plugin",
|
|
40
|
+
version: "1.1.0",
|
|
41
|
+
detect: async (adapter) => {
|
|
42
|
+
return await hasDependency(adapter, 'next');
|
|
43
|
+
},
|
|
44
|
+
lifecycle: {
|
|
45
|
+
onProjectInit: async (adapter) => {
|
|
46
|
+
// Read next.config.js to look for custom entry points or redirects
|
|
47
|
+
const nextConfig = await adapter.readFile('next.config.js') || await adapter.readFile('next.config.mjs');
|
|
48
|
+
if (nextConfig) {
|
|
49
|
+
// In a real implementation, we would parse the config to find custom rewrites/redirects
|
|
50
|
+
// For now, we just log that we found it
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
onFileStart: (fileId, adapter) => {
|
|
54
|
+
const filename = fileId.split('/').pop() || '';
|
|
55
|
+
if (['page.tsx', 'page.js', 'layout.tsx', 'layout.js', 'route.ts', 'route.js', 'error.tsx', 'loading.tsx'].includes(filename)) {
|
|
56
|
+
adapter.markAsUsed(fileId);
|
|
57
|
+
}
|
|
58
|
+
if (fileId.includes('/pages/api/')) {
|
|
59
|
+
adapter.markAsUsed(fileId);
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
onASTNode: (node, fileId, adapter) => {
|
|
63
|
+
if (t.isExportNamedDeclaration(node) && node.declaration) {
|
|
64
|
+
const decl = node.declaration;
|
|
65
|
+
if (t.isFunctionDeclaration(decl) && decl.id) {
|
|
66
|
+
const name = decl.id.name;
|
|
67
|
+
if (['getStaticProps', 'getServerSideProps', 'getStaticPaths', 'generateMetadata', 'generateStaticParams'].includes(name)) {
|
|
68
|
+
adapter.markAsUsed(fileId, name);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* Nuxt Plugin
|
|
77
|
+
* Handles Nuxt-specific directory conventions and auto-imports.
|
|
78
|
+
*/
|
|
79
|
+
export const NuxtPlugin = {
|
|
80
|
+
name: "nuxt-plugin",
|
|
81
|
+
version: "1.1.0",
|
|
82
|
+
detect: async (adapter) => {
|
|
83
|
+
return await hasDependency(adapter, 'nuxt');
|
|
84
|
+
},
|
|
85
|
+
lifecycle: {
|
|
86
|
+
onProjectInit: async (adapter) => {
|
|
87
|
+
// Read nuxt.config.ts to look for custom modules or dir overrides
|
|
88
|
+
const nuxtConfig = await adapter.readFile('nuxt.config.ts') || await adapter.readFile('nuxt.config.js');
|
|
89
|
+
if (nuxtConfig) {
|
|
90
|
+
// Example: Nuxt might have custom directory configurations
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
onFileStart: (fileId, adapter) => {
|
|
94
|
+
const pathParts = fileId.split('/');
|
|
95
|
+
if (pathParts.includes('pages') || pathParts.includes('layouts') || pathParts.includes('middleware') || pathParts.includes('server') || pathParts.includes('composables')) {
|
|
96
|
+
adapter.markAsUsed(fileId);
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
onASTNode: (node, fileId, adapter) => {
|
|
100
|
+
if (t.isCallExpression(node) && t.isIdentifier(node.callee)) {
|
|
101
|
+
if (['definePageMeta', 'defineNuxtComponent', 'useNuxtApp', 'useFetch', 'defineEventHandler'].includes(node.callee.name)) {
|
|
102
|
+
adapter.markAsUsed(fileId);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
//# sourceMappingURL=framework-plugins.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"framework-plugins.js","sourceRoot":"","sources":["../src/framework-plugins.ts"],"names":[],"mappings":"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"}
|
package/dist/fs-utils.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ export declare function isLikelyLocalSpecifier(specifier: string): boolean;
|
|
|
14
14
|
export declare function removeQueryAndHash(specifier: string): string;
|
|
15
15
|
/**
|
|
16
16
|
* Resolves an import specifier against a set of known files.
|
|
17
|
-
*
|
|
17
|
+
* Handles .js -> .ts / .tsx extension mapping.
|
|
18
18
|
*/
|
|
19
19
|
export declare function resolveLocalSpecifier(sourceFilePath: string, rawSpecifier: string, knownFiles: Set<string> | Map<string, unknown>, extensions?: string[]): string | undefined;
|
|
20
20
|
export declare function resolveDynamicPattern(fromFile: string, prefix: string, suffix: string, knownFiles: Set<string>): string[];
|