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 CHANGED
@@ -13,18 +13,18 @@
13
13
 
14
14
  ## Key Features
15
15
 
16
- * **Staged 6-Layer Engine:** From AST entry point resolution to SMT constraint solving, isolated V8 execution, and unused package sweeping.
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
- * **VitePress Powered Docs:** Comprehensive architecture breakdown and guide available in the `/docs` suite.
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 6-stage analysis pipeline:
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;SACpC,CAAC;QAEF,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,eAAe,CAAC,CAAC;QAE9C,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YAClB,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;QACnC,CAAC;aAAM,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;YACxB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC/C,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC;QACtC,CAAC;QAED,IAAI,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,MAAa,CAAC,EAAE,CAAC;YAC9C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,+BAA+B,EAAE,KAAK,CAAC,CAAC;QACtD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -18,6 +18,8 @@ export const DEFAULT_CONFIG = {
18
18
  smtTimeoutMs: 100,
19
19
  isolateMemoryLimitMb: 16,
20
20
  enableConcolicProof: true,
21
+ skip3: false,
22
+ skip4: false,
21
23
  },
22
24
  rules: {
23
25
  'unused-export': 'warning',
@@ -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;KAC1B;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"}
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
- runUsageInstructions(context: AnalysisContext): void;
6
+ run(context: AnalysisContext): Promise<Finding[]>;
7
+ private createAdapter;
6
8
  }
7
9
  /**
8
- * Zod Instruction Plugin
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
- runUsageInstructions(context) {
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
- // Use the default export of traverse
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
- for (const instruction of plugin.instructions) {
32
- if (instruction.identifyUsage) {
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
- * Zod Instruction Plugin
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
- instructions: [
52
- {
53
- name: "zod-schema-usage",
54
- description: "Identifies exports that are Zod schemas and marks them as used.",
55
- identifyUsage(node) {
56
- const used = [];
57
- // Pattern: const User = z.object(...)
58
- if (t.isVariableDeclarator(node) && t.isIdentifier(node.id)) {
59
- const init = node.init;
60
- const isZod = t.isCallExpression(init) &&
61
- ((t.isMemberExpression(init.callee) && t.isIdentifier(init.callee.object) && (init.callee.object.name === 'z' || init.callee.object.name === 'zod')) ||
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
- name: "dynamic-property-access",
72
- description: "Handles cases like controller[method]() where method is a string.",
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
@@ -1 +1 @@
1
- {"version":3,"file":"engine.js","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}
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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"}
@@ -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
- * INCLUDES MANUS FEATURE: Handles .js -> .ts / .tsx extension mapping!
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[];