@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/dist/doctor.js ADDED
@@ -0,0 +1,291 @@
1
+ /**
2
+ * `nifra doctor` — catches the Bun-workspace footgun the typed-client lint can't: a package that's
3
+ * IMPORTED in source but NOT declared in `package.json`. Bun resolves it at runtime (via hoisting or a
4
+ * workspace), so tests pass and `bun install` reports "no changes" — false confidence — yet `tsc` fails
5
+ * and a fresh or standalone install can't resolve it. doctor diffs every bare import specifier against
6
+ * the package's declared dependencies and flags the gap, with a stable `--json` shape for agents/CI.
7
+ *
8
+ * Scope is intentionally per-package: it checks the `package.json` at `cwd`, because a dependency must be
9
+ * declared by the package that imports it (for `tsc` and for that package to install on its own) even
10
+ * when a monorepo would hoist it. Relative paths, runtime builtins (node core, `node:`/`bun:`, `bun`),
11
+ * the package's own name, and tsconfig `paths` aliases are excluded — none of them are npm deps.
12
+ */
13
+ import { builtinModules } from "node:module";
14
+ import { dirname, join } from "node:path";
15
+ import { stripComments, walkSource } from "./check.js";
16
+ // Runtime-provided modules that are never an npm dependency: Node core (bare + `node:` form) and Bun's
17
+ // own `bun` module. `node:`/`bun:`-prefixed specifiers are filtered in packageOf by prefix.
18
+ const BUILTINS = new Set([
19
+ ...builtinModules,
20
+ ...builtinModules.map((m) => `node:${m}`),
21
+ "bun",
22
+ ]);
23
+ // The four specifier-bearing forms: static import/re-export with a source, side-effect import, dynamic
24
+ // import, and CJS require. Anchored with `(?<![.\w$])` so `myimport`/`.import`/`foorequire` never match.
25
+ // Comments are stripped before these run (see stripComments) — else a doc-comment usage example would be
26
+ // flagged as a real import.
27
+ const IMPORT_PATTERNS = [
28
+ /(?<![.\w$])(?:import|export)\b[^'"]*?\bfrom\s*['"]([^'"]+)['"]/g,
29
+ /(?<![.\w$])import\s+['"]([^'"]+)['"]/g,
30
+ /(?<![.\w$])import\s*\(\s*['"]([^'"]+)['"]/g,
31
+ /(?<![.\w$])require\s*\(\s*['"]([^'"]+)['"]/g,
32
+ ];
33
+ const NPM_PACKAGE_NAME = /^(?:@[A-Za-z0-9._-]+\/)?[A-Za-z0-9._-]+$/;
34
+ const DEPENDENCY_FIELDS = [
35
+ "dependencies",
36
+ "devDependencies",
37
+ "peerDependencies",
38
+ "optionalDependencies",
39
+ ];
40
+ const isNpmPackageName = (name) => NPM_PACKAGE_NAME.test(name) &&
41
+ name.split("/").every((part) => part !== "" && part !== "." && part !== "..");
42
+ /**
43
+ * Resolve an import specifier to the npm package name it would install as, or `undefined` when it isn't
44
+ * an npm dependency at all (a relative/absolute path, a runtime builtin, or a malformed scope like the
45
+ * `@/…` path-alias convention). `@scope/name/sub` → `@scope/name`; `name/sub` → `name`.
46
+ */
47
+ export function packageOf(spec) {
48
+ if (spec === "" || spec.startsWith(".") || spec.startsWith("/"))
49
+ return undefined;
50
+ if (spec.startsWith("node:") || spec.startsWith("bun:"))
51
+ return undefined;
52
+ if (spec.startsWith("@")) {
53
+ const [scope, name] = spec.split("/");
54
+ if (!scope || scope === "@" || !name)
55
+ return undefined; // `@/alias`, `@foo` — not a real package
56
+ const pkg = `${scope}/${name}`;
57
+ return isNpmPackageName(pkg) ? pkg : undefined;
58
+ }
59
+ const name = spec.split("/")[0];
60
+ if (!isNpmPackageName(name))
61
+ return undefined;
62
+ return BUILTINS.has(name) ? undefined : name;
63
+ }
64
+ /** Build a predicate matching tsconfig `paths` aliases (e.g. `@/*`, `~/utils`), which resolve to local
65
+ * source, not npm packages — so doctor must not flag them. */
66
+ export function aliasMatcher(paths) {
67
+ const prefixes = Object.keys(paths ?? {})
68
+ .map((k) => k.replace(/\/?\*$/, ""))
69
+ .filter((p) => p !== "");
70
+ return (spec) => prefixes.some((p) => spec === p || spec.startsWith(`${p}/`));
71
+ }
72
+ /**
73
+ * Scan one file for bare imports whose resolved package is neither `declared` nor a path `alias`. Pure +
74
+ * line-accurate. Deduped per (package, line): the `snippet` carries the undeclared package name.
75
+ */
76
+ export function scanUndeclaredImports(file, content, declared, isAlias) {
77
+ const out = [];
78
+ const seen = new Set();
79
+ const code = stripComments(content); // so doc-comment usage examples aren't read as real imports
80
+ for (const rx of IMPORT_PATTERNS) {
81
+ rx.lastIndex = 0;
82
+ for (let m = rx.exec(code); m !== null; m = rx.exec(code)) {
83
+ const spec = m[1] ?? "";
84
+ if (isAlias(spec))
85
+ continue;
86
+ const pkg = packageOf(spec);
87
+ if (pkg === undefined || declared.has(pkg))
88
+ continue;
89
+ const line = content.slice(0, m.index).split("\n").length;
90
+ const key = `${pkg}@${line}`;
91
+ if (seen.has(key))
92
+ continue;
93
+ seen.add(key);
94
+ out.push({ file, line, snippet: pkg });
95
+ }
96
+ }
97
+ return out.sort((a, b) => a.line - b.line || a.snippet.localeCompare(b.snippet));
98
+ }
99
+ /** Read + parse a JSON file, or `undefined` if it's missing/unparseable (doctor degrades, never throws). */
100
+ async function readJson(path) {
101
+ try {
102
+ const text = await Bun.file(path).text();
103
+ const parsed = JSON.parse(text);
104
+ return typeof parsed === "object" && parsed !== null
105
+ ? parsed
106
+ : undefined;
107
+ }
108
+ catch {
109
+ return undefined;
110
+ }
111
+ }
112
+ const depNames = (pkg, field) => {
113
+ const deps = pkg[field];
114
+ return typeof deps === "object" && deps !== null
115
+ ? Object.keys(deps)
116
+ : [];
117
+ };
118
+ const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
119
+ function depRecord(pkg, field) {
120
+ const deps = pkg[field];
121
+ return isRecord(deps) ? deps : undefined;
122
+ }
123
+ function dependencySpec(pkg, name) {
124
+ for (const field of DEPENDENCY_FIELDS) {
125
+ const spec = depRecord(pkg, field)?.[name];
126
+ if (typeof spec === "string" && spec.length > 0)
127
+ return spec;
128
+ }
129
+ return undefined;
130
+ }
131
+ async function ancestorDependencySpec(cwd, name) {
132
+ for (let dir = dirname(cwd);; dir = dirname(dir)) {
133
+ const pkg = await readJson(join(dir, "package.json"));
134
+ if (pkg !== undefined) {
135
+ const spec = dependencySpec(pkg, name);
136
+ if (spec !== undefined)
137
+ return spec;
138
+ }
139
+ const parent = dirname(dir);
140
+ if (parent === dir)
141
+ return undefined;
142
+ }
143
+ }
144
+ async function installedPackageSpec(cwd, name) {
145
+ if (!isNpmPackageName(name))
146
+ return undefined;
147
+ const parts = name.split("/");
148
+ for (let dir = cwd;; dir = dirname(dir)) {
149
+ const meta = await readJson(join(dir, "node_modules", ...parts, "package.json"));
150
+ if (typeof meta?.version === "string" && meta.version.length > 0) {
151
+ return `^${meta.version}`;
152
+ }
153
+ const parent = dirname(dir);
154
+ if (parent === dir)
155
+ return undefined;
156
+ }
157
+ }
158
+ async function inferDependencyFix(cwd, name) {
159
+ const ancestorSpec = await ancestorDependencySpec(cwd, name);
160
+ if (ancestorSpec !== undefined) {
161
+ return { version: ancestorSpec, source: "ancestor-package-json" };
162
+ }
163
+ const installedSpec = await installedPackageSpec(cwd, name);
164
+ return installedSpec === undefined
165
+ ? undefined
166
+ : { version: installedSpec, source: "installed-package-json" };
167
+ }
168
+ /** Run doctor against the project at `cwd`: diff source imports vs declared deps. */
169
+ export async function collectDoctorResult(cwd) {
170
+ const pkg = await readJson(join(cwd, "package.json"));
171
+ if (pkg === undefined)
172
+ return { ok: true, ran: false, findings: [] };
173
+ const declared = new Set();
174
+ if (typeof pkg.name === "string")
175
+ declared.add(pkg.name); // a package may import its own name (exports map)
176
+ for (const field of DEPENDENCY_FIELDS) {
177
+ for (const name of depNames(pkg, field))
178
+ declared.add(name);
179
+ }
180
+ const tsconfig = await readJson(join(cwd, "tsconfig.json"));
181
+ const compilerOptions = tsconfig?.compilerOptions;
182
+ const isAlias = aliasMatcher(compilerOptions?.paths);
183
+ const findings = [];
184
+ await walkSource(cwd, (rel, content) => {
185
+ for (const f of scanUndeclaredImports(rel, content, declared, isAlias)) {
186
+ findings.push({ file: f.file, line: f.line, package: f.snippet });
187
+ }
188
+ });
189
+ findings.sort((a, b) => a.file.localeCompare(b.file) || a.line - b.line);
190
+ return { ok: findings.length === 0, ran: true, findings };
191
+ }
192
+ /** Safely add undeclared imports to package.json when the version can be inferred without network I/O. */
193
+ export async function applyDoctorAutoFix(cwd) {
194
+ const before = await collectDoctorResult(cwd);
195
+ if (!before.ran || before.findings.length === 0)
196
+ return before;
197
+ const pkgPath = join(cwd, "package.json");
198
+ const pkg = await readJson(pkgPath);
199
+ if (pkg === undefined)
200
+ return before;
201
+ const dependencies = pkg.dependencies;
202
+ if (dependencies !== undefined && !isRecord(dependencies)) {
203
+ const skippedFixes = [...new Set(before.findings.map((f) => f.package))].sort().map((name) => ({
204
+ package: name,
205
+ reason: "`dependencies` exists but is not an object; refusing to rewrite it automatically",
206
+ command: ["bun", "add", name],
207
+ }));
208
+ return { ...before, skippedFixes };
209
+ }
210
+ const deps = (dependencies ?? {});
211
+ if (dependencies === undefined)
212
+ pkg.dependencies = deps;
213
+ const fixed = [];
214
+ const skippedFixes = [];
215
+ for (const name of [...new Set(before.findings.map((f) => f.package))].sort()) {
216
+ if (!isNpmPackageName(name)) {
217
+ skippedFixes.push({
218
+ package: name,
219
+ reason: "package name did not match npm package-name syntax",
220
+ command: ["bun", "add", name],
221
+ });
222
+ continue;
223
+ }
224
+ const inferred = await inferDependencyFix(cwd, name);
225
+ if (inferred === undefined) {
226
+ skippedFixes.push({
227
+ package: name,
228
+ reason: "no declared ancestor version or installed package metadata was found locally",
229
+ command: ["bun", "add", name],
230
+ });
231
+ continue;
232
+ }
233
+ deps[name] = inferred.version;
234
+ fixed.push({ package: name, field: "dependencies", ...inferred });
235
+ }
236
+ if (fixed.length > 0)
237
+ await Bun.write(pkgPath, `${JSON.stringify(pkg, null, 2)}\n`);
238
+ const after = fixed.length > 0 ? await collectDoctorResult(cwd) : before;
239
+ return {
240
+ ...after,
241
+ ...(fixed.length > 0 ? { fixed } : {}),
242
+ ...(skippedFixes.length > 0 ? { skippedFixes } : {}),
243
+ };
244
+ }
245
+ /** Run doctor; print a report (`--json` for machine output) and return whether it passed. */
246
+ export async function runDoctor(cwd, opts = {}) {
247
+ const result = opts.autoFix ? await applyDoctorAutoFix(cwd) : await collectDoctorResult(cwd);
248
+ if (opts.json) {
249
+ console.log(JSON.stringify(result, null, 2));
250
+ return result.ok;
251
+ }
252
+ console.log("nifra doctor\n");
253
+ if (!result.ran) {
254
+ console.log("• no package.json at this directory — nothing to check");
255
+ return true;
256
+ }
257
+ if (result.fixed && result.fixed.length > 0) {
258
+ console.log("✓ updated package.json dependencies:");
259
+ for (const f of result.fixed) {
260
+ console.log(` ${f.package}@${f.version} (${f.source})`);
261
+ }
262
+ console.log("");
263
+ }
264
+ if (result.skippedFixes && result.skippedFixes.length > 0) {
265
+ console.log("• not auto-fixed:");
266
+ for (const f of result.skippedFixes) {
267
+ console.log(` ${f.package} — ${f.reason}; run \`${f.command.join(" ")}\``);
268
+ }
269
+ console.log("");
270
+ }
271
+ if (result.ok) {
272
+ console.log("✓ every imported package is declared in package.json");
273
+ return true;
274
+ }
275
+ // Group by package so the fix ("add X to dependencies") is stated once with its import sites.
276
+ const byPkg = new Map();
277
+ for (const f of result.findings) {
278
+ const list = byPkg.get(f.package) ?? [];
279
+ list.push(f);
280
+ byPkg.set(f.package, list);
281
+ }
282
+ console.log(`✗ ${byPkg.size} package(s) imported but not declared in package.json:\n`);
283
+ for (const [pkg, sites] of [...byPkg.entries()].sort()) {
284
+ console.log(` ${pkg} — add to dependencies (\`bun add ${pkg}\`)`);
285
+ for (const s of sites)
286
+ console.log(` ${s.file}:${s.line}`);
287
+ }
288
+ console.log("\nThese resolve at Bun runtime via hoisting/workspace but break `tsc` and a standalone install.");
289
+ return false;
290
+ }
291
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * `nifra_example` — verified, copy-pasteable code examples for agents. The corpus is `examples.json`
3
+ * (written into this package by `bun run gen:llms`): the same doc snippets `check:docs` typechecks
4
+ * against the live `@nifrajs/*` API. So every example this returns is GUARANTEED to compile against the
5
+ * installed version — the antidote to an agent hallucinating a framework API from stale training.
6
+ *
7
+ * Keyword-scored over each example's name/topic/slug (curated identifiers, heavily weighted) and its
8
+ * code body. No query → a grouped index of what's available (the cheap discovery call).
9
+ */
10
+ export interface Example {
11
+ readonly name: string;
12
+ /** The doc page's title, e.g. "Nifra — Auth & sessions". */
13
+ readonly topic: string;
14
+ /** The doc page slug, e.g. "auth" — a short, matchable tag. */
15
+ readonly slug: string;
16
+ readonly code: string;
17
+ }
18
+ export interface ScoredExample extends Example {
19
+ readonly score: number;
20
+ }
21
+ /** Score examples against the query: a term in the slug/topic/name (the curated, searchable labels)
22
+ * is worth far more than a mention in the code body; body hits cap per term so one long snippet can't
23
+ * outweigh a precisely-tagged one. */
24
+ export declare function searchExamples(examples: readonly Example[], query: string, limit: number): ScoredExample[];
25
+ /** Render the tool result: matched examples as fenced code blocks, or the grouped index when no query. */
26
+ export declare function renderExamplesResult(examples: readonly Example[], query: string | undefined, limit: number): string;
27
+ /** Load the bundled example corpus. Resolves relative to this module so it works from `src/` (repo dev)
28
+ * and `dist/` (published) alike — `docs/examples.json` sits at the package root next to both. */
29
+ export declare function loadExamplesCorpus(): Promise<Example[] | undefined>;
30
+ //# sourceMappingURL=examples.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"examples.d.ts","sourceRoot":"","sources":["../src/examples.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,4DAA4D;IAC5D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,+DAA+D;IAC/D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CACtB;AAED,MAAM,WAAW,aAAc,SAAQ,OAAO;IAC5C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB;AAED;;sCAEsC;AACtC,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,SAAS,OAAO,EAAE,EAC5B,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,GACZ,aAAa,EAAE,CAejB;AAED,0GAA0G;AAC1G,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,SAAS,OAAO,EAAE,EAC5B,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,KAAK,EAAE,MAAM,GACZ,MAAM,CAoBR;AAED;iGACiG;AACjG,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,OAAO,EAAE,GAAG,SAAS,CAAC,CAUzE"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * `nifra_example` — verified, copy-pasteable code examples for agents. The corpus is `examples.json`
3
+ * (written into this package by `bun run gen:llms`): the same doc snippets `check:docs` typechecks
4
+ * against the live `@nifrajs/*` API. So every example this returns is GUARANTEED to compile against the
5
+ * installed version — the antidote to an agent hallucinating a framework API from stale training.
6
+ *
7
+ * Keyword-scored over each example's name/topic/slug (curated identifiers, heavily weighted) and its
8
+ * code body. No query → a grouped index of what's available (the cheap discovery call).
9
+ */
10
+ import { countBodyHits, queryTermGroups, tokenize, tokenSetHas } from "./search-terms.js";
11
+ /** Score examples against the query: a term in the slug/topic/name (the curated, searchable labels)
12
+ * is worth far more than a mention in the code body; body hits cap per term so one long snippet can't
13
+ * outweigh a precisely-tagged one. */
14
+ export function searchExamples(examples, query, limit) {
15
+ const terms = queryTermGroups(query);
16
+ if (terms.length === 0)
17
+ return [];
18
+ const scored = [];
19
+ for (const ex of examples) {
20
+ const labelTokens = new Set([...tokenize(ex.slug), ...tokenize(ex.topic), ...tokenize(ex.name)]);
21
+ const codeLower = ex.code.toLowerCase();
22
+ let score = 0;
23
+ for (const term of terms) {
24
+ if (tokenSetHas(labelTokens, term))
25
+ score += 8;
26
+ score += countBodyHits(codeLower, term, 5);
27
+ }
28
+ if (score > 0)
29
+ scored.push({ ...ex, score });
30
+ }
31
+ return scored.sort((a, b) => b.score - a.score).slice(0, limit);
32
+ }
33
+ /** Render the tool result: matched examples as fenced code blocks, or the grouped index when no query. */
34
+ export function renderExamplesResult(examples, query, limit) {
35
+ if (query === undefined || query.trim() === "") {
36
+ const byTopic = new Map();
37
+ for (const ex of examples) {
38
+ const list = byTopic.get(ex.topic) ?? [];
39
+ list.push(ex.name);
40
+ byTopic.set(ex.topic, list);
41
+ }
42
+ const index = [...byTopic.entries()]
43
+ .map(([topic, names]) => `- **${topic}**: ${names.join(", ")}`)
44
+ .join("\n");
45
+ return `# nifra examples — index (${examples.length} verified snippets; pass \`query\` to fetch code)\n\nEvery snippet is typechecked against the installed nifra version — prefer these over recalling an API.\n\n${index}`;
46
+ }
47
+ const matches = searchExamples(examples, query, limit);
48
+ if (matches.length === 0) {
49
+ return `No examples matched ${JSON.stringify(query)}. Call without a query for the index, or try a broader term (e.g. "auth", "upload", "isr", "client").`;
50
+ }
51
+ return matches
52
+ .map((m) => `## ${m.name} — ${m.topic}\n\n\`\`\`ts\n${m.code}\n\`\`\``)
53
+ .join("\n\n---\n\n");
54
+ }
55
+ /** Load the bundled example corpus. Resolves relative to this module so it works from `src/` (repo dev)
56
+ * and `dist/` (published) alike — `docs/examples.json` sits at the package root next to both. */
57
+ export async function loadExamplesCorpus() {
58
+ const url = new URL("../docs/examples.json", import.meta.url);
59
+ try {
60
+ const text = await Bun.file(url).text();
61
+ if (text.length === 0)
62
+ return undefined;
63
+ const parsed = JSON.parse(text);
64
+ return Array.isArray(parsed) && parsed.length > 0 ? parsed : undefined;
65
+ }
66
+ catch {
67
+ return undefined;
68
+ }
69
+ }
70
+ //# sourceMappingURL=examples.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"examples.js","sourceRoot":"","sources":["../src/examples.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Introspect a loaded nifra project into a Markdown brief — the API routes (`backend.routes()`), the
3
+ * page routes (`discoverRoutes`), and a conventions summary — for piping into an AI coding agent's
4
+ * prompt. Used by `nifra context` (stdout) and the `nifra mcp` server (a tool result), so an agent sees
5
+ * *this* project's actual surface, not just generic docs.
6
+ */
7
+ import type { Manifest } from "@nifrajs/web";
8
+ import type { LoadedApp } from "./load.js";
9
+ /** Structural view of a `@nifrajs/core` route descriptor — declared locally so the CLI needs no type
10
+ * dependency on core. `app.routes()` returns these. */
11
+ interface RouteDesc {
12
+ readonly method: string;
13
+ readonly path: string;
14
+ readonly schema?: unknown;
15
+ }
16
+ /**
17
+ * Render a JSON Schema as a compact TypeScript-like type (`{ id: string, name?: string }`) — the
18
+ * shape agents already think in, at a fraction of the raw JSON Schema's tokens (~70-80% smaller).
19
+ * Anything the renderer doesn't model falls back to the raw JSON for that subtree, so the output
20
+ * is always faithful, just not always minimal.
21
+ */
22
+ export declare function tsTypeOf(schema: unknown, depth?: number): string;
23
+ /**
24
+ * The typed-client call form for a route — the exact `client<typeof app>` proxy chain an agent should
25
+ * write, derived from the same convention `@nifrajs/client` implements (so it never has to read the
26
+ * client tests to learn it): a static segment is a property (`.users`), a path param/wildcard is a call
27
+ * that appends the value (`({ id })`), the root path is `.index`, and the HTTP verb is the terminal call.
28
+ * Body verbs (POST/PUT/PATCH) take the body first then call-options; other verbs take call-options first —
29
+ * so the `{ query }` argument lands in the right slot for each.
30
+ */
31
+ export declare function clientCall(method: string, path: string, schema: unknown): string;
32
+ /** Markdown section listing the backend's API routes with their request + response field shapes. */
33
+ export declare function apiRoutesSection(routes: readonly RouteDesc[]): string;
34
+ /** Markdown section listing the file-routed pages (URL pattern → source file). */
35
+ export declare function pageRoutesSection(manifest: Manifest | undefined): string;
36
+ /** Optional narrowing for {@link describeProject} — a path prefix and/or one section. A filtered
37
+ * brief omits the conventions block (the agent already has it from its first full call), so
38
+ * follow-up calls cost a fraction of the tokens. */
39
+ export interface ContextFilter {
40
+ readonly path?: string;
41
+ readonly kind?: "api" | "pages";
42
+ }
43
+ /** Build the project brief (API routes + page routes + conventions) as Markdown — optionally
44
+ * narrowed by {@link ContextFilter} for cheap follow-up calls. */
45
+ export declare function describeProject(app: LoadedApp, filter?: ContextFilter): string;
46
+ /** One API route as structured JSON: method, path, the exact typed-client call form, and compact
47
+ * TS-shaped request/response contracts (present only when the route declares the schema). */
48
+ export interface RouteJson {
49
+ readonly method: string;
50
+ readonly path: string;
51
+ readonly call: string;
52
+ readonly body?: string;
53
+ readonly query?: string;
54
+ readonly response?: string;
55
+ }
56
+ /**
57
+ * The backend's API routes as structured JSON — what the `nifra_routes` MCP tool returns, so an agent
58
+ * consumes the contract programmatically (`list_routes` / `get_route_schema`) instead of parsing the
59
+ * Markdown brief. Optionally filtered to routes whose path starts with `pathPrefix`. Reuses the exact
60
+ * same `call` form and TS-shaped contracts the Markdown brief shows.
61
+ */
62
+ export declare function routesToJson(app: LoadedApp, pathPrefix?: string): RouteJson[];
63
+ export {};
64
+ //# sourceMappingURL=introspect.d.ts.map
@@ -0,0 +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;AAoCD;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,SAAI,GAAG,MAAM,CAsC3D;AAuBD;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,MAAM,CAwBhF;AAED,oGAAoG;AACpG,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,GAAG,MAAM,CAYrE;AAED,kFAAkF;AAClF,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,GAAG,SAAS,GAAG,MAAM,CAQxE;AAmBD;;oDAEoD;AACpD,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,GAAG,OAAO,CAAA;CAChC;AAED;kEACkE;AAClE,wBAAgB,eAAe,CAAC,GAAG,EAAE,SAAS,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,MAAM,CA8B9E;AAED;6FAC6F;AAC7F,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAC3B;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,SAAS,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,EAAE,CA2B7E"}