feat(screens): Next.js as a Screens app — pages, route handlers, links and redirects
- frameworks/nextjs.ts (split out of react.ts): App Router app/**/page.tsx and Pages Router pages → routes named by path ((group) stripped, [slug] → :slug, [...all] → :all*), bound to the default export; app/**/route.ts exports → METHOD /api/… endpoints referencing their functions; pages/api → ANY; resolve() claims router.push/replace/prefetch, redirect/permanentRedirect and NextResponse.redirect(new URL(…)) into navigates edges via the Expo href readers, against a Next-only route table gated on the app's root
- next-router-synthesizer.ts: <Link href> and internal <a href> → dashed navigates edges from the component (next-link, registeredAt)
- expo-router.ts: href readers exported; matcher accepts :param / :all* segments
- steps.ts: a Next page's own work fires from page load; a Next page makes the project a web app; {status: 201} read off the call site (branch-guards CallSiteText.status) for response rows
- frameworks/package-deps.ts: nested package.json files probed on disk (getAllFiles lists only sources); Express/React/Expo/Nest detectors use it; routing manifest names constant handlers
- tests: nextjs.test.ts (file→route rules, extract, verbs, end to end with Screens and Steps); frameworks.test.ts Next cases moved to the Next resolver
- docs: CHANGELOG, spec §3.12 frameworks paragraph, CLAUDE.md, synthesis doc, plan P4 built, playbook rows for Next / MERN / Nest channels
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01REFyW9hmNrxhwN5wxRoAkC
This commit is contained in:
co-authored by
Claude Fable 5
parent
b1f40c57dd
commit
9c6bc23b21
@@ -433,6 +433,26 @@ export interface CallSiteText {
|
||||
args: string;
|
||||
/** The same arguments one by one — a registration site's middleware chain is `argList.slice(1, -1)`. */
|
||||
argList: string[];
|
||||
/** A status code written as an object property in the arguments (`{ status: 201 }`), which the abbreviation to keys would hide. */
|
||||
status?: number;
|
||||
}
|
||||
|
||||
const STATUS_KEY = /^(?:status|statusCode|status_code|code)$/;
|
||||
|
||||
/** `{ status: 201 }` inside an argument — the literal an abbreviated object hides. */
|
||||
function statusPropertyIn(node: SyntaxNode, depth = 0): number | null {
|
||||
if (depth > 2) return null;
|
||||
for (let i = 0; i < node.namedChildCount; i++) {
|
||||
const c = node.namedChild(i)!;
|
||||
if (c.type === 'pair' || c.type === 'keyword_argument' || c.type === 'named_argument' || c.type === 'property_assignment' || c.type === 'object_property') {
|
||||
const key = c.childForFieldName('key') ?? c.childForFieldName('name') ?? c.namedChild(0);
|
||||
const value = c.childForFieldName('value') ?? c.namedChild(c.namedChildCount - 1);
|
||||
if (key && value && STATUS_KEY.test(key.text.replace(/['"]/g, '')) && /^[1-5]\d{2}$/.test(value.text)) return Number(value.text);
|
||||
}
|
||||
const inner = statusPropertyIn(c, depth + 1);
|
||||
if (inner !== null) return inner;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Longest callee text kept before it is cut. */
|
||||
@@ -473,13 +493,15 @@ export function callSiteInTree(root: SyntaxNode, source: string, line: number, c
|
||||
const callee = calleeChainText(call, container);
|
||||
if (container.type === 'lambda_literal') return { callee, args: '{ … }', argList: ['{ … }'] };
|
||||
const parts: string[] = [];
|
||||
let status: number | null = null;
|
||||
for (let i = 0; i < container.namedChildCount; i++) {
|
||||
const c = container.namedChild(i);
|
||||
if (!c || c.type === 'comment') continue;
|
||||
parts.push(abbreviateArgument(c, source));
|
||||
if (status === null && c.type !== 'comment') status = statusPropertyIn(c);
|
||||
}
|
||||
const text = parts.join(', ');
|
||||
return { callee, args: text.length > MAX_ARGS_TEXT ? `${text.slice(0, MAX_ARGS_TEXT - 1)}…` : text, argList: parts };
|
||||
return { callee, args: text.length > MAX_ARGS_TEXT ? `${text.slice(0, MAX_ARGS_TEXT - 1)}…` : text, argList: parts, ...(status !== null ? { status } : {}) };
|
||||
}
|
||||
|
||||
/** The text of a call before its arguments, normalised to a member chain. */
|
||||
|
||||
Reference in New Issue
Block a user