@nifrajs/cli 0.1.0-alpha.1

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.
Files changed (95) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +99 -0
  3. package/dist/check.d.ts +100 -0
  4. package/dist/check.d.ts.map +1 -0
  5. package/dist/check.js +690 -0
  6. package/dist/check.js.map +1 -0
  7. package/dist/cli.d.ts +3 -0
  8. package/dist/cli.d.ts.map +1 -0
  9. package/dist/cli.js +208 -0
  10. package/dist/cli.js.map +1 -0
  11. package/dist/docs-search.d.ts +30 -0
  12. package/dist/docs-search.d.ts.map +1 -0
  13. package/dist/docs-search.js +94 -0
  14. package/dist/docs-search.js.map +1 -0
  15. package/dist/doctor.d.ts +52 -0
  16. package/dist/doctor.d.ts.map +1 -0
  17. package/dist/doctor.js +291 -0
  18. package/dist/doctor.js.map +1 -0
  19. package/dist/examples.d.ts +30 -0
  20. package/dist/examples.d.ts.map +1 -0
  21. package/dist/examples.js +70 -0
  22. package/dist/examples.js.map +1 -0
  23. package/dist/introspect.d.ts +64 -0
  24. package/dist/introspect.d.ts.map +1 -0
  25. package/dist/introspect.js +243 -0
  26. package/dist/introspect.js.map +1 -0
  27. package/dist/load.d.ts +51 -0
  28. package/dist/load.d.ts.map +1 -0
  29. package/dist/load.js +70 -0
  30. package/dist/load.js.map +1 -0
  31. package/dist/mcp-docs-tools.d.ts +13 -0
  32. package/dist/mcp-docs-tools.d.ts.map +1 -0
  33. package/dist/mcp-docs-tools.js +63 -0
  34. package/dist/mcp-docs-tools.js.map +1 -0
  35. package/dist/mcp-http.d.ts +43 -0
  36. package/dist/mcp-http.d.ts.map +1 -0
  37. package/dist/mcp-http.js +136 -0
  38. package/dist/mcp-http.js.map +1 -0
  39. package/dist/mcp-protocol.d.ts +97 -0
  40. package/dist/mcp-protocol.d.ts.map +1 -0
  41. package/dist/mcp-protocol.js +248 -0
  42. package/dist/mcp-protocol.js.map +1 -0
  43. package/dist/mcp-render.d.ts +17 -0
  44. package/dist/mcp-render.d.ts.map +1 -0
  45. package/dist/mcp-render.js +73 -0
  46. package/dist/mcp-render.js.map +1 -0
  47. package/dist/mcp-run.d.ts +24 -0
  48. package/dist/mcp-run.d.ts.map +1 -0
  49. package/dist/mcp-run.js +142 -0
  50. package/dist/mcp-run.js.map +1 -0
  51. package/dist/mcp-ws.d.ts +26 -0
  52. package/dist/mcp-ws.d.ts.map +1 -0
  53. package/dist/mcp-ws.js +258 -0
  54. package/dist/mcp-ws.js.map +1 -0
  55. package/dist/mcp.d.ts +42 -0
  56. package/dist/mcp.d.ts.map +1 -0
  57. package/dist/mcp.js +712 -0
  58. package/dist/mcp.js.map +1 -0
  59. package/dist/openapi-tool.d.ts +6 -0
  60. package/dist/openapi-tool.d.ts.map +1 -0
  61. package/dist/openapi-tool.js +48 -0
  62. package/dist/openapi-tool.js.map +1 -0
  63. package/dist/scaffold.d.ts +35 -0
  64. package/dist/scaffold.d.ts.map +1 -0
  65. package/dist/scaffold.js +140 -0
  66. package/dist/scaffold.js.map +1 -0
  67. package/dist/search-terms.d.ts +17 -0
  68. package/dist/search-terms.d.ts.map +1 -0
  69. package/dist/search-terms.js +82 -0
  70. package/dist/search-terms.js.map +1 -0
  71. package/dist/test-tool.d.ts +29 -0
  72. package/dist/test-tool.d.ts.map +1 -0
  73. package/dist/test-tool.js +150 -0
  74. package/dist/test-tool.js.map +1 -0
  75. package/docs/examples.json +314 -0
  76. package/docs/llms-full.txt +4325 -0
  77. package/package.json +58 -0
  78. package/src/check.ts +790 -0
  79. package/src/cli.ts +237 -0
  80. package/src/docs-search.ts +111 -0
  81. package/src/doctor.ts +349 -0
  82. package/src/examples.ts +89 -0
  83. package/src/introspect.ts +284 -0
  84. package/src/load.ts +129 -0
  85. package/src/mcp-docs-tools.ts +72 -0
  86. package/src/mcp-http.ts +155 -0
  87. package/src/mcp-protocol.ts +326 -0
  88. package/src/mcp-render.ts +78 -0
  89. package/src/mcp-run.ts +153 -0
  90. package/src/mcp-ws.ts +328 -0
  91. package/src/mcp.ts +863 -0
  92. package/src/openapi-tool.ts +51 -0
  93. package/src/scaffold.ts +164 -0
  94. package/src/search-terms.ts +89 -0
  95. package/src/test-tool.ts +181 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Nifra Authors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,99 @@
1
+ # @nifrajs/cli
2
+
3
+ The `nifra` CLI — zero-config dev/build/start for a nifra app, plus the agent surfaces (`nifra context`,
4
+ `nifra mcp`). Run from your project root (it reads `nifra.config.ts`/`framework.ts`, `backend.ts`, and
5
+ `routes/`).
6
+
7
+ ```
8
+ nifra dev [--port <n>] [--poll] True-HMR dev server (Vite + nifra SSR).
9
+ nifra build [--out <dir>] Content-hashed client bundle + manifest.json.
10
+ nifra start [--port <n>] [--out <dir>] Serve the built app (client + SSR) on Bun.
11
+ nifra context Print this project's API + page routes + conventions.
12
+ nifra mcp MCP server (stdio) exposing this project to a coding agent.
13
+ nifra check [--json] Gate: typecheck + lints; --json includes fixes/suggestions.
14
+ nifra doctor [--json] [--auto-fix] Catch undeclared imported packages; auto-fix safe local versions.
15
+ ```
16
+
17
+ ## `nifra check` — the drift gate (run as "done")
18
+
19
+ `nifra check` makes nifra's anti-drift guarantees actually fire instead of relying on the agent to
20
+ remember them. It does three things and exits non-zero if any fails:
21
+
22
+ 1. **Typecheck** (`tsc --noEmit`, using the project's own TypeScript) — the frontend↔backend contract is
23
+ compiler-enforced. `client<typeof app>` derives request inputs **and** `res.data` from your routes, so
24
+ a screen that expects the wrong shape is a type error. Running the typecheck is what turns that latent
25
+ guarantee into an enforced one.
26
+ 2. **Typed-client lint** — flags any hand-rolled `fetch()` to your own API (a relative URL like
27
+ `fetch("/users")`), which bypasses the typed client so the compiler can't see the drift. External
28
+ absolute-URL fetches are not flagged.
29
+ 3. **Server-only-import lint** — flags a top-level import of server-only code (a DB driver, `node:`/`bun:`
30
+ builtins, the `./db` module) into a `routes/` page module. Those modules are bundled for the browser,
31
+ so the import ships server code to the client. Reach it via `c.db` / `ctx.api` inside a loader instead.
32
+
33
+ Pass **`--json`** for a machine-readable result (`{ ok, typecheck, diagnostics[] }`) — what the
34
+ `nifra_check` MCP tool returns, so an agent acts on diagnostics instead of scraping output. Each diagnostic
35
+ has a short `fix` string and, when safe, a structured `suggestion`: an exact one-line diff, an argv command
36
+ array (for example `["bun","add","react"]`), or concrete manual steps. Tell a coding agent to run
37
+ `nifra check` as its definition of done (the scaffolded `AGENTS.md` already does), and wire it into CI — a
38
+ green check means the frontend and backend can't have silently diverged.
39
+
40
+ For hand-rolled own-API `fetch()` calls, `nifra check` stays conservative: simple string-literal calls
41
+ that match a statically visible Nifra route get an exact typed-client rewrite diff; dynamic URLs, custom
42
+ headers, bodies, query strings, or ambiguous routes fall back to manual steps.
43
+
44
+ ## For AI coding agents
45
+
46
+ **`nifra context`** prints this project's actual surface — API routes (from `backend.routes()`), page
47
+ routes (from `routes/`), and the framework conventions — as Markdown. Pipe it into a prompt:
48
+
49
+ ```sh
50
+ nifra context | pbcopy # or: nifra context > .agent-context.md
51
+ ```
52
+
53
+ **`nifra mcp`** runs a [Model Context Protocol](https://modelcontextprotocol.io) server over stdio, so
54
+ an agent can act on the project, not just read about it. Core tools:
55
+
56
+ - **`nifra_context`** — the same project surface as above.
57
+ - **`nifra_routes`** / **`nifra_openapi`** — structured API route contracts and an OpenAPI 3.1 document.
58
+ - **`nifra_docs`** / **`nifra_example`** — token-efficient docs slices and verified code snippets.
59
+ - **`nifra_scaffold`** — map a URL to the correct `routes/` file; optionally write safe JSX stubs.
60
+ - **`nifra_run`** — run HTTP requests through this project's backend and get structured results
61
+ (status, headers, parsed body, and any thrown error). The backend is re-loaded in a fresh process
62
+ each call by default, so it reflects the agent's latest edits — the write → run → see-the-failure
63
+ → fix loop. Pass `warm:true` to reuse a hot worker while source files are unchanged.
64
+ - **`nifra_render`** — SSR a page route and return rendered HTML for quick page verification.
65
+ - **`nifra_ws`** — verify a WebSocket route with a real Bun WebSocket round-trip and structured output.
66
+ - **`nifra_test`** — run bounded `bun test` with structured output.
67
+ - **`nifra_check`** — run the drift gate and get the structured `{ ok, typecheck, diagnostics[] }`
68
+ result with suggestions, so the agent verifies its own work and fixes each diagnostic before finishing.
69
+ - **`nifra_doctor`** — catch imported packages missing from `package.json`; with `autoFix:true`, write
70
+ safe dependency entries when a version can be inferred locally and return exact `bun add` commands
71
+ for anything that needs a package-manager decision.
72
+
73
+ The MCP server also exposes compact resources (`nifra://routes`, `nifra://openapi`, `nifra://package-json`,
74
+ `nifra://agents-md`) and prompt templates for common tasks.
75
+
76
+ For long-running stdio tool calls, nifra follows MCP's standard `_meta.progressToken` progress
77
+ notifications and `notifications/cancelled` request cancellation. `nifra_run`, `nifra_render`,
78
+ `nifra_test`, and full `nifra_check` calls stop their subprocess work when cancelled.
79
+ For token-sensitive clients, `tools/list` also accepts the opt-in extension `{ "compact": true }`;
80
+ call `tools/describe` with a tool name when you need the full schema and description.
81
+
82
+ Wire it into a client. Claude Desktop / Cursor (`mcp.json`):
83
+
84
+ ```json
85
+ {
86
+ "mcpServers": {
87
+ "nifra": { "command": "nifra", "args": ["mcp"] }
88
+ }
89
+ }
90
+ ```
91
+
92
+ Claude Code:
93
+
94
+ ```sh
95
+ claude mcp add nifra -- nifra mcp
96
+ ```
97
+
98
+ Run the client from (or point it at) your project root. The protocol is hand-rolled
99
+ (newline-delimited JSON-RPC 2.0) — no SDK dependency.
@@ -0,0 +1,100 @@
1
+ /**
2
+ * `nifra check` — the agent's (and CI's) definition of done. It makes the guarantees that keep a nifra
3
+ * app drift-proof actually *fire*, instead of relying on the agent to remember them:
4
+ *
5
+ * 1. **typecheck** (`tsc --noEmit`) — the frontend↔backend contract is compiler-enforced. The typed
6
+ * client derives request + response types from the routes, so a shape mismatch is a type error.
7
+ * 2. **typed-client lint** — flags hand-rolled `fetch()` to this app's *own* API (a relative URL),
8
+ * which bypasses `client<typeof app>` so the compiler can't see the drift.
9
+ * 3. **server-only-import lint** — flags a top-level import of server-only code (a DB driver, `node:`/
10
+ * `bun:` builtins, the `./db` module) into a `routes/` page module. Those modules are bundled for
11
+ * the browser too, so the import ships server code to the client and breaks the build — the #1
12
+ * full-stack footgun. Reach server resources via `c.db` / `ctx.api`, never a top-level import.
13
+ *
14
+ * `collectCheckResult` returns a structured, machine-readable result (consumed by `--json` and the
15
+ * `nifra_check` MCP tool, so an agent acts on diagnostics instead of scraping prose). Exits non-zero if
16
+ * anything fails. Pure scanners (`scanFetchText`, `scanServerOnlyImports`) are unit-tested.
17
+ */
18
+ export interface SourceFinding {
19
+ readonly file: string;
20
+ readonly line: number;
21
+ readonly snippet: string;
22
+ }
23
+ /** @deprecated kept for back-compat with existing tests; prefer {@link SourceFinding}. */
24
+ export type FetchFinding = SourceFinding;
25
+ export interface StaticRouteFinding extends SourceFinding {
26
+ readonly method: string;
27
+ readonly path: string;
28
+ }
29
+ /**
30
+ * Blank, with spaces (newlines preserved, so every byte offset — and line number — is unchanged):
31
+ * - `//` line comments and block comments;
32
+ * - the CONTENTS of backtick template literals — code-as-text (doc `CodeBlock` examples, code
33
+ * generators), never a real statement to lint.
34
+ * Single/double-quoted strings are KEPT (a real import/Response specifier lives in one). A small
35
+ * char-state machine, not a full lexer: it doesn't model regex literals, so a regex containing a quote
36
+ * could mis-skip — in practice the constructs these scanners look for sit before any such regex.
37
+ * Shared by the source scanners here and by `nifra doctor` ({@link ./doctor.ts}).
38
+ */
39
+ export declare function stripComments(src: string): string;
40
+ /** Scan one file's text for hand-rolled own-API `fetch()` calls. Pure + line-accurate. */
41
+ export declare function scanFetchText(file: string, content: string): SourceFinding[];
42
+ /** Statically collect simple Nifra route registrations from source, without importing app code. */
43
+ export declare function scanStaticRouteText(file: string, content: string): StaticRouteFinding[];
44
+ /** Scan one file's text for untyped `client("…")` calls. Pure + line-accurate. */
45
+ export declare function scanUntypedClient(file: string, content: string): SourceFinding[];
46
+ /** Scan a route module for top-level server-only imports. Returns `[]` for non-route files (only
47
+ * `routes/` modules are browser-bundled, so a server-only import elsewhere is fine). Pure. */
48
+ export declare function scanServerOnlyImports(file: string, content: string): SourceFinding[];
49
+ /** Scan a backend module (one that calls `server(`) for handlers returning a raw `Response`, which collapses
50
+ * the typed client's `data` to `never`. Pure + line-accurate; returns `[]` for files with no `server(` call. */
51
+ export declare function scanResponseRoutes(file: string, content: string): SourceFinding[];
52
+ /** Walk the project's `.ts`/`.tsx` source (skipping deps/build/tests), calling `visit` per file.
53
+ * Exported so `nifra doctor` ({@link ./doctor.ts}) scans the same source surface as `nifra check`. */
54
+ export declare function walkSource(cwd: string, visit: (rel: string, content: string) => void): Promise<void>;
55
+ /** Collect own-API `fetch()` findings across the project (kept for back-compat + reuse). */
56
+ export declare function scanProject(cwd: string): Promise<SourceFinding[]>;
57
+ /** A single machine-readable check failure — the unit an agent (or CI) acts on. */
58
+ export interface CheckDiagnostic {
59
+ readonly rule: "typecheck" | "typed-client" | "untyped-client" | "server-only-import" | "response-route" | "undeclared-dependency";
60
+ /** `error` fails the gate (a real contract break); `warning` is advisory — surfaced to the agent but
61
+ * does NOT fail `nifra check`, for patterns that are sometimes intentional (a route returning a raw
62
+ * `Response`, which silently drops the typed client to `data: never` but is valid for files/redirects). */
63
+ readonly severity: "error" | "warning";
64
+ readonly file?: string;
65
+ readonly line?: number;
66
+ readonly message: string;
67
+ /** The canonical, rule-level fix — clean of the per-occurrence snippet, so an agent can apply it
68
+ * directly. Set for the lint rules (they have one correct fix); omitted for `typecheck` (the fix is
69
+ * specific to each type error). */
70
+ readonly fix?: string;
71
+ /** A richer, agent-oriented fix hint. Diffs are only emitted when the edit is mechanical and local;
72
+ * ambiguous cases give concrete steps instead of pretending the checker can safely rewrite code. */
73
+ readonly suggestion?: CheckSuggestion;
74
+ }
75
+ export interface CheckSuggestion {
76
+ readonly kind: "edit" | "command" | "manual";
77
+ readonly title: string;
78
+ readonly diff?: string;
79
+ /** argv array, not a shell string, so MCP clients can run it without quoting hazards. */
80
+ readonly command?: readonly string[];
81
+ readonly steps?: readonly string[];
82
+ }
83
+ /** The structured result of a full check — what `--json` prints and the `nifra_check` MCP tool returns. */
84
+ export interface CheckResult {
85
+ readonly ok: boolean;
86
+ readonly typecheck: "pass" | "fail" | "skipped";
87
+ readonly diagnostics: readonly CheckDiagnostic[];
88
+ }
89
+ /** Run the three checks and assemble a structured, machine-readable result. The single source the CLI
90
+ * report, `--json`, and the MCP tool all render from. */
91
+ export declare function collectCheckResult(cwd: string, opts?: {
92
+ readonly lintsOnly?: boolean;
93
+ readonly signal?: AbortSignal;
94
+ }): Promise<CheckResult>;
95
+ /** Run the full check; print a report (`--json` for machine output) and return whether it passed. */
96
+ export declare function runCheck(cwd: string, opts?: {
97
+ readonly json?: boolean;
98
+ readonly lintsOnly?: boolean;
99
+ }): Promise<boolean>;
100
+ //# sourceMappingURL=check.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../src/check.ts"],"names":[],"mappings":"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"}