codesift-mcp 0.4.0 → 0.5.3
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 +94 -25
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/help.js +8 -6
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/platform.d.ts.map +1 -1
- package/dist/cli/platform.js +12 -14
- package/dist/cli/platform.js.map +1 -1
- package/dist/cli/setup.d.ts +1 -1
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +30 -6
- package/dist/cli/setup.js.map +1 -1
- package/dist/formatters.d.ts +2 -2
- package/dist/formatters.d.ts.map +1 -1
- package/dist/formatters.js +23 -0
- package/dist/formatters.js.map +1 -1
- package/dist/instructions.d.ts +1 -1
- package/dist/instructions.d.ts.map +1 -1
- package/dist/instructions.js +21 -21
- package/dist/parser/extractors/php.d.ts.map +1 -1
- package/dist/parser/extractors/php.js +37 -29
- package/dist/parser/extractors/php.js.map +1 -1
- package/dist/parser/extractors/typescript.d.ts.map +1 -1
- package/dist/parser/extractors/typescript.js +43 -0
- package/dist/parser/extractors/typescript.js.map +1 -1
- package/dist/parser/parse-cache.d.ts +39 -0
- package/dist/parser/parse-cache.d.ts.map +1 -0
- package/dist/parser/parse-cache.js +87 -0
- package/dist/parser/parse-cache.js.map +1 -0
- package/dist/parser/parser-manager.d.ts +1 -1
- package/dist/parser/parser-manager.d.ts.map +1 -1
- package/dist/parser/parser-manager.js +14 -5
- package/dist/parser/parser-manager.js.map +1 -1
- package/dist/parser/stub-languages.d.ts +2 -0
- package/dist/parser/stub-languages.d.ts.map +1 -0
- package/dist/parser/stub-languages.js +5 -0
- package/dist/parser/stub-languages.js.map +1 -0
- package/dist/register-tool-loaders.d.ts +130 -0
- package/dist/register-tool-loaders.d.ts.map +1 -0
- package/dist/register-tool-loaders.js +212 -0
- package/dist/register-tool-loaders.js.map +1 -0
- package/dist/register-tools.d.ts +2 -2
- package/dist/register-tools.d.ts.map +1 -1
- package/dist/register-tools.js +355 -634
- package/dist/register-tools.js.map +1 -1
- package/dist/search/tool-ranker.d.ts +90 -0
- package/dist/search/tool-ranker.d.ts.map +1 -0
- package/dist/search/tool-ranker.js +420 -0
- package/dist/search/tool-ranker.js.map +1 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +23 -14
- package/dist/server.js.map +1 -1
- package/dist/storage/usage-tracker.d.ts.map +1 -1
- package/dist/storage/usage-tracker.js +4 -1
- package/dist/storage/usage-tracker.js.map +1 -1
- package/dist/tools/astro-actions.d.ts +54 -0
- package/dist/tools/astro-actions.d.ts.map +1 -0
- package/dist/tools/astro-actions.js +561 -0
- package/dist/tools/astro-actions.js.map +1 -0
- package/dist/tools/astro-audit.d.ts +87 -0
- package/dist/tools/astro-audit.d.ts.map +1 -0
- package/dist/tools/astro-audit.js +345 -0
- package/dist/tools/astro-audit.js.map +1 -0
- package/dist/tools/astro-content-collections.d.ts +44 -0
- package/dist/tools/astro-content-collections.d.ts.map +1 -0
- package/dist/tools/astro-content-collections.js +630 -0
- package/dist/tools/astro-content-collections.js.map +1 -0
- package/dist/tools/astro-islands.d.ts +3 -1
- package/dist/tools/astro-islands.d.ts.map +1 -1
- package/dist/tools/astro-islands.js +19 -4
- package/dist/tools/astro-islands.js.map +1 -1
- package/dist/tools/astro-migration.d.ts +31 -0
- package/dist/tools/astro-migration.d.ts.map +1 -0
- package/dist/tools/astro-migration.js +378 -0
- package/dist/tools/astro-migration.js.map +1 -0
- package/dist/tools/async-correctness.d.ts +26 -0
- package/dist/tools/async-correctness.d.ts.map +1 -0
- package/dist/tools/async-correctness.js +166 -0
- package/dist/tools/async-correctness.js.map +1 -0
- package/dist/tools/django-view-security-tools.d.ts +32 -0
- package/dist/tools/django-view-security-tools.d.ts.map +1 -0
- package/dist/tools/django-view-security-tools.js +184 -0
- package/dist/tools/django-view-security-tools.js.map +1 -0
- package/dist/tools/fastapi-depends.d.ts +63 -0
- package/dist/tools/fastapi-depends.d.ts.map +1 -0
- package/dist/tools/fastapi-depends.js +191 -0
- package/dist/tools/fastapi-depends.js.map +1 -0
- package/dist/tools/hono-analyze-app.js +1 -9
- package/dist/tools/hono-analyze-app.js.map +1 -1
- package/dist/tools/hono-api-contract.d.ts.map +1 -1
- package/dist/tools/hono-api-contract.js +41 -9
- package/dist/tools/hono-api-contract.js.map +1 -1
- package/dist/tools/hono-context-flow.js +1 -9
- package/dist/tools/hono-context-flow.js.map +1 -1
- package/dist/tools/hono-dead-routes.d.ts.map +1 -1
- package/dist/tools/hono-dead-routes.js +2 -9
- package/dist/tools/hono-dead-routes.js.map +1 -1
- package/dist/tools/hono-entry-resolver.d.ts +27 -0
- package/dist/tools/hono-entry-resolver.d.ts.map +1 -0
- package/dist/tools/hono-entry-resolver.js +31 -0
- package/dist/tools/hono-entry-resolver.js.map +1 -0
- package/dist/tools/hono-inline-analyze.js +1 -9
- package/dist/tools/hono-inline-analyze.js.map +1 -1
- package/dist/tools/hono-middleware-chain.d.ts +24 -6
- package/dist/tools/hono-middleware-chain.d.ts.map +1 -1
- package/dist/tools/hono-middleware-chain.js +77 -40
- package/dist/tools/hono-middleware-chain.js.map +1 -1
- package/dist/tools/hono-modules.js +1 -9
- package/dist/tools/hono-modules.js.map +1 -1
- package/dist/tools/hono-response-types.js +1 -9
- package/dist/tools/hono-response-types.js.map +1 -1
- package/dist/tools/hono-rpc-types.js +1 -9
- package/dist/tools/hono-rpc-types.js.map +1 -1
- package/dist/tools/hono-security.d.ts +14 -4
- package/dist/tools/hono-security.d.ts.map +1 -1
- package/dist/tools/hono-security.js +185 -14
- package/dist/tools/hono-security.js.map +1 -1
- package/dist/tools/hono-visualize.js +1 -9
- package/dist/tools/hono-visualize.js.map +1 -1
- package/dist/tools/nest-ext-tools.d.ts +115 -0
- package/dist/tools/nest-ext-tools.d.ts.map +1 -1
- package/dist/tools/nest-ext-tools.js +393 -0
- package/dist/tools/nest-ext-tools.js.map +1 -1
- package/dist/tools/nest-tools.d.ts +27 -0
- package/dist/tools/nest-tools.d.ts.map +1 -1
- package/dist/tools/nest-tools.js +137 -37
- package/dist/tools/nest-tools.js.map +1 -1
- package/dist/tools/nextjs-component-readers.d.ts +101 -0
- package/dist/tools/nextjs-component-readers.d.ts.map +1 -0
- package/dist/tools/nextjs-component-readers.js +287 -0
- package/dist/tools/nextjs-component-readers.js.map +1 -0
- package/dist/tools/nextjs-component-tools.d.ts +8 -78
- package/dist/tools/nextjs-component-tools.d.ts.map +1 -1
- package/dist/tools/nextjs-component-tools.js +9 -257
- package/dist/tools/nextjs-component-tools.js.map +1 -1
- package/dist/tools/nextjs-framework-audit-tools.d.ts +24 -1
- package/dist/tools/nextjs-framework-audit-tools.d.ts.map +1 -1
- package/dist/tools/nextjs-framework-audit-tools.js +184 -1
- package/dist/tools/nextjs-framework-audit-tools.js.map +1 -1
- package/dist/tools/nextjs-route-readers.d.ts +81 -0
- package/dist/tools/nextjs-route-readers.d.ts.map +1 -0
- package/dist/tools/nextjs-route-readers.js +340 -0
- package/dist/tools/nextjs-route-readers.js.map +1 -0
- package/dist/tools/nextjs-route-tools.d.ts +7 -71
- package/dist/tools/nextjs-route-tools.d.ts.map +1 -1
- package/dist/tools/nextjs-route-tools.js +9 -327
- package/dist/tools/nextjs-route-tools.js.map +1 -1
- package/dist/tools/pattern-tools.d.ts.map +1 -1
- package/dist/tools/pattern-tools.js +92 -2
- package/dist/tools/pattern-tools.js.map +1 -1
- package/dist/tools/php-tools.d.ts +14 -5
- package/dist/tools/php-tools.d.ts.map +1 -1
- package/dist/tools/php-tools.js +166 -64
- package/dist/tools/php-tools.js.map +1 -1
- package/dist/tools/plan-turn-tools.d.ts +89 -0
- package/dist/tools/plan-turn-tools.d.ts.map +1 -0
- package/dist/tools/plan-turn-tools.js +508 -0
- package/dist/tools/plan-turn-tools.js.map +1 -0
- package/dist/tools/project-tools.d.ts +1 -1
- package/dist/tools/project-tools.js +1 -1
- package/dist/tools/project-tools.js.map +1 -1
- package/dist/tools/pydantic-models.d.ts +46 -0
- package/dist/tools/pydantic-models.d.ts.map +1 -0
- package/dist/tools/pydantic-models.js +249 -0
- package/dist/tools/pydantic-models.js.map +1 -0
- package/dist/tools/python-audit.d.ts +40 -0
- package/dist/tools/python-audit.d.ts.map +1 -0
- package/dist/tools/python-audit.js +244 -0
- package/dist/tools/python-audit.js.map +1 -0
- package/dist/tools/python-constants-tools.d.ts +44 -0
- package/dist/tools/python-constants-tools.d.ts.map +1 -0
- package/dist/tools/python-constants-tools.js +525 -0
- package/dist/tools/python-constants-tools.js.map +1 -0
- package/dist/tools/react-tools.d.ts +46 -1
- package/dist/tools/react-tools.d.ts.map +1 -1
- package/dist/tools/react-tools.js +126 -1
- package/dist/tools/react-tools.js.map +1 -1
- package/dist/tools/review-diff-tools.d.ts +5 -0
- package/dist/tools/review-diff-tools.d.ts.map +1 -1
- package/dist/tools/review-diff-tools.js +109 -3
- package/dist/tools/review-diff-tools.js.map +1 -1
- package/dist/tools/search-tools.d.ts +3 -2
- package/dist/tools/search-tools.d.ts.map +1 -1
- package/dist/tools/search-tools.js +16 -3
- package/dist/tools/search-tools.js.map +1 -1
- package/dist/tools/sql-tools.d.ts +40 -0
- package/dist/tools/sql-tools.d.ts.map +1 -1
- package/dist/tools/sql-tools.js +123 -0
- package/dist/tools/sql-tools.js.map +1 -1
- package/dist/tools/symbol-tools.d.ts.map +1 -1
- package/dist/tools/symbol-tools.js +7 -10
- package/dist/tools/symbol-tools.js.map +1 -1
- package/dist/tools/taint-tools.d.ts +43 -0
- package/dist/tools/taint-tools.d.ts.map +1 -0
- package/dist/tools/taint-tools.js +922 -0
- package/dist/tools/taint-tools.js.map +1 -0
- package/dist/utils/import-graph.d.ts +6 -0
- package/dist/utils/import-graph.d.ts.map +1 -1
- package/dist/utils/import-graph.js +43 -7
- package/dist/utils/import-graph.js.map +1 -1
- package/package.json +3 -3
- package/rules/codesift.md +51 -13
- package/rules/codesift.mdc +51 -13
- package/rules/codex.md +51 -13
- package/rules/gemini.md +51 -13
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Next.js component classifier readers: directive detection, signal walking,
|
|
3
|
+
* per-file classification logic, and the decision table.
|
|
4
|
+
*
|
|
5
|
+
* These readers are pure helpers with no orchestration logic. They are used by
|
|
6
|
+
* `nextjs-component-tools.ts` (orchestrator) and re-exported from it for
|
|
7
|
+
* backward compatibility with existing consumers and tests. Split follows the
|
|
8
|
+
* T2/T3 reader + orchestrator precedent.
|
|
9
|
+
*/
|
|
10
|
+
import { readFile } from "node:fs/promises";
|
|
11
|
+
import { relative } from "node:path";
|
|
12
|
+
import { cachedParseFile as parseFile } from "../utils/nextjs-audit-cache.js";
|
|
13
|
+
import { scanDirective } from "../utils/nextjs.js";
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
// Constants
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
export const MAX_FILE_SIZE_BYTES = 2_097_152; // 2 MB hard cap per file
|
|
18
|
+
export const DEFAULT_MAX_FILES = 2000;
|
|
19
|
+
export const PARSE_CONCURRENCY = 10;
|
|
20
|
+
/** Hooks that are server-safe (or SSR-safe) and don't imply client component. */
|
|
21
|
+
export const CLIENT_HOOKS_EXCLUDE = new Set(["useId"]);
|
|
22
|
+
/** JSX event attributes that imply client component. */
|
|
23
|
+
export const EVENT_HANDLER_ATTRS = new Set([
|
|
24
|
+
"onClick", "onChange", "onSubmit", "onInput", "onFocus", "onBlur",
|
|
25
|
+
"onKeyDown", "onKeyUp", "onKeyPress",
|
|
26
|
+
"onMouseDown", "onMouseUp", "onMouseMove", "onMouseEnter", "onMouseLeave", "onMouseOver", "onMouseOut",
|
|
27
|
+
"onTouchStart", "onTouchEnd", "onTouchMove",
|
|
28
|
+
"onDrag", "onDrop", "onDragOver", "onDragEnd", "onDragStart", "onDragLeave", "onDragEnter",
|
|
29
|
+
"onScroll", "onWheel",
|
|
30
|
+
"onAnimationStart", "onAnimationEnd", "onTransitionEnd",
|
|
31
|
+
"onLoad", "onError",
|
|
32
|
+
"onCopy", "onCut", "onPaste",
|
|
33
|
+
]);
|
|
34
|
+
/** Browser-only globals (detected in MemberExpressions like `window.foo`). */
|
|
35
|
+
export const BROWSER_GLOBALS = new Set([
|
|
36
|
+
"window", "document", "localStorage", "sessionStorage",
|
|
37
|
+
"navigator", "location", "history",
|
|
38
|
+
]);
|
|
39
|
+
export const HOOK_NAME_RE = /^use[A-Z]\w*$/;
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
// Classification decision table
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
/**
|
|
44
|
+
* Pure decision table for component classification. No I/O, no AST access.
|
|
45
|
+
*
|
|
46
|
+
* Rules (in priority order):
|
|
47
|
+
* - directive === "use client":
|
|
48
|
+
* has any signal -> client_explicit
|
|
49
|
+
* no signals -> client_explicit + violation "unnecessary_use_client"
|
|
50
|
+
* - directive === "use server" -> server
|
|
51
|
+
* - directive === null:
|
|
52
|
+
* has any signal -> client_inferred
|
|
53
|
+
* no signals -> server
|
|
54
|
+
*/
|
|
55
|
+
export function applyClassificationTable(directive, signals) {
|
|
56
|
+
const hasAnySignal = signals.hooks.length > 0 ||
|
|
57
|
+
signals.event_handlers.length > 0 ||
|
|
58
|
+
signals.browser_globals.length > 0 ||
|
|
59
|
+
signals.dynamic_ssr_false;
|
|
60
|
+
if (directive === "use client") {
|
|
61
|
+
return {
|
|
62
|
+
classification: "client_explicit",
|
|
63
|
+
violations: hasAnySignal ? [] : ["unnecessary_use_client"],
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
if (directive === "use server") {
|
|
67
|
+
return { classification: "server", violations: [] };
|
|
68
|
+
}
|
|
69
|
+
// directive === null
|
|
70
|
+
return {
|
|
71
|
+
classification: hasAnySignal ? "client_inferred" : "server",
|
|
72
|
+
violations: [],
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
// ---------------------------------------------------------------------------
|
|
76
|
+
// Signal detection (hooks, JSX event handlers, browser globals, next/dynamic)
|
|
77
|
+
// ---------------------------------------------------------------------------
|
|
78
|
+
/**
|
|
79
|
+
* Walk the AST to collect client-component signals:
|
|
80
|
+
* - hooks — call_expression whose callee identifier matches /^use[A-Z]/
|
|
81
|
+
* - events — jsx_attribute property_identifier in EVENT_HANDLER_ATTRS
|
|
82
|
+
* - globals — member_expression object identifier in BROWSER_GLOBALS
|
|
83
|
+
* - next/dynamic({ ssr: false }) — import from "next/dynamic" + call with ssr:false
|
|
84
|
+
*/
|
|
85
|
+
export function detectSignals(tree, _source) {
|
|
86
|
+
const hooks = new Set();
|
|
87
|
+
const event_handlers = new Set();
|
|
88
|
+
const browser_globals = new Set();
|
|
89
|
+
const signal_locations = [];
|
|
90
|
+
let dynamic_ssr_false = false;
|
|
91
|
+
const root = tree.rootNode;
|
|
92
|
+
// Hooks: call_expression with identifier callee matching /^use[A-Z]/
|
|
93
|
+
for (const call of root.descendantsOfType("call_expression")) {
|
|
94
|
+
const fn = call.childForFieldName("function") ?? call.namedChild(0);
|
|
95
|
+
if (fn?.type === "identifier") {
|
|
96
|
+
const name = fn.text;
|
|
97
|
+
if (HOOK_NAME_RE.test(name) && !CLIENT_HOOKS_EXCLUDE.has(name)) {
|
|
98
|
+
hooks.add(name);
|
|
99
|
+
signal_locations.push({
|
|
100
|
+
name,
|
|
101
|
+
line: fn.startPosition.row + 1,
|
|
102
|
+
column: fn.startPosition.column + 1,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
// JSX event handlers
|
|
108
|
+
for (const attr of root.descendantsOfType("jsx_attribute")) {
|
|
109
|
+
const nameNode = attr.namedChild(0);
|
|
110
|
+
if (nameNode?.type === "property_identifier" || nameNode?.type === "identifier") {
|
|
111
|
+
const name = nameNode.text;
|
|
112
|
+
if (EVENT_HANDLER_ATTRS.has(name)) {
|
|
113
|
+
event_handlers.add(name);
|
|
114
|
+
signal_locations.push({
|
|
115
|
+
name,
|
|
116
|
+
line: nameNode.startPosition.row + 1,
|
|
117
|
+
column: nameNode.startPosition.column + 1,
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// Browser globals via member_expression (e.g. window.location)
|
|
123
|
+
for (const mem of root.descendantsOfType("member_expression")) {
|
|
124
|
+
const obj = mem.childForFieldName("object") ?? mem.namedChild(0);
|
|
125
|
+
if (obj?.type === "identifier" && BROWSER_GLOBALS.has(obj.text)) {
|
|
126
|
+
browser_globals.add(obj.text);
|
|
127
|
+
signal_locations.push({
|
|
128
|
+
name: obj.text,
|
|
129
|
+
line: obj.startPosition.row + 1,
|
|
130
|
+
column: obj.startPosition.column + 1,
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
// next/dynamic with { ssr: false }
|
|
135
|
+
// Only trust if there's an import from "next/dynamic". We then look for any
|
|
136
|
+
// call expression with second argument containing { ssr: false }.
|
|
137
|
+
const importsNextDynamic = root
|
|
138
|
+
.descendantsOfType("import_statement")
|
|
139
|
+
.some((imp) => {
|
|
140
|
+
// The module source is a direct string child of import_statement
|
|
141
|
+
for (const child of imp.namedChildren) {
|
|
142
|
+
if (child.type === "string") {
|
|
143
|
+
const frag = child.namedChild(0);
|
|
144
|
+
const text = frag?.type === "string_fragment" ? frag.text : child.text.slice(1, -1);
|
|
145
|
+
if (text === "next/dynamic")
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return false;
|
|
150
|
+
});
|
|
151
|
+
if (importsNextDynamic) {
|
|
152
|
+
for (const call of root.descendantsOfType("call_expression")) {
|
|
153
|
+
const fn = call.childForFieldName("function") ?? call.namedChild(0);
|
|
154
|
+
if (fn?.type !== "identifier" || fn.text !== "dynamic")
|
|
155
|
+
continue;
|
|
156
|
+
const args = call.childForFieldName("arguments") ?? call.namedChild(1);
|
|
157
|
+
if (!args)
|
|
158
|
+
continue;
|
|
159
|
+
// Find the second argument (an object with ssr: false)
|
|
160
|
+
const argChildren = args.namedChildren;
|
|
161
|
+
if (argChildren.length < 2)
|
|
162
|
+
continue;
|
|
163
|
+
const opts = argChildren[1];
|
|
164
|
+
if (!opts || opts.type !== "object")
|
|
165
|
+
continue;
|
|
166
|
+
// Iterate pairs that are direct named children of the options object.
|
|
167
|
+
for (const pair of opts.namedChildren) {
|
|
168
|
+
if (pair.type !== "pair")
|
|
169
|
+
continue;
|
|
170
|
+
const key = pair.childForFieldName("key") ?? pair.namedChild(0);
|
|
171
|
+
if (!key)
|
|
172
|
+
continue;
|
|
173
|
+
const keyText = key.type === "property_identifier" || key.type === "identifier"
|
|
174
|
+
? key.text
|
|
175
|
+
: key.type === "string"
|
|
176
|
+
? key.text.slice(1, -1)
|
|
177
|
+
: null;
|
|
178
|
+
if (keyText !== "ssr")
|
|
179
|
+
continue;
|
|
180
|
+
const value = pair.childForFieldName("value") ?? pair.namedChild(1);
|
|
181
|
+
if (value?.type === "false") {
|
|
182
|
+
dynamic_ssr_false = true;
|
|
183
|
+
break;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return {
|
|
189
|
+
hooks: [...hooks],
|
|
190
|
+
event_handlers: [...event_handlers],
|
|
191
|
+
browser_globals: [...browser_globals],
|
|
192
|
+
dynamic_ssr_false,
|
|
193
|
+
signal_locations,
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
// ---------------------------------------------------------------------------
|
|
197
|
+
// Two-stage directive detection
|
|
198
|
+
// ---------------------------------------------------------------------------
|
|
199
|
+
/**
|
|
200
|
+
* Confirm a file-level directive by inspecting `Program.body[0]`.
|
|
201
|
+
*
|
|
202
|
+
* Tree-sitter's tsx/typescript grammars expose top-level directive strings as
|
|
203
|
+
* an `expression_statement` whose first named child is a `string` literal
|
|
204
|
+
* (a `"use client"` or `"use server"` token). Any other shape — including a
|
|
205
|
+
* nested block, inline comment, or non-first statement — must return `null`.
|
|
206
|
+
*/
|
|
207
|
+
export function confirmDirectiveFromTree(tree) {
|
|
208
|
+
const root = tree.rootNode;
|
|
209
|
+
const first = root.namedChildren[0];
|
|
210
|
+
if (!first)
|
|
211
|
+
return null;
|
|
212
|
+
if (first.type !== "expression_statement")
|
|
213
|
+
return null;
|
|
214
|
+
const exprChild = first.namedChildren[0];
|
|
215
|
+
if (!exprChild)
|
|
216
|
+
return null;
|
|
217
|
+
if (exprChild.type !== "string")
|
|
218
|
+
return null;
|
|
219
|
+
// tree-sitter `string` nodes have fragment children containing the text
|
|
220
|
+
// between the quotes. Strip the surrounding quotes via .text and compare.
|
|
221
|
+
const raw = exprChild.text;
|
|
222
|
+
if (raw.length < 3)
|
|
223
|
+
return null;
|
|
224
|
+
const inner = raw.slice(1, -1);
|
|
225
|
+
if (inner === "use client")
|
|
226
|
+
return "use client";
|
|
227
|
+
if (inner === "use server")
|
|
228
|
+
return "use server";
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Classify a single file. Returns a partial entry with the directive field
|
|
233
|
+
* populated. Signal detection + final classification are added by the
|
|
234
|
+
* orchestrator (Task 23) via `detectSignals` (Task 21) and
|
|
235
|
+
* `applyClassificationTable` (Task 22).
|
|
236
|
+
*/
|
|
237
|
+
export async function classifyFile(filePath, repoRoot) {
|
|
238
|
+
const relPath = relative(repoRoot, filePath);
|
|
239
|
+
const emptySignals = {
|
|
240
|
+
hooks: [],
|
|
241
|
+
event_handlers: [],
|
|
242
|
+
browser_globals: [],
|
|
243
|
+
dynamic_ssr_false: false,
|
|
244
|
+
};
|
|
245
|
+
// Stage 1: fast-reject via 512-byte window
|
|
246
|
+
const stage1 = await scanDirective(filePath);
|
|
247
|
+
// Stage 2: parse file via tree-sitter
|
|
248
|
+
let source;
|
|
249
|
+
try {
|
|
250
|
+
source = await readFile(filePath, "utf8");
|
|
251
|
+
}
|
|
252
|
+
catch {
|
|
253
|
+
return {
|
|
254
|
+
path: relPath,
|
|
255
|
+
classification: "ambiguous",
|
|
256
|
+
directive: null,
|
|
257
|
+
signals: emptySignals,
|
|
258
|
+
violations: [],
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
const tree = await parseFile(filePath, source);
|
|
262
|
+
if (!tree) {
|
|
263
|
+
return {
|
|
264
|
+
path: relPath,
|
|
265
|
+
classification: "ambiguous",
|
|
266
|
+
directive: null,
|
|
267
|
+
signals: emptySignals,
|
|
268
|
+
violations: [],
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
// Stage 3: confirm directive via AST (only if stage 1 matched)
|
|
272
|
+
let directive = null;
|
|
273
|
+
if (stage1 !== null) {
|
|
274
|
+
directive = confirmDirectiveFromTree(tree);
|
|
275
|
+
}
|
|
276
|
+
// Note: signal detection and final classification are layered in by
|
|
277
|
+
// Tasks 21-23. For now we return a stub classification — the orchestrator
|
|
278
|
+
// rebuilds this via detectSignals + applyClassificationTable.
|
|
279
|
+
return {
|
|
280
|
+
path: relPath,
|
|
281
|
+
classification: directive === "use client" ? "client_explicit" : "server",
|
|
282
|
+
directive,
|
|
283
|
+
signals: emptySignals,
|
|
284
|
+
violations: [],
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
//# sourceMappingURL=nextjs-component-readers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nextjs-component-readers.js","sourceRoot":"","sources":["../../src/tools/nextjs-component-readers.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,36 +8,15 @@
|
|
|
8
8
|
* Then walks the AST for client-component signals (hooks, JSX event handlers,
|
|
9
9
|
* browser globals, `next/dynamic({ ssr: false })`) and classifies each file
|
|
10
10
|
* per the 8-row decision table.
|
|
11
|
+
*
|
|
12
|
+
* This file is the orchestrator. AST reader helpers (`applyClassificationTable`,
|
|
13
|
+
* `detectSignals`, `confirmDirectiveFromTree`, `classifyFile`) live in
|
|
14
|
+
* `nextjs-component-readers.ts` and are re-exported from here for backward
|
|
15
|
+
* compatibility.
|
|
11
16
|
*/
|
|
12
|
-
import type
|
|
13
|
-
export
|
|
14
|
-
export
|
|
15
|
-
hooks: string[];
|
|
16
|
-
event_handlers: string[];
|
|
17
|
-
browser_globals: string[];
|
|
18
|
-
dynamic_ssr_false: boolean;
|
|
19
|
-
}
|
|
20
|
-
export interface NextjsComponentEntry {
|
|
21
|
-
path: string;
|
|
22
|
-
classification: ComponentClassification;
|
|
23
|
-
directive: "use client" | "use server" | null;
|
|
24
|
-
signals: ComponentSignals;
|
|
25
|
-
violations: string[];
|
|
26
|
-
/**
|
|
27
|
-
* Actionable remediation text for classification violations.
|
|
28
|
-
* Set when the entry has `unnecessary_use_client` violation or
|
|
29
|
-
* `client_inferred` classification; omitted otherwise.
|
|
30
|
-
*/
|
|
31
|
-
suggested_fix?: string;
|
|
32
|
-
}
|
|
33
|
-
export interface NextjsComponentsCounts {
|
|
34
|
-
total: number;
|
|
35
|
-
server: number;
|
|
36
|
-
client_explicit: number;
|
|
37
|
-
client_inferred: number;
|
|
38
|
-
ambiguous: number;
|
|
39
|
-
unnecessary_use_client: number;
|
|
40
|
-
}
|
|
17
|
+
import type { NextjsComponentEntry, NextjsComponentsCounts } from "./nextjs-component-readers.js";
|
|
18
|
+
export { MAX_FILE_SIZE_BYTES, DEFAULT_MAX_FILES, PARSE_CONCURRENCY, CLIENT_HOOKS_EXCLUDE, EVENT_HANDLER_ATTRS, BROWSER_GLOBALS, HOOK_NAME_RE, applyClassificationTable, detectSignals, confirmDirectiveFromTree, classifyFile, } from "./nextjs-component-readers.js";
|
|
19
|
+
export type { ComponentClassification, SignalLocation, ComponentSignals, NextjsComponentEntry, NextjsComponentsCounts, } from "./nextjs-component-readers.js";
|
|
41
20
|
export interface NextjsComponentsResult {
|
|
42
21
|
files: NextjsComponentEntry[];
|
|
43
22
|
counts: NextjsComponentsCounts;
|
|
@@ -53,55 +32,6 @@ export interface AnalyzeNextjsComponentsOptions {
|
|
|
53
32
|
file_pattern?: string | undefined;
|
|
54
33
|
max_files?: number | undefined;
|
|
55
34
|
}
|
|
56
|
-
export declare const MAX_FILE_SIZE_BYTES = 2097152;
|
|
57
|
-
export declare const DEFAULT_MAX_FILES = 2000;
|
|
58
|
-
export declare const PARSE_CONCURRENCY = 10;
|
|
59
|
-
/** Hooks that are server-safe (or SSR-safe) and don't imply client component. */
|
|
60
|
-
export declare const CLIENT_HOOKS_EXCLUDE: Set<string>;
|
|
61
|
-
/** JSX event attributes that imply client component. */
|
|
62
|
-
export declare const EVENT_HANDLER_ATTRS: Set<string>;
|
|
63
|
-
/** Browser-only globals (detected in MemberExpressions like `window.foo`). */
|
|
64
|
-
export declare const BROWSER_GLOBALS: Set<string>;
|
|
65
|
-
/**
|
|
66
|
-
* Pure decision table for component classification. No I/O, no AST access.
|
|
67
|
-
*
|
|
68
|
-
* Rules (in priority order):
|
|
69
|
-
* - directive === "use client":
|
|
70
|
-
* has any signal -> client_explicit
|
|
71
|
-
* no signals -> client_explicit + violation "unnecessary_use_client"
|
|
72
|
-
* - directive === "use server" -> server
|
|
73
|
-
* - directive === null:
|
|
74
|
-
* has any signal -> client_inferred
|
|
75
|
-
* no signals -> server
|
|
76
|
-
*/
|
|
77
|
-
export declare function applyClassificationTable(directive: "use client" | "use server" | null, signals: ComponentSignals): {
|
|
78
|
-
classification: ComponentClassification;
|
|
79
|
-
violations: string[];
|
|
80
|
-
};
|
|
81
|
-
/**
|
|
82
|
-
* Walk the AST to collect client-component signals:
|
|
83
|
-
* - hooks — call_expression whose callee identifier matches /^use[A-Z]/
|
|
84
|
-
* - events — jsx_attribute property_identifier in EVENT_HANDLER_ATTRS
|
|
85
|
-
* - globals — member_expression object identifier in BROWSER_GLOBALS
|
|
86
|
-
* - next/dynamic({ ssr: false }) — import from "next/dynamic" + call with ssr:false
|
|
87
|
-
*/
|
|
88
|
-
export declare function detectSignals(tree: Parser.Tree, _source: string): ComponentSignals;
|
|
89
|
-
/**
|
|
90
|
-
* Confirm a file-level directive by inspecting `Program.body[0]`.
|
|
91
|
-
*
|
|
92
|
-
* Tree-sitter's tsx/typescript grammars expose top-level directive strings as
|
|
93
|
-
* an `expression_statement` whose first named child is a `string` literal
|
|
94
|
-
* (a `"use client"` or `"use server"` token). Any other shape — including a
|
|
95
|
-
* nested block, inline comment, or non-first statement — must return `null`.
|
|
96
|
-
*/
|
|
97
|
-
export declare function confirmDirectiveFromTree(tree: Parser.Tree): "use client" | "use server" | null;
|
|
98
|
-
/**
|
|
99
|
-
* Classify a single file. Returns a partial entry with the directive field
|
|
100
|
-
* populated. Signal detection + final classification are added by the
|
|
101
|
-
* orchestrator (Task 23) via `detectSignals` (Task 21) and
|
|
102
|
-
* `applyClassificationTable` (Task 22).
|
|
103
|
-
*/
|
|
104
|
-
export declare function classifyFile(filePath: string, repoRoot: string): Promise<NextjsComponentEntry>;
|
|
105
35
|
/**
|
|
106
36
|
* Analyze a Next.js repository for Server/Client component classification.
|
|
107
37
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nextjs-component-tools.d.ts","sourceRoot":"","sources":["../../src/tools/nextjs-component-tools.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"nextjs-component-tools.d.ts","sourceRoot":"","sources":["../../src/tools/nextjs-component-tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAgBH,OAAO,KAAK,EAEV,oBAAoB,EACpB,sBAAsB,EACvB,MAAM,+BAA+B,CAAC;AAGvC,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,EACpB,mBAAmB,EACnB,eAAe,EACf,YAAY,EACZ,wBAAwB,EACxB,aAAa,EACb,wBAAwB,EACxB,YAAY,GACb,MAAM,+BAA+B,CAAC;AACvC,YAAY,EACV,uBAAuB,EACvB,cAAc,EACd,gBAAgB,EAChB,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,+BAA+B,CAAC;AAMvC,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,oBAAoB,EAAE,CAAC;IAC9B,MAAM,EAAE,sBAAsB,CAAC;IAC/B,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,8BAA8B;IAC7C,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC;AASD;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,uBAAuB,CAC3C,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,8BAA8B,GACvC,OAAO,CAAC,sBAAsB,CAAC,CA8GjC"}
|