@nifrajs/cli 0.1.0-alpha.1 → 0.1.0-alpha.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 +8 -0
- package/dist/check.d.ts +82 -3
- package/dist/check.d.ts.map +1 -1
- package/dist/check.js +326 -11
- package/dist/check.js.map +1 -1
- package/dist/cli.d.ts +11 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +178 -17
- package/dist/cli.js.map +1 -1
- package/dist/init-agents.d.ts +58 -0
- package/dist/init-agents.d.ts.map +1 -0
- package/dist/init-agents.js +126 -0
- package/dist/init-agents.js.map +1 -0
- package/dist/introspect.d.ts +77 -2
- package/dist/introspect.d.ts.map +1 -1
- package/dist/introspect.js +138 -9
- package/dist/introspect.js.map +1 -1
- package/dist/mcp-render.d.ts.map +1 -1
- package/dist/mcp-render.js +99 -8
- package/dist/mcp-render.js.map +1 -1
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +49 -21
- package/dist/mcp.js.map +1 -1
- package/dist/openapi-tool.d.ts +12 -3
- package/dist/openapi-tool.d.ts.map +1 -1
- package/dist/openapi-tool.js +21 -4
- package/dist/openapi-tool.js.map +1 -1
- package/dist/port.d.ts +144 -0
- package/dist/port.d.ts.map +1 -0
- package/dist/port.js +498 -0
- package/dist/port.js.map +1 -0
- package/docs/examples.json +91 -133
- package/docs/llms-full.txt +1090 -35
- package/package.json +6 -5
- package/src/check.ts +398 -14
- package/src/cli.ts +176 -21
- package/src/init-agents.ts +176 -0
- package/src/introspect.ts +208 -8
- package/src/mcp-render.ts +106 -11
- package/src/mcp.ts +56 -20
- package/src/openapi-tool.ts +24 -4
- package/src/port.ts +663 -0
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `nifra init-agents` — retrofit an EXISTING app with the agent-discovery files a freshly scaffolded
|
|
3
|
+
* app ships, so an already-built project adopts the nifra MCP in one command:
|
|
4
|
+
*
|
|
5
|
+
* .mcp.json — Claude Code's project MCP registry (launches `bunx @nifrajs/cli mcp`)
|
|
6
|
+
* .cursor/mcp.json — Cursor's MCP registry (same server config)
|
|
7
|
+
* CLAUDE.md — Claude's MCP-first preamble + `@AGENTS.md` import
|
|
8
|
+
* AGENTS.md — a `## MCP server` section appended (or a minimal file if none exists)
|
|
9
|
+
*
|
|
10
|
+
* The generators are imported from `create-nifra/agent-files` — the SAME source of truth `create-nifra`
|
|
11
|
+
* uses at scaffold time — so a retrofitted app and a freshly scaffolded one get byte-identical configs.
|
|
12
|
+
*
|
|
13
|
+
* Safety: this writes into the user's existing tree, so it NEVER silently clobbers a file they may have
|
|
14
|
+
* customized. By default an existing `.mcp.json` / `CLAUDE.md` / `.cursor/mcp.json` is SKIPPED with a
|
|
15
|
+
* notice; `--force` overwrites. `AGENTS.md` is special-cased — if it already has the MCP section it's
|
|
16
|
+
* left alone, otherwise the section is APPENDED (never overwriting the user's conventions), and `--force`
|
|
17
|
+
* is not needed for that append since it's additive. Every write path is resolved + confined under the
|
|
18
|
+
* cwd (no `..` traversal escaping the project root).
|
|
19
|
+
*/
|
|
20
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
21
|
+
import { isAbsolute, relative, resolve } from "node:path";
|
|
22
|
+
import { AGENTS_MD_PATH, agentsMcpSection, CLAUDE_MD_PATH, CURSOR_MCP_JSON_PATH, claudeMd, MCP_JSON_PATH, mcpJson, } from "create-nifra/agent-files";
|
|
23
|
+
/** Confine a project-relative path under `cwd` and return the absolute path. Rejects a spec that escapes
|
|
24
|
+
* the root (defense-in-depth — these specs are constants, but the cwd-confinement invariant is enforced
|
|
25
|
+
* at the seam, not assumed). Exported so the invariant is directly testable. */
|
|
26
|
+
export function safeJoin(cwd, rel) {
|
|
27
|
+
const abs = resolve(cwd, rel);
|
|
28
|
+
const within = relative(cwd, abs);
|
|
29
|
+
if (within.startsWith("..") || isAbsolute(within)) {
|
|
30
|
+
throw new Error(`[nifra] refusing to write outside the project root: ${rel}`);
|
|
31
|
+
}
|
|
32
|
+
return abs;
|
|
33
|
+
}
|
|
34
|
+
const fileExists = (path) => readFile(path)
|
|
35
|
+
.then(() => true)
|
|
36
|
+
.catch(() => false);
|
|
37
|
+
/**
|
|
38
|
+
* Write a whole-file generator's output to `path` unless it already exists and `force` is false.
|
|
39
|
+
* Returns the per-file result for the report.
|
|
40
|
+
*/
|
|
41
|
+
async function writeOwned(cwd, rel, content, force) {
|
|
42
|
+
const abs = safeJoin(cwd, rel);
|
|
43
|
+
if (!force && (await fileExists(abs))) {
|
|
44
|
+
return { path: rel, action: "skipped", note: "exists — pass --force to overwrite" };
|
|
45
|
+
}
|
|
46
|
+
// `.cursor/mcp.json` needs its parent dir; `recursive` is a no-op for the root-level files.
|
|
47
|
+
await mkdir(resolve(abs, ".."), { recursive: true });
|
|
48
|
+
await writeFile(abs, content);
|
|
49
|
+
return { path: rel, action: "wrote" };
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* AGENTS.md is additive, not owned: if it exists and already has the MCP section, leave it; if it exists
|
|
53
|
+
* without the section, append the section (preserving the user's conventions); if it's absent, write a
|
|
54
|
+
* minimal AGENTS.md that is just the MCP section under a heading. `--force` is irrelevant here — we never
|
|
55
|
+
* overwrite the user's existing guidance.
|
|
56
|
+
*/
|
|
57
|
+
async function ensureAgentsMd(cwd) {
|
|
58
|
+
const abs = safeJoin(cwd, AGENTS_MD_PATH);
|
|
59
|
+
const section = agentsMcpSection();
|
|
60
|
+
let existing;
|
|
61
|
+
try {
|
|
62
|
+
existing = await readFile(abs, "utf8");
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
existing = undefined; // no AGENTS.md yet
|
|
66
|
+
}
|
|
67
|
+
if (existing === undefined) {
|
|
68
|
+
await writeFile(abs, `# AGENTS.md\n\nGuidance for AI coding agents working in this repo.\n\n${section}\n`);
|
|
69
|
+
return { path: AGENTS_MD_PATH, action: "wrote" };
|
|
70
|
+
}
|
|
71
|
+
// Match on the section heading, not the full body, so a reformatted-but-present section still counts.
|
|
72
|
+
if (existing.includes("## MCP server")) {
|
|
73
|
+
return { path: AGENTS_MD_PATH, action: "present", note: "already has an MCP section" };
|
|
74
|
+
}
|
|
75
|
+
const sep = existing.endsWith("\n") ? "\n" : "\n\n";
|
|
76
|
+
await writeFile(abs, `${existing}${sep}${section}\n`);
|
|
77
|
+
return { path: AGENTS_MD_PATH, action: "appended" };
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Retrofit `cwd` with the four agent-discovery files. Pure enough to unit-test (no argv, no process.exit,
|
|
81
|
+
* no console) — the CLI wrapper handles printing + the exit code.
|
|
82
|
+
*/
|
|
83
|
+
export async function initAgents(cwd, opts = {}) {
|
|
84
|
+
const force = opts.force ?? false;
|
|
85
|
+
// Order: the two MCP registries + CLAUDE.md (owned, no-clobber), then AGENTS.md (additive).
|
|
86
|
+
const files = [];
|
|
87
|
+
files.push(await writeOwned(cwd, MCP_JSON_PATH, mcpJson(), force));
|
|
88
|
+
files.push(await writeOwned(cwd, CURSOR_MCP_JSON_PATH, mcpJson(), force));
|
|
89
|
+
files.push(await writeOwned(cwd, CLAUDE_MD_PATH, claudeMd(), force));
|
|
90
|
+
files.push(await ensureAgentsMd(cwd));
|
|
91
|
+
return { cwd, files };
|
|
92
|
+
}
|
|
93
|
+
const ACTION_GLYPH = {
|
|
94
|
+
wrote: "✓ wrote",
|
|
95
|
+
appended: "✓ appended MCP section to",
|
|
96
|
+
skipped: "• skipped",
|
|
97
|
+
present: "• kept",
|
|
98
|
+
};
|
|
99
|
+
/** Format the retrofit result for the terminal. */
|
|
100
|
+
export function renderInitAgents(result) {
|
|
101
|
+
const lines = result.files.map((f) => {
|
|
102
|
+
const tail = f.note ? ` (${f.note})` : "";
|
|
103
|
+
return ` ${ACTION_GLYPH[f.action]} ${f.path}${tail}`;
|
|
104
|
+
});
|
|
105
|
+
const wroteAny = result.files.some((f) => f.action === "wrote" || f.action === "appended");
|
|
106
|
+
const footer = wroteAny
|
|
107
|
+
? "\nThe nifra MCP is now registered. Restart your agent so it picks up .mcp.json, then prefer nifra_docs / nifra_example and gate on nifra check."
|
|
108
|
+
: "\nNothing to do — every file was already present (use --force to overwrite the owned ones).";
|
|
109
|
+
return `nifra init-agents\n\n${lines.join("\n")}\n${footer}`;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* CLI entry: run the retrofit at `cwd` and print the result. Returns `true` (the command always succeeds
|
|
113
|
+
* unless a write throws — which propagates as a non-zero exit via the dispatcher's catch). `--json`
|
|
114
|
+
* emits the structured result for agents/CI.
|
|
115
|
+
*/
|
|
116
|
+
export async function runInitAgents(cwd, opts = {}) {
|
|
117
|
+
const result = await initAgents(cwd, { force: opts.force ?? false });
|
|
118
|
+
if (opts.json) {
|
|
119
|
+
console.log(JSON.stringify(result, null, 2));
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
console.log(renderInitAgents(result));
|
|
123
|
+
}
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=init-agents.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init-agents.js","sourceRoot":"","sources":["../src/init-agents.ts"],"names":[],"mappings":"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"}
|
package/dist/introspect.d.ts
CHANGED
|
@@ -13,6 +13,8 @@ interface RouteDesc {
|
|
|
13
13
|
readonly path: string;
|
|
14
14
|
readonly schema?: unknown;
|
|
15
15
|
}
|
|
16
|
+
/** Read the backend's registered routes, if it's a `server()` with a `.routes()` method. */
|
|
17
|
+
export declare function backendRoutes(backend: unknown): RouteDesc[];
|
|
16
18
|
/**
|
|
17
19
|
* Render a JSON Schema as a compact TypeScript-like type (`{ id: string, name?: string }`) — the
|
|
18
20
|
* shape agents already think in, at a fraction of the raw JSON Schema's tokens (~70-80% smaller).
|
|
@@ -31,6 +33,11 @@ export declare function tsTypeOf(schema: unknown, depth?: number): string;
|
|
|
31
33
|
export declare function clientCall(method: string, path: string, schema: unknown): string;
|
|
32
34
|
/** Markdown section listing the backend's API routes with their request + response field shapes. */
|
|
33
35
|
export declare function apiRoutesSection(routes: readonly RouteDesc[]): string;
|
|
36
|
+
/** Compact API-routes INDEX for the no-arg `nifra_context` call — `METHOD path` per route, WITHOUT the
|
|
37
|
+
* body/query/response shapes or the per-route `call` line. Bounds the first-call payload on a big backend:
|
|
38
|
+
* an agent gets the full route list (so it knows what's mounted) plus a pointer to fetch any route's full
|
|
39
|
+
* contract via the `path`/`kind` slice, instead of every schema up front. */
|
|
40
|
+
export declare function apiRoutesIndexSection(routes: readonly RouteDesc[]): string;
|
|
34
41
|
/** Markdown section listing the file-routed pages (URL pattern → source file). */
|
|
35
42
|
export declare function pageRoutesSection(manifest: Manifest | undefined): string;
|
|
36
43
|
/** Optional narrowing for {@link describeProject} — a path prefix and/or one section. A filtered
|
|
@@ -40,8 +47,14 @@ export interface ContextFilter {
|
|
|
40
47
|
readonly path?: string;
|
|
41
48
|
readonly kind?: "api" | "pages";
|
|
42
49
|
}
|
|
43
|
-
/**
|
|
44
|
-
*
|
|
50
|
+
/**
|
|
51
|
+
* Build the project brief as Markdown. A no-arg call returns a tight **INDEX** — the route list (API
|
|
52
|
+
* routes as `METHOD path`, page routes as `pattern → file`) + conventions + a pointer to fetch full
|
|
53
|
+
* contracts via the slice — so learning a big project is cheap, not a full-surface schema dump. Passing a
|
|
54
|
+
* {@link ContextFilter} (`path` prefix and/or `kind`) returns the narrowed, FULL detail (per-route
|
|
55
|
+
* body/query/response shapes + the typed-client `call` form), and omits the conventions block (the agent
|
|
56
|
+
* already has it from the index call).
|
|
57
|
+
*/
|
|
45
58
|
export declare function describeProject(app: LoadedApp, filter?: ContextFilter): string;
|
|
46
59
|
/** One API route as structured JSON: method, path, the exact typed-client call form, and compact
|
|
47
60
|
* TS-shaped request/response contracts (present only when the route declares the schema). */
|
|
@@ -60,5 +73,67 @@ export interface RouteJson {
|
|
|
60
73
|
* same `call` form and TS-shaped contracts the Markdown brief shows.
|
|
61
74
|
*/
|
|
62
75
|
export declare function routesToJson(app: LoadedApp, pathPrefix?: string): RouteJson[];
|
|
76
|
+
/** The kind of route: a file-routed `page` (SSR/SSG) or a backend `api` (HTTP handler). */
|
|
77
|
+
export type RouteKind = "page" | "api";
|
|
78
|
+
/** One row of the unified route table. */
|
|
79
|
+
export interface RouteTableEntry {
|
|
80
|
+
readonly kind: RouteKind;
|
|
81
|
+
/** The URL pattern (page: `/blog/:slug`; api: `/api/users`). */
|
|
82
|
+
readonly path: string;
|
|
83
|
+
/** Methods this route serves, sorted (page: `GET`, plus `POST` when it has an `action`). */
|
|
84
|
+
readonly methods: readonly string[];
|
|
85
|
+
/** Source file (page only — the route module path relative to `routes/`). */
|
|
86
|
+
readonly file?: string;
|
|
87
|
+
/** True when this API route is auto-mounted under the page router's `apiPrefix` (so it's reachable
|
|
88
|
+
* through the same web app, no hand-wired `if (pathname.startsWith("/api/"))`). Pages are never
|
|
89
|
+
* auto-mounted (they ARE the page router); only API routes carry this flag. */
|
|
90
|
+
readonly autoMounted?: boolean;
|
|
91
|
+
}
|
|
92
|
+
/** A page route + whether its module exports an `action` (→ it also serves POST). The caller resolves
|
|
93
|
+
* `hasAction` (a module load); kept out of the pure builder so the builder needs no fs. */
|
|
94
|
+
export interface PageRouteInput {
|
|
95
|
+
readonly pattern: string;
|
|
96
|
+
readonly file: string;
|
|
97
|
+
readonly hasAction: boolean;
|
|
98
|
+
}
|
|
99
|
+
export interface RouteTableInput {
|
|
100
|
+
readonly pages: readonly PageRouteInput[];
|
|
101
|
+
readonly api: readonly RouteDesc[];
|
|
102
|
+
/** The page router's `apiPrefix` (default `/api`); an API route at/under it is auto-mounted. `""`
|
|
103
|
+
* disables the auto-mount, so no API route is marked auto-mounted. */
|
|
104
|
+
readonly apiPrefix?: string;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Build the unified, sorted route table from page routes + backend API routes. Pure — the caller
|
|
108
|
+
* supplies page `hasAction` (resolved via a module load) and the API descriptors (`backend.routes()`).
|
|
109
|
+
* Page routes serve `GET` (+ `POST` when they export an `action`); API routes carry their declared
|
|
110
|
+
* method, and are flagged `autoMounted` when at/under `apiPrefix`. Sorted by path, then kind, then the
|
|
111
|
+
* joined methods, for stable output.
|
|
112
|
+
*/
|
|
113
|
+
export declare function buildRouteTable(input: RouteTableInput): RouteTableEntry[];
|
|
114
|
+
/** Render the route table as a terse aligned text table (the `nifra routes` default output). Pure. */
|
|
115
|
+
export declare function renderRouteTable(rows: readonly RouteTableEntry[]): string;
|
|
116
|
+
/** One JSON row for `nifra routes --json` (the agent-facing, stable shape). */
|
|
117
|
+
export interface RouteJsonRow {
|
|
118
|
+
readonly kind: RouteKind;
|
|
119
|
+
readonly path: string;
|
|
120
|
+
readonly methods: readonly string[];
|
|
121
|
+
readonly file?: string;
|
|
122
|
+
readonly autoMounted?: boolean;
|
|
123
|
+
}
|
|
124
|
+
/** The route table as a JSON document for `--json` (agents). Stable keys; `file`/`autoMounted` present
|
|
125
|
+
* only where meaningful (file on pages, autoMounted on API routes). */
|
|
126
|
+
export declare function routeTableToJson(rows: readonly RouteTableEntry[]): {
|
|
127
|
+
readonly routes: readonly RouteJsonRow[];
|
|
128
|
+
};
|
|
129
|
+
/**
|
|
130
|
+
* Gather + render the unified route table for `nifra routes`. Discovers page routes (`discoverRoutes`),
|
|
131
|
+
* loads each module to detect an `action` export (→ POST), reads the backend's API routes, then renders
|
|
132
|
+
* text (default) or JSON (`--json`). The page-route load mirrors what SSR would do; a load failure
|
|
133
|
+
* degrades to GET-only for that route (never throws the whole command).
|
|
134
|
+
*/
|
|
135
|
+
export declare function describeRoutes(app: LoadedApp, opts?: {
|
|
136
|
+
readonly json?: boolean;
|
|
137
|
+
}): Promise<string>;
|
|
63
138
|
export {};
|
|
64
139
|
//# sourceMappingURL=introspect.d.ts.map
|
package/dist/introspect.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"introspect.d.ts","sourceRoot":"","sources":["../src/introspect.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAE5C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAE1C;uDACuD;AACvD,UAAU,SAAS;IACjB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAC1B;
|
|
1
|
+
{"version":3,"file":"introspect.d.ts","sourceRoot":"","sources":["../src/introspect.ts"],"names":[],"mappings":"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"}
|
package/dist/introspect.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { discoverRoutes } from "@nifrajs/web/fs";
|
|
8
8
|
/** Read the backend's registered routes, if it's a `server()` with a `.routes()` method. */
|
|
9
|
-
function backendRoutes(backend) {
|
|
9
|
+
export function backendRoutes(backend) {
|
|
10
10
|
if (backend && typeof backend.routes === "function") {
|
|
11
11
|
try {
|
|
12
12
|
return backend.routes();
|
|
@@ -144,6 +144,19 @@ export function apiRoutesSection(routes) {
|
|
|
144
144
|
]);
|
|
145
145
|
return `## API routes (backend.ts)\n\nEach route's \`body\`/\`query\`/\`response\` shape is its contract — the typed client derives request inputs and \`res.data\` from these, so a screen built on \`client<typeof app>\` stays in sync automatically. The \`call\` line is the exact \`client<typeof app>\` form: static path segments are properties, a path param is a call (\`({ id })\`), the verb is the terminal call (body first for POST/PUT/PATCH), and every call returns the never-throwing \`{ ok, status, data, error }\` Result.\n\n${lines.join("\n")}`;
|
|
146
146
|
}
|
|
147
|
+
/** Compact API-routes INDEX for the no-arg `nifra_context` call — `METHOD path` per route, WITHOUT the
|
|
148
|
+
* body/query/response shapes or the per-route `call` line. Bounds the first-call payload on a big backend:
|
|
149
|
+
* an agent gets the full route list (so it knows what's mounted) plus a pointer to fetch any route's full
|
|
150
|
+
* contract via the `path`/`kind` slice, instead of every schema up front. */
|
|
151
|
+
export function apiRoutesIndexSection(routes) {
|
|
152
|
+
if (routes.length === 0) {
|
|
153
|
+
return "## API routes (backend.ts)\n\nNo `backend.ts` server routes found (this app may be frontend-only).";
|
|
154
|
+
}
|
|
155
|
+
const lines = [...routes]
|
|
156
|
+
.sort((a, b) => a.path.localeCompare(b.path) || a.method.localeCompare(b.method))
|
|
157
|
+
.map((r) => `- \`${r.method} ${r.path}\``);
|
|
158
|
+
return `## API routes (backend.ts)\n\n${routes.length} route${routes.length === 1 ? "" : "s"}. Call \`nifra_context\` again with \`path\` (a route prefix) and/or \`kind: "api"\` for the body/query/response contracts + the exact \`client<typeof app>\` call form — or \`nifra_routes\` for the same as structured JSON.\n\n${lines.join("\n")}`;
|
|
159
|
+
}
|
|
147
160
|
/** Markdown section listing the file-routed pages (URL pattern → source file). */
|
|
148
161
|
export function pageRoutesSection(manifest) {
|
|
149
162
|
if (!manifest || manifest.routes.length === 0) {
|
|
@@ -170,8 +183,14 @@ const CONVENTIONS = `## Conventions (summary)
|
|
|
170
183
|
for the browser — **never top-level-import server-only code** (DB, secrets, \`process.env\`) into a route
|
|
171
184
|
file; reach it via \`ctx.api\` / \`ctx.env\`.
|
|
172
185
|
- \`app.fetch(Request)\` is the universal entry. Full reference: this repo's \`AGENTS.md\`, or \`llms-full.txt\`.`;
|
|
173
|
-
/**
|
|
174
|
-
*
|
|
186
|
+
/**
|
|
187
|
+
* Build the project brief as Markdown. A no-arg call returns a tight **INDEX** — the route list (API
|
|
188
|
+
* routes as `METHOD path`, page routes as `pattern → file`) + conventions + a pointer to fetch full
|
|
189
|
+
* contracts via the slice — so learning a big project is cheap, not a full-surface schema dump. Passing a
|
|
190
|
+
* {@link ContextFilter} (`path` prefix and/or `kind`) returns the narrowed, FULL detail (per-route
|
|
191
|
+
* body/query/response shapes + the typed-client `call` form), and omits the conventions block (the agent
|
|
192
|
+
* already has it from the index call).
|
|
193
|
+
*/
|
|
175
194
|
export function describeProject(app, filter) {
|
|
176
195
|
let manifest;
|
|
177
196
|
try {
|
|
@@ -189,19 +208,23 @@ export function describeProject(app, filter) {
|
|
|
189
208
|
pages = { ...manifest, routes: manifest.routes.filter((r) => r.pattern.startsWith(prefix)) };
|
|
190
209
|
}
|
|
191
210
|
}
|
|
192
|
-
|
|
211
|
+
// No `path` and no `kind` → the first-call index (compact route list, no per-route schemas). Any filter
|
|
212
|
+
// → the narrowed full-detail slice (schemas + call form), unchanged.
|
|
213
|
+
const isIndex = filter?.kind === undefined && (prefix === undefined || prefix === "");
|
|
193
214
|
const sections = [`# nifra project: ${app.cwd.slice(app.cwd.lastIndexOf("/") + 1)}`];
|
|
194
|
-
if (
|
|
195
|
-
sections.push("A full-stack nifra app — Web-standard, one app on Bun, Node, Deno, and the edge.",
|
|
215
|
+
if (isIndex) {
|
|
216
|
+
sections.push("A full-stack nifra app — Web-standard, one app on Bun, Node, Deno, and the edge. This is the route INDEX; fetch a route's full body/query/response contract on demand (see below).",
|
|
196
217
|
// Point agents at the verified surface, not recalled APIs — nifra is young, so training data is the
|
|
197
218
|
// wrong source. The MCP tools (nifra_docs / nifra_example) are checked against the installed version.
|
|
198
219
|
"> **Build against THIS surface + the verified tools — do not write nifra APIs from memory** (the\n> framework is young; recalled APIs drift). For framework code, call `nifra_example` (snippets\n> typechecked against the installed version) or `nifra_docs`; verify edits with `nifra_run` + `nifra_check`.");
|
|
199
220
|
}
|
|
200
|
-
if (filter?.kind !== "pages")
|
|
201
|
-
|
|
221
|
+
if (filter?.kind !== "pages") {
|
|
222
|
+
// Index → compact `METHOD path` list; a slice → the full schema + call-form detail.
|
|
223
|
+
sections.push(isIndex ? apiRoutesIndexSection(routes) : apiRoutesSection(routes));
|
|
224
|
+
}
|
|
202
225
|
if (filter?.kind !== "api")
|
|
203
226
|
sections.push(pageRoutesSection(pages));
|
|
204
|
-
if (
|
|
227
|
+
if (isIndex)
|
|
205
228
|
sections.push(CONVENTIONS);
|
|
206
229
|
return sections.join("\n\n");
|
|
207
230
|
}
|
|
@@ -240,4 +263,110 @@ export function routesToJson(app, pathPrefix) {
|
|
|
240
263
|
};
|
|
241
264
|
});
|
|
242
265
|
}
|
|
266
|
+
/** True when `path` is at or under `prefix` as a path segment boundary (`/api` matches `/api` and
|
|
267
|
+
* `/api/x`, but not `/apiary`). An empty prefix matches nothing (auto-mount disabled). */
|
|
268
|
+
function isUnderPrefix(path, prefix) {
|
|
269
|
+
if (prefix === "")
|
|
270
|
+
return false;
|
|
271
|
+
return path === prefix || path.startsWith(`${prefix}/`);
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Build the unified, sorted route table from page routes + backend API routes. Pure — the caller
|
|
275
|
+
* supplies page `hasAction` (resolved via a module load) and the API descriptors (`backend.routes()`).
|
|
276
|
+
* Page routes serve `GET` (+ `POST` when they export an `action`); API routes carry their declared
|
|
277
|
+
* method, and are flagged `autoMounted` when at/under `apiPrefix`. Sorted by path, then kind, then the
|
|
278
|
+
* joined methods, for stable output.
|
|
279
|
+
*/
|
|
280
|
+
export function buildRouteTable(input) {
|
|
281
|
+
const apiPrefix = input.apiPrefix ?? "/api";
|
|
282
|
+
const rows = [];
|
|
283
|
+
for (const page of input.pages) {
|
|
284
|
+
const methods = page.hasAction ? ["GET", "POST"] : ["GET"];
|
|
285
|
+
rows.push({ kind: "page", path: page.pattern, methods, file: page.file });
|
|
286
|
+
}
|
|
287
|
+
// Collapse API routes that share a path into one row with all its methods (a REST resource).
|
|
288
|
+
const byPath = new Map();
|
|
289
|
+
for (const r of input.api) {
|
|
290
|
+
const existing = byPath.get(r.path);
|
|
291
|
+
if (existing === undefined) {
|
|
292
|
+
byPath.set(r.path, {
|
|
293
|
+
methods: new Set([r.method.toUpperCase()]),
|
|
294
|
+
autoMounted: isUnderPrefix(r.path, apiPrefix),
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
else
|
|
298
|
+
existing.methods.add(r.method.toUpperCase());
|
|
299
|
+
}
|
|
300
|
+
for (const [path, info] of byPath) {
|
|
301
|
+
rows.push({
|
|
302
|
+
kind: "api",
|
|
303
|
+
path,
|
|
304
|
+
methods: [...info.methods].sort(),
|
|
305
|
+
autoMounted: info.autoMounted,
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
return rows.sort((a, b) => a.path.localeCompare(b.path) ||
|
|
309
|
+
a.kind.localeCompare(b.kind) ||
|
|
310
|
+
a.methods.join(",").localeCompare(b.methods.join(",")));
|
|
311
|
+
}
|
|
312
|
+
/** Render the route table as a terse aligned text table (the `nifra routes` default output). Pure. */
|
|
313
|
+
export function renderRouteTable(rows) {
|
|
314
|
+
if (rows.length === 0)
|
|
315
|
+
return "No routes found (no `routes/` pages and no `backend.ts` API routes).";
|
|
316
|
+
const display = rows.map((r) => ({
|
|
317
|
+
methods: r.methods.join(", "),
|
|
318
|
+
kind: r.kind,
|
|
319
|
+
path: r.kind === "api" && r.autoMounted ? `${r.path} (auto-mounted)` : r.path,
|
|
320
|
+
}));
|
|
321
|
+
const methodW = Math.max("METHOD".length, ...display.map((d) => d.methods.length));
|
|
322
|
+
const kindW = Math.max("KIND".length, ...display.map((d) => d.kind.length));
|
|
323
|
+
const padEnd = (s, w) => s + " ".repeat(Math.max(0, w - s.length));
|
|
324
|
+
const line = (methods, kind, path) => `${padEnd(methods, methodW)} ${padEnd(kind, kindW)} ${path}`;
|
|
325
|
+
return [
|
|
326
|
+
line("METHOD", "KIND", "PATH"),
|
|
327
|
+
...display.map((d) => line(d.methods, d.kind, d.path)),
|
|
328
|
+
].join("\n");
|
|
329
|
+
}
|
|
330
|
+
/** The route table as a JSON document for `--json` (agents). Stable keys; `file`/`autoMounted` present
|
|
331
|
+
* only where meaningful (file on pages, autoMounted on API routes). */
|
|
332
|
+
export function routeTableToJson(rows) {
|
|
333
|
+
return {
|
|
334
|
+
routes: rows.map((r) => ({
|
|
335
|
+
kind: r.kind,
|
|
336
|
+
path: r.path,
|
|
337
|
+
methods: r.methods,
|
|
338
|
+
...(r.file !== undefined ? { file: r.file } : {}),
|
|
339
|
+
...(r.kind === "api" ? { autoMounted: r.autoMounted === true } : {}),
|
|
340
|
+
})),
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Gather + render the unified route table for `nifra routes`. Discovers page routes (`discoverRoutes`),
|
|
345
|
+
* loads each module to detect an `action` export (→ POST), reads the backend's API routes, then renders
|
|
346
|
+
* text (default) or JSON (`--json`). The page-route load mirrors what SSR would do; a load failure
|
|
347
|
+
* degrades to GET-only for that route (never throws the whole command).
|
|
348
|
+
*/
|
|
349
|
+
export async function describeRoutes(app, opts = {}) {
|
|
350
|
+
let manifest;
|
|
351
|
+
try {
|
|
352
|
+
manifest = discoverRoutes(app.routesDir);
|
|
353
|
+
}
|
|
354
|
+
catch {
|
|
355
|
+
// No (or unreadable) routes/ — fall through with no pages; the table still shows API routes.
|
|
356
|
+
}
|
|
357
|
+
const pages = [];
|
|
358
|
+
for (const route of manifest?.routes ?? []) {
|
|
359
|
+
let hasAction = false;
|
|
360
|
+
try {
|
|
361
|
+
const mod = (await route.load());
|
|
362
|
+
hasAction = typeof mod.action === "function";
|
|
363
|
+
}
|
|
364
|
+
catch {
|
|
365
|
+
// A route that can't be loaded at introspection time (e.g. a server-only import) → GET-only.
|
|
366
|
+
}
|
|
367
|
+
pages.push({ pattern: route.pattern, file: route.file, hasAction });
|
|
368
|
+
}
|
|
369
|
+
const rows = buildRouteTable({ pages, api: backendRoutes(app.backend) });
|
|
370
|
+
return opts.json ? JSON.stringify(routeTableToJson(rows), null, 2) : renderRouteTable(rows);
|
|
371
|
+
}
|
|
243
372
|
//# sourceMappingURL=introspect.js.map
|
package/dist/introspect.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"introspect.js","sourceRoot":"","sources":["../src/introspect.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"introspect.js","sourceRoot":"","sources":["../src/introspect.ts"],"names":[],"mappings":"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"}
|
package/dist/mcp-render.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-render.d.ts","sourceRoot":"","sources":["../src/mcp-render.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;
|
|
1
|
+
{"version":3,"file":"mcp-render.d.ts","sourceRoot":"","sources":["../src/mcp-render.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AA+CH,wBAAsB,WAAW,CAC/B,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,OAAO,GAChB,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAWnD"}
|
package/dist/mcp-render.js
CHANGED
|
@@ -15,9 +15,10 @@ import { createWebApp } from "@nifrajs/web";
|
|
|
15
15
|
import { discoverRoutes } from "@nifrajs/web/fs";
|
|
16
16
|
import { loadApp, resolvePlugins } from "./load.js";
|
|
17
17
|
const errString = (err) => err instanceof Error ? `${err.name}: ${err.message}` : String(err);
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
/** Load the project, register its SSR plugins, and build the SSR `createWebApp` once — the cost the warm
|
|
19
|
+
* worker amortizes across calls. Never throws (every failure → `{ error }`). Factored out of
|
|
20
|
+
* {@link renderPages} so the cold path (fresh process per call) and the warm worker share one builder. */
|
|
21
|
+
async function buildWebApp(cwd) {
|
|
21
22
|
let app;
|
|
22
23
|
try {
|
|
23
24
|
app = await loadApp(cwd, "dist");
|
|
@@ -36,30 +37,120 @@ export async function renderPages(cwd, requests) {
|
|
|
36
37
|
catch (err) {
|
|
37
38
|
return { error: errString(err) };
|
|
38
39
|
}
|
|
39
|
-
let webApp;
|
|
40
40
|
try {
|
|
41
|
-
webApp = createWebApp({
|
|
41
|
+
const webApp = createWebApp({
|
|
42
42
|
// The adapter is validated by loadApp; cast at the seam (same as the CLI's `asAdapter`).
|
|
43
43
|
adapter: app.framework.adapter,
|
|
44
44
|
manifest: discoverRoutes(app.routesDir),
|
|
45
45
|
clientEntry: "/_nifra-render-only.js", // placeholder; SSR HTML does not need the built client
|
|
46
46
|
...(app.backend !== undefined ? { api: inProcessClient(app.backend) } : {}),
|
|
47
47
|
});
|
|
48
|
+
return { app: webApp };
|
|
48
49
|
}
|
|
49
50
|
catch (err) {
|
|
50
51
|
return { error: errString(err) };
|
|
51
52
|
}
|
|
53
|
+
}
|
|
54
|
+
export async function renderPages(cwd, requests) {
|
|
55
|
+
if (!Array.isArray(requests))
|
|
56
|
+
return { error: "expected { requests: [...] }" };
|
|
57
|
+
const built = await buildWebApp(cwd);
|
|
58
|
+
if ("error" in built)
|
|
59
|
+
return built;
|
|
52
60
|
try {
|
|
53
|
-
return { results: await runApp(
|
|
61
|
+
return { results: await runApp(built.app, requests) };
|
|
54
62
|
}
|
|
55
63
|
catch (err) {
|
|
56
64
|
return { error: errString(err) };
|
|
57
65
|
}
|
|
58
66
|
}
|
|
59
|
-
|
|
60
|
-
|
|
67
|
+
/** Send console output to stderr so it never corrupts the newline-delimited JSON-RPC on stdout (mirrors
|
|
68
|
+
* `mcp-run`'s worker). A loader that logs would otherwise inject noise into a response line. */
|
|
69
|
+
function redirectConsoleToStderr() {
|
|
70
|
+
const write = (level, args) => {
|
|
71
|
+
Bun.stderr.write(`[${level}] ${args.map((arg) => String(arg)).join(" ")}\n`);
|
|
72
|
+
};
|
|
73
|
+
console.debug = (...args) => write("debug", args);
|
|
74
|
+
console.info = (...args) => write("info", args);
|
|
75
|
+
console.log = (...args) => write("log", args);
|
|
76
|
+
console.warn = (...args) => write("warn", args);
|
|
77
|
+
console.error = (...args) => write("error", args);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Warm-worker loop (`--worker`): build the web app ONCE, then SSR each `{ id, input: { requests } }` line
|
|
81
|
+
* against that hot app and reply `{ id, output }`. The parent (`mcp.ts`'s warm-render handler) spawns this,
|
|
82
|
+
* fingerprints the source tree, and restarts the worker when a file changes — so warm reuse never serves a
|
|
83
|
+
* stale render. Mirrors `mcp-run.ts`'s worker (single backend entry → no per-call entry key needed here).
|
|
84
|
+
*/
|
|
85
|
+
async function runWorker(cwd) {
|
|
86
|
+
redirectConsoleToStderr();
|
|
87
|
+
// Build once; the same `{ error }` is returned for every request if the build failed, so an agent sees
|
|
88
|
+
// the actionable message and the parent restarts the worker on the next file change.
|
|
89
|
+
const built = await buildWebApp(cwd);
|
|
90
|
+
const decoder = new TextDecoder();
|
|
91
|
+
let buffer = "";
|
|
92
|
+
const send = (id, output) => {
|
|
93
|
+
process.stdout.write(`${JSON.stringify({ id, output })}\n`);
|
|
94
|
+
};
|
|
95
|
+
for await (const chunk of Bun.stdin.stream()) {
|
|
96
|
+
buffer += decoder.decode(chunk, { stream: true });
|
|
97
|
+
let nl = buffer.indexOf("\n");
|
|
98
|
+
while (nl !== -1) {
|
|
99
|
+
const line = buffer.slice(0, nl).trim();
|
|
100
|
+
buffer = buffer.slice(nl + 1);
|
|
101
|
+
nl = buffer.indexOf("\n");
|
|
102
|
+
if (line === "")
|
|
103
|
+
continue;
|
|
104
|
+
let message;
|
|
105
|
+
try {
|
|
106
|
+
message = JSON.parse(line);
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
send(null, { error: "invalid worker input: expected JSON line" });
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
const requests = message.input?.requests;
|
|
113
|
+
if (!Array.isArray(requests)) {
|
|
114
|
+
send(message.id, { error: "expected { requests: [...] }" });
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
if ("error" in built) {
|
|
118
|
+
send(message.id, built);
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
try {
|
|
122
|
+
send(message.id, {
|
|
123
|
+
results: await runApp(built.app, requests),
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
catch (err) {
|
|
127
|
+
send(message.id, { error: errString(err) });
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
// Child-process entry: read `{ requests }` from stdin, SSR, print JSON. `--worker` runs the persistent
|
|
133
|
+
// warm loop instead. Guarded so importing this module in a test does not execute it.
|
|
61
134
|
if (import.meta.main) {
|
|
62
135
|
const cwd = process.argv[2] ?? process.cwd();
|
|
136
|
+
// The parent (mcp.ts) spawns `bun mcp-render.ts <cwd>` WITHOUT setting the subprocess `cwd` option, so
|
|
137
|
+
// this process inherits the MCP server's working dir, not the app's. SSR resolves `react-dom/server`
|
|
138
|
+
// from `process.cwd()` to share ONE React core with the app's route components (the dual-React fix in
|
|
139
|
+
// @nifrajs/web-react) — so we must chdir to the app root before any render. Best-effort: a bad path
|
|
140
|
+
// surfaces later as a load error rather than crashing the child here.
|
|
141
|
+
if (cwd !== process.cwd()) {
|
|
142
|
+
try {
|
|
143
|
+
process.chdir(cwd);
|
|
144
|
+
}
|
|
145
|
+
catch {
|
|
146
|
+
// Leave cwd as-is; loadApp(cwd) below uses the explicit `cwd` arg and will report an actionable
|
|
147
|
+
// error if the directory is unusable. The adapter then falls back to its bundled react-dom.
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
if (process.argv.includes("--worker")) {
|
|
151
|
+
await runWorker(cwd);
|
|
152
|
+
process.exit(0);
|
|
153
|
+
}
|
|
63
154
|
let output;
|
|
64
155
|
try {
|
|
65
156
|
const { requests } = JSON.parse(await Bun.stdin.text());
|