@nifrajs/cli 2.11.0 → 2.12.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.
- package/README.md +6 -0
- package/dist/assure-hydration.d.ts +14 -0
- package/dist/assure-hydration.d.ts.map +1 -0
- package/dist/assure-hydration.js +483 -0
- package/dist/assure-hydration.js.map +1 -0
- package/dist/assure.d.ts +35 -0
- package/dist/assure.d.ts.map +1 -1
- package/dist/assure.js +222 -1
- package/dist/assure.js.map +1 -1
- package/dist/capabilities-tool.d.ts +13 -0
- package/dist/capabilities-tool.d.ts.map +1 -1
- package/dist/capabilities-tool.js +64 -1
- package/dist/capabilities-tool.js.map +1 -1
- package/dist/check.d.ts +125 -10
- package/dist/check.d.ts.map +1 -1
- package/dist/check.js +706 -145
- package/dist/check.js.map +1 -1
- package/dist/cli.d.ts +23 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +194 -10
- package/dist/cli.js.map +1 -1
- package/dist/contract-proof.d.ts +49 -0
- package/dist/contract-proof.d.ts.map +1 -0
- package/dist/contract-proof.js +128 -0
- package/dist/contract-proof.js.map +1 -0
- package/dist/contracts.d.ts +22 -0
- package/dist/contracts.d.ts.map +1 -0
- package/dist/contracts.js +134 -0
- package/dist/contracts.js.map +1 -0
- package/dist/diagnostics.d.ts +23 -0
- package/dist/diagnostics.d.ts.map +1 -0
- package/dist/diagnostics.js +9 -0
- package/dist/diagnostics.js.map +1 -0
- package/dist/diff-tool.d.ts +2 -0
- package/dist/diff-tool.d.ts.map +1 -1
- package/dist/diff-tool.js +1 -1
- package/dist/diff-tool.js.map +1 -1
- package/dist/docs-search.d.ts +8 -3
- package/dist/docs-search.d.ts.map +1 -1
- package/dist/docs-search.js +36 -15
- package/dist/docs-search.js.map +1 -1
- package/dist/doctor.d.ts +28 -2
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +173 -7
- package/dist/doctor.js.map +1 -1
- package/dist/examples.d.ts +1 -2
- package/dist/examples.d.ts.map +1 -1
- package/dist/examples.js +37 -16
- package/dist/examples.js.map +1 -1
- package/dist/fix-recipes.d.ts +12 -0
- package/dist/fix-recipes.d.ts.map +1 -0
- package/dist/fix-recipes.js +106 -0
- package/dist/fix-recipes.js.map +1 -0
- package/dist/init-agents.d.ts.map +1 -1
- package/dist/init-agents.js +60 -4
- package/dist/init-agents.js.map +1 -1
- package/dist/internal/source-facts.d.ts +15 -0
- package/dist/internal/source-facts.d.ts.map +1 -0
- package/dist/internal/source-facts.js +82 -0
- package/dist/internal/source-facts.js.map +1 -0
- package/dist/internal/typescript-import.d.ts +9 -0
- package/dist/internal/typescript-import.d.ts.map +1 -1
- package/dist/internal/typescript-import.js +38 -0
- package/dist/internal/typescript-import.js.map +1 -1
- package/dist/introspect.d.ts +6 -2
- package/dist/introspect.d.ts.map +1 -1
- package/dist/introspect.js +53 -4
- package/dist/introspect.js.map +1 -1
- package/dist/load.d.ts +6 -0
- package/dist/load.d.ts.map +1 -1
- package/dist/load.js.map +1 -1
- package/dist/manifest-tool.d.ts.map +1 -1
- package/dist/manifest-tool.js +14 -9
- package/dist/manifest-tool.js.map +1 -1
- package/dist/mcp-docs-tools.d.ts.map +1 -1
- package/dist/mcp-docs-tools.js +3 -0
- package/dist/mcp-docs-tools.js.map +1 -1
- package/dist/mcp-http.js +1 -1
- package/dist/mcp-root.d.ts +83 -0
- package/dist/mcp-root.d.ts.map +1 -0
- package/dist/mcp-root.js +221 -0
- package/dist/mcp-root.js.map +1 -0
- package/dist/mcp-run.d.ts.map +1 -1
- package/dist/mcp-run.js +18 -4
- package/dist/mcp-run.js.map +1 -1
- package/dist/mcp.d.ts +27 -4
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +358 -25
- package/dist/mcp.js.map +1 -1
- package/dist/project-path.d.ts +3 -0
- package/dist/project-path.d.ts.map +1 -0
- package/dist/project-path.js +36 -0
- package/dist/project-path.js.map +1 -0
- package/dist/replay.d.ts +12 -0
- package/dist/replay.d.ts.map +1 -0
- package/dist/replay.js +36 -0
- package/dist/replay.js.map +1 -0
- package/dist/rules/codes.d.ts +42 -0
- package/dist/rules/codes.d.ts.map +1 -0
- package/dist/rules/codes.js +52 -0
- package/dist/rules/codes.js.map +1 -0
- package/dist/rules/comment-markers.d.ts +10 -0
- package/dist/rules/comment-markers.d.ts.map +1 -0
- package/dist/rules/comment-markers.js +24 -0
- package/dist/rules/comment-markers.js.map +1 -0
- package/dist/rules/index.d.ts +31 -0
- package/dist/rules/index.d.ts.map +1 -0
- package/dist/rules/index.js +133 -0
- package/dist/rules/index.js.map +1 -0
- package/dist/rules/legacy.d.ts +7 -0
- package/dist/rules/legacy.d.ts.map +1 -0
- package/dist/rules/legacy.js +85 -0
- package/dist/rules/legacy.js.map +1 -0
- package/dist/rules/routes.d.ts +12 -0
- package/dist/rules/routes.d.ts.map +1 -0
- package/dist/rules/routes.js +142 -0
- package/dist/rules/routes.js.map +1 -0
- package/dist/rules/security.d.ts +10 -0
- package/dist/rules/security.d.ts.map +1 -0
- package/dist/rules/security.js +471 -0
- package/dist/rules/security.js.map +1 -0
- package/dist/search-terms.d.ts +2 -0
- package/dist/search-terms.d.ts.map +1 -1
- package/dist/search-terms.js +5 -1
- package/dist/search-terms.js.map +1 -1
- package/dist/types-search.d.ts +1 -2
- package/dist/types-search.d.ts.map +1 -1
- package/dist/types-search.js +33 -16
- package/dist/types-search.js.map +1 -1
- package/dist/verification.d.ts +9 -0
- package/dist/verification.d.ts.map +1 -1
- package/dist/verification.js +17 -1
- package/dist/verification.js.map +1 -1
- package/dist/work-graph.d.ts +123 -0
- package/dist/work-graph.d.ts.map +1 -0
- package/dist/work-graph.js +465 -0
- package/dist/work-graph.js.map +1 -0
- package/docs/examples.json +32 -2
- package/docs/llms-full.txt +906 -15
- package/docs/types.json +1682 -130
- package/package.json +34 -9
- package/src/assure-hydration.ts +606 -0
- package/src/assure.ts +316 -2
- package/src/capabilities-tool.ts +80 -1
- package/src/check.ts +873 -168
- package/src/cli.ts +198 -11
- package/src/contract-proof.ts +194 -0
- package/src/contracts.ts +157 -0
- package/src/diagnostics.ts +32 -0
- package/src/diff-tool.ts +1 -1
- package/src/docs-search.ts +45 -15
- package/src/doctor.ts +259 -8
- package/src/examples.ts +43 -15
- package/src/fix-recipes.ts +126 -0
- package/src/init-agents.ts +61 -4
- package/src/internal/source-facts.ts +133 -0
- package/src/internal/typescript-import.ts +29 -0
- package/src/introspect.ts +75 -6
- package/src/load.ts +6 -0
- package/src/manifest-tool.ts +16 -10
- package/src/mcp-docs-tools.ts +3 -0
- package/src/mcp-http.ts +1 -1
- package/src/mcp-root.ts +271 -0
- package/src/mcp-run.ts +19 -4
- package/src/mcp.ts +438 -32
- package/src/project-path.ts +36 -0
- package/src/replay.ts +44 -0
- package/src/rules/codes.ts +57 -0
- package/src/rules/comment-markers.ts +26 -0
- package/src/rules/index.ts +175 -0
- package/src/rules/legacy.ts +93 -0
- package/src/rules/routes.ts +157 -0
- package/src/rules/security.ts +505 -0
- package/src/search-terms.ts +9 -4
- package/src/types-search.ts +39 -15
- package/src/verification.ts +18 -1
- package/src/work-graph.ts +613 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { existsSync, realpathSync } from "node:fs";
|
|
2
|
+
import { resolve, sep } from "node:path";
|
|
3
|
+
import { diffRouteSnapshots } from "@nifrajs/core/diff";
|
|
4
|
+
import { DEFAULT_SNAPSHOT_FILE, parseSnapshotFile, snapshotBackend } from "./diff-tool.js";
|
|
5
|
+
import { collectProjectVerification } from "./verification.js";
|
|
6
|
+
const routeKey = (method, path) => `${method.toUpperCase()}\n${path}`;
|
|
7
|
+
function safeBaselinePath(cwd, baselinePath) {
|
|
8
|
+
const root = resolve(cwd);
|
|
9
|
+
const target = resolve(root, baselinePath);
|
|
10
|
+
if (target !== root && !target.startsWith(`${root}${sep}`)) {
|
|
11
|
+
throw new Error("contract proof baseline must stay inside the project directory");
|
|
12
|
+
}
|
|
13
|
+
return target;
|
|
14
|
+
}
|
|
15
|
+
function errorMessage(error) {
|
|
16
|
+
return error instanceof Error ? error.message : String(error);
|
|
17
|
+
}
|
|
18
|
+
function changedRoutes(diff, assurance, capability) {
|
|
19
|
+
const changes = new Map();
|
|
20
|
+
for (const change of diff.changes) {
|
|
21
|
+
const key = routeKey(change.method, change.path);
|
|
22
|
+
const current = changes.get(key);
|
|
23
|
+
if (current === undefined)
|
|
24
|
+
changes.set(key, [change]);
|
|
25
|
+
else
|
|
26
|
+
current.push(change);
|
|
27
|
+
}
|
|
28
|
+
const assured = new Map((assurance?.routes ?? []).map((route) => [routeKey(route.method, route.path), route]));
|
|
29
|
+
const assuranceFindings = new Map();
|
|
30
|
+
for (const finding of assurance?.findings ?? []) {
|
|
31
|
+
const key = routeKey(finding.method, finding.path);
|
|
32
|
+
const current = assuranceFindings.get(key);
|
|
33
|
+
if (current === undefined)
|
|
34
|
+
assuranceFindings.set(key, [finding]);
|
|
35
|
+
else
|
|
36
|
+
current.push(finding);
|
|
37
|
+
}
|
|
38
|
+
const capable = new Map((capability?.routes ?? []).map((route) => [routeKey(route.method, route.path), route]));
|
|
39
|
+
const capabilityFindings = new Map();
|
|
40
|
+
for (const finding of capability?.findings ?? []) {
|
|
41
|
+
const key = routeKey(finding.method, finding.path);
|
|
42
|
+
const current = capabilityFindings.get(key);
|
|
43
|
+
if (current === undefined)
|
|
44
|
+
capabilityFindings.set(key, [finding]);
|
|
45
|
+
else
|
|
46
|
+
current.push(finding);
|
|
47
|
+
}
|
|
48
|
+
return Object.freeze([...changes].map(([key, routeChanges]) => {
|
|
49
|
+
const first = routeChanges[0];
|
|
50
|
+
if (first === undefined)
|
|
51
|
+
throw new Error("contract proof: missing route change");
|
|
52
|
+
const assuredRoute = assured.get(key);
|
|
53
|
+
const capableRoute = capable.get(key);
|
|
54
|
+
return {
|
|
55
|
+
method: first.method,
|
|
56
|
+
path: first.path,
|
|
57
|
+
changes: Object.freeze([...routeChanges]),
|
|
58
|
+
...(assurance === undefined
|
|
59
|
+
? {}
|
|
60
|
+
: {
|
|
61
|
+
assurance: {
|
|
62
|
+
...(assuredRoute === undefined ? {} : { route: assuredRoute }),
|
|
63
|
+
findings: Object.freeze([...(assuranceFindings.get(key) ?? [])]),
|
|
64
|
+
},
|
|
65
|
+
}),
|
|
66
|
+
...(capability === undefined
|
|
67
|
+
? {}
|
|
68
|
+
: {
|
|
69
|
+
capability: {
|
|
70
|
+
...(capableRoute === undefined ? {} : { route: capableRoute }),
|
|
71
|
+
findings: Object.freeze([...(capabilityFindings.get(key) ?? [])]),
|
|
72
|
+
},
|
|
73
|
+
}),
|
|
74
|
+
};
|
|
75
|
+
}));
|
|
76
|
+
}
|
|
77
|
+
/** Compose route diff, route assurance, capability evidence, and an optional check result. */
|
|
78
|
+
export async function collectContractProof(cwd, options = {}) {
|
|
79
|
+
const baselinePath = options.baselinePath ?? DEFAULT_SNAPSHOT_FILE;
|
|
80
|
+
const resolvedBaseline = safeBaselinePath(cwd, baselinePath);
|
|
81
|
+
if (!existsSync(resolvedBaseline)) {
|
|
82
|
+
throw new Error(`contract proof baseline not found: ${resolvedBaseline}`);
|
|
83
|
+
}
|
|
84
|
+
const realRoot = realpathSync(resolve(cwd));
|
|
85
|
+
const realBaseline = realpathSync(resolvedBaseline);
|
|
86
|
+
if (realBaseline !== realRoot && !realBaseline.startsWith(`${realRoot}${sep}`)) {
|
|
87
|
+
throw new Error("contract proof baseline must stay inside the project directory");
|
|
88
|
+
}
|
|
89
|
+
const baseline = parseSnapshotFile(await Bun.file(resolvedBaseline).text(), baselinePath);
|
|
90
|
+
const current = await snapshotBackend(cwd);
|
|
91
|
+
const diff = diffRouteSnapshots(baseline.routes, current);
|
|
92
|
+
const verification = await collectProjectVerification(cwd, {
|
|
93
|
+
...(options.signal === undefined ? {} : { signal: options.signal }),
|
|
94
|
+
});
|
|
95
|
+
const proof = {
|
|
96
|
+
assuranceConfigPresent: verification.assuranceConfigPresent,
|
|
97
|
+
...(verification.configError === undefined
|
|
98
|
+
? {}
|
|
99
|
+
: { configError: errorMessage(verification.configError) }),
|
|
100
|
+
...(verification.routeAssurance === undefined
|
|
101
|
+
? {}
|
|
102
|
+
: {
|
|
103
|
+
assurance: {
|
|
104
|
+
ok: verification.routeAssurance.ok,
|
|
105
|
+
routeCount: verification.routeAssurance.routes.length,
|
|
106
|
+
findings: verification.routeAssurance.findings,
|
|
107
|
+
},
|
|
108
|
+
}),
|
|
109
|
+
...(verification.capability === undefined
|
|
110
|
+
? {}
|
|
111
|
+
: {
|
|
112
|
+
capability: {
|
|
113
|
+
ok: verification.capability.report.ok,
|
|
114
|
+
routeCount: verification.capability.report.routes.length,
|
|
115
|
+
findings: verification.capability.report.findings,
|
|
116
|
+
},
|
|
117
|
+
}),
|
|
118
|
+
...(options.check === true ? { check: await verification.check() } : {}),
|
|
119
|
+
};
|
|
120
|
+
return Object.freeze({
|
|
121
|
+
baseline: baselinePath,
|
|
122
|
+
hasBreaking: diff.hasBreaking,
|
|
123
|
+
changes: diff.changes,
|
|
124
|
+
routes: changedRoutes(diff, verification.routeAssurance, verification.capability?.report),
|
|
125
|
+
verification: proof,
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=contract-proof.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract-proof.js","sourceRoot":"","sources":["../src/contract-proof.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type ReflectedRoute } from "@nifrajs/core/reflection";
|
|
2
|
+
export interface ContractDigest {
|
|
3
|
+
readonly request: string;
|
|
4
|
+
readonly response: string;
|
|
5
|
+
}
|
|
6
|
+
export interface ContractsLock {
|
|
7
|
+
readonly version: 1;
|
|
8
|
+
readonly routes: Readonly<Record<string, ContractDigest>>;
|
|
9
|
+
}
|
|
10
|
+
export declare const DEFAULT_CONTRACTS_LOCK = "contracts.lock.json";
|
|
11
|
+
export declare function digestRoute(route: ReflectedRoute): Promise<ContractDigest>;
|
|
12
|
+
export declare function buildContractsLock(source: unknown): Promise<ContractsLock>;
|
|
13
|
+
export declare function snapshotContracts(cwd: string, out?: string): Promise<ContractsLock>;
|
|
14
|
+
export declare function parseContractsLock(value: unknown): ContractsLock;
|
|
15
|
+
export declare function checkContractsLock(cwd: string, file?: string): Promise<{
|
|
16
|
+
present: boolean;
|
|
17
|
+
diagnostics: Array<{
|
|
18
|
+
route?: string;
|
|
19
|
+
message: string;
|
|
20
|
+
}>;
|
|
21
|
+
}>;
|
|
22
|
+
//# sourceMappingURL=contracts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contracts.d.ts","sourceRoot":"","sources":["../src/contracts.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,cAAc,EAAiB,MAAM,0BAA0B,CAAA;AAE7E,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAC1B;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAA;IACnB,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,CAAA;CAC1D;AAED,eAAO,MAAM,sBAAsB,wBAAwB,CAAA;AAmD3D,wBAAsB,WAAW,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC,CAIhF;AAED,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,aAAa,CAAC,CAYhF;AAYD,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,MAAM,EACX,GAAG,SAAyB,GAC3B,OAAO,CAAC,aAAa,CAAC,CAIxB;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,aAAa,CAwBhE;AAED,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,MAAM,EACX,IAAI,SAAyB,GAC5B,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,WAAW,EAAE,KAAK,CAAC;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CAAC,CAuBxF"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
|
|
2
|
+
if (typeof path === "string" && /^\.\.?\//.test(path)) {
|
|
3
|
+
return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
|
|
4
|
+
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
|
|
5
|
+
});
|
|
6
|
+
}
|
|
7
|
+
return path;
|
|
8
|
+
};
|
|
9
|
+
import { existsSync } from "node:fs";
|
|
10
|
+
import { resolve } from "node:path";
|
|
11
|
+
import { reflectRoutes } from "@nifrajs/core/reflection";
|
|
12
|
+
export const DEFAULT_CONTRACTS_LOCK = "contracts.lock.json";
|
|
13
|
+
const DIGEST = /^[a-f0-9]{64}$/;
|
|
14
|
+
function recordOf(value) {
|
|
15
|
+
return typeof value === "object" && value !== null && !Array.isArray(value)
|
|
16
|
+
? Object.fromEntries(Object.entries(value))
|
|
17
|
+
: undefined;
|
|
18
|
+
}
|
|
19
|
+
function canonical(value, key) {
|
|
20
|
+
if (["description", "title", "default", "example", "examples"].includes(key ?? ""))
|
|
21
|
+
return undefined;
|
|
22
|
+
if (Array.isArray(value))
|
|
23
|
+
return value.map((item) => canonical(item));
|
|
24
|
+
const record = recordOf(value);
|
|
25
|
+
if (record === undefined)
|
|
26
|
+
return value;
|
|
27
|
+
const out = {};
|
|
28
|
+
for (const name of Object.keys(record).sort()) {
|
|
29
|
+
const item = canonical(record[name], name);
|
|
30
|
+
if (item !== undefined)
|
|
31
|
+
out[name] = item;
|
|
32
|
+
}
|
|
33
|
+
return out;
|
|
34
|
+
}
|
|
35
|
+
async function sha256(value) {
|
|
36
|
+
const bytes = new TextEncoder().encode(value);
|
|
37
|
+
const digest = new Uint8Array(await crypto.subtle.digest("SHA-256", bytes));
|
|
38
|
+
return [...digest].map((item) => item.toString(16).padStart(2, "0")).join("");
|
|
39
|
+
}
|
|
40
|
+
function schemaValue(route, side) {
|
|
41
|
+
const schema = route.schema;
|
|
42
|
+
if (schema === undefined)
|
|
43
|
+
return {};
|
|
44
|
+
if (side === "request") {
|
|
45
|
+
return {
|
|
46
|
+
body: schema.body?.jsonSchema ?? schema.body?.fields ?? null,
|
|
47
|
+
query: schema.query?.jsonSchema ?? schema.query?.fields ?? null,
|
|
48
|
+
params: schema.params?.jsonSchema ?? schema.params?.fields ?? null,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
response: schema.response?.jsonSchema ?? schema.response?.fields ?? null,
|
|
53
|
+
sse: schema.sse?.jsonSchema ?? schema.sse?.fields ?? null,
|
|
54
|
+
errors: Object.fromEntries(Object.entries(schema.errors ?? {}).map(([status, value]) => [
|
|
55
|
+
status,
|
|
56
|
+
value.jsonSchema ?? value.fields ?? null,
|
|
57
|
+
])),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
export async function digestRoute(route) {
|
|
61
|
+
const request = JSON.stringify(canonical(schemaValue(route, "request")));
|
|
62
|
+
const response = JSON.stringify(canonical(schemaValue(route, "response")));
|
|
63
|
+
return { request: await sha256(request), response: await sha256(response) };
|
|
64
|
+
}
|
|
65
|
+
export async function buildContractsLock(source) {
|
|
66
|
+
const routes = Object.fromEntries(await Promise.all(reflectRoutes(source).map(async (route) => [`${route.method} ${route.path}`, await digestRoute(route)])));
|
|
67
|
+
return {
|
|
68
|
+
version: 1,
|
|
69
|
+
routes: Object.fromEntries(Object.entries(routes).sort(([a], [b]) => a.localeCompare(b))),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
async function loadBackend(cwd) {
|
|
73
|
+
const backendPath = resolve(cwd, "backend.ts");
|
|
74
|
+
if (!existsSync(backendPath))
|
|
75
|
+
throw new Error(`[nifra] no backend.ts in ${cwd}`);
|
|
76
|
+
const loadedValue = await import(__rewriteRelativeImportExtension(backendPath));
|
|
77
|
+
const loaded = recordOf(loadedValue);
|
|
78
|
+
if (loaded?.backend === undefined)
|
|
79
|
+
throw new Error(`[nifra] ${backendPath} does not export backend`);
|
|
80
|
+
return loaded.backend;
|
|
81
|
+
}
|
|
82
|
+
export async function snapshotContracts(cwd, out = DEFAULT_CONTRACTS_LOCK) {
|
|
83
|
+
const lock = await buildContractsLock(await loadBackend(cwd));
|
|
84
|
+
await Bun.write(resolve(cwd, out), `${JSON.stringify(lock, null, 2)}\n`);
|
|
85
|
+
return lock;
|
|
86
|
+
}
|
|
87
|
+
export function parseContractsLock(value) {
|
|
88
|
+
const record = recordOf(value);
|
|
89
|
+
if (record === undefined)
|
|
90
|
+
throw new TypeError("contracts lock must be an object");
|
|
91
|
+
const routesValue = record.routes;
|
|
92
|
+
const routesRecord = recordOf(routesValue);
|
|
93
|
+
if (record.version !== 1 || routesRecord === undefined)
|
|
94
|
+
throw new TypeError("contracts lock must have version 1 and routes");
|
|
95
|
+
const routes = {};
|
|
96
|
+
for (const [key, raw] of Object.entries(routesRecord)) {
|
|
97
|
+
const item = recordOf(raw);
|
|
98
|
+
const request = item?.request;
|
|
99
|
+
const response = item?.response;
|
|
100
|
+
if (request === undefined ||
|
|
101
|
+
typeof request !== "string" ||
|
|
102
|
+
response === undefined ||
|
|
103
|
+
typeof response !== "string" ||
|
|
104
|
+
!DIGEST.test(request) ||
|
|
105
|
+
!DIGEST.test(response))
|
|
106
|
+
throw new TypeError(`invalid contract ${key}`);
|
|
107
|
+
routes[key] = { request, response };
|
|
108
|
+
}
|
|
109
|
+
return { version: 1, routes };
|
|
110
|
+
}
|
|
111
|
+
export async function checkContractsLock(cwd, file = DEFAULT_CONTRACTS_LOCK) {
|
|
112
|
+
const path = resolve(cwd, file);
|
|
113
|
+
if (!existsSync(path))
|
|
114
|
+
return { present: false, diagnostics: [] };
|
|
115
|
+
const parsed = parseContractsLock(JSON.parse(await Bun.file(path).text()));
|
|
116
|
+
const current = await buildContractsLock(await loadBackend(cwd));
|
|
117
|
+
const diagnostics = [];
|
|
118
|
+
const keys = new Set([...Object.keys(parsed.routes), ...Object.keys(current.routes)]);
|
|
119
|
+
for (const key of [...keys].sort()) {
|
|
120
|
+
const before = parsed.routes[key];
|
|
121
|
+
const after = current.routes[key];
|
|
122
|
+
if (before === undefined ||
|
|
123
|
+
after === undefined ||
|
|
124
|
+
before.request !== after.request ||
|
|
125
|
+
before.response !== after.response) {
|
|
126
|
+
diagnostics.push({
|
|
127
|
+
route: key,
|
|
128
|
+
message: `contract changed for ${key}; if intentional run \`nifra contracts snapshot\` and include the lock update in the same change.`,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return { present: true, diagnostics };
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=contracts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contracts.js","sourceRoot":"","sources":["../src/contracts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** Stable, machine-actionable diagnostics shared by CLI gates and MCP renderers. */
|
|
2
|
+
export type Severity = "error" | "warn" | "info";
|
|
3
|
+
export interface DiagnosticFix {
|
|
4
|
+
readonly recipe: string;
|
|
5
|
+
readonly command?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface Diagnostic {
|
|
8
|
+
/** Stable forever. Never renumber or reuse. */
|
|
9
|
+
readonly code: string;
|
|
10
|
+
readonly severity: Severity;
|
|
11
|
+
readonly message: string;
|
|
12
|
+
readonly file?: string;
|
|
13
|
+
readonly line?: number;
|
|
14
|
+
/** Short evidence strings that help an agent act without exposing payloads. */
|
|
15
|
+
readonly evidence?: readonly string[];
|
|
16
|
+
readonly fix?: DiagnosticFix;
|
|
17
|
+
/** Command that proves the fix worked. */
|
|
18
|
+
readonly verify?: string;
|
|
19
|
+
}
|
|
20
|
+
export declare const diagnostic: (value: Diagnostic) => Diagnostic;
|
|
21
|
+
export declare function severityFails(severity: Severity, strict?: boolean): boolean;
|
|
22
|
+
export declare function normalizeSeverity(value: "error" | "warning" | "warn" | "info"): Severity;
|
|
23
|
+
//# sourceMappingURL=diagnostics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../src/diagnostics.ts"],"names":[],"mappings":"AAAA,oFAAoF;AAEpF,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAA;AAEhD,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAC1B;AAED,MAAM,WAAW,UAAU;IACzB,+CAA+C;IAC/C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB,+EAA+E;IAC/E,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACrC,QAAQ,CAAC,GAAG,CAAC,EAAE,aAAa,CAAA;IAC5B,0CAA0C;IAC1C,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CACzB;AAED,eAAO,MAAM,UAAU,GAAI,OAAO,UAAU,KAAG,UAAkC,CAAA;AAEjF,wBAAgB,aAAa,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,UAAQ,GAAG,OAAO,CAEzE;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,CAExF"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Stable, machine-actionable diagnostics shared by CLI gates and MCP renderers. */
|
|
2
|
+
export const diagnostic = (value) => Object.freeze(value);
|
|
3
|
+
export function severityFails(severity, strict = false) {
|
|
4
|
+
return severity === "error" || (strict && severity === "warn");
|
|
5
|
+
}
|
|
6
|
+
export function normalizeSeverity(value) {
|
|
7
|
+
return value === "warning" ? "warn" : value;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=diagnostics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagnostics.js","sourceRoot":"","sources":["../src/diagnostics.ts"],"names":[],"mappings":"AAAA,oFAAoF;AAuBpF,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,KAAiB,EAAc,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AAEjF,MAAM,UAAU,aAAa,CAAC,QAAkB,EAAE,MAAM,GAAG,KAAK;IAC9D,OAAO,QAAQ,KAAK,OAAO,IAAI,CAAC,MAAM,IAAI,QAAQ,KAAK,MAAM,CAAC,CAAA;AAChE,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAA4C;IAC5E,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAA;AAC7C,CAAC"}
|
package/dist/diff-tool.d.ts
CHANGED
|
@@ -24,6 +24,8 @@ export declare const DEFAULT_SNAPSHOT_FILE = "api-snapshot.json";
|
|
|
24
24
|
export declare function parseSnapshotFile(content: string, sourcePath: string): SnapshotFile;
|
|
25
25
|
/** Render a diff for terminals: breaking first, then info, then compatible. */
|
|
26
26
|
export declare function formatDiff(diff: RoutesDiff): string;
|
|
27
|
+
/** Import `backend.ts` from `cwd` and snapshot its routes. */
|
|
28
|
+
export declare function snapshotBackend(cwd: string): Promise<readonly RouteSnapshot[]>;
|
|
27
29
|
/** `nifra snapshot`: write the current contract as the CI baseline. */
|
|
28
30
|
export declare function runSnapshot(cwd: string, options: {
|
|
29
31
|
out?: string;
|
package/dist/diff-tool.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diff-tool.d.ts","sourceRoot":"","sources":["../src/diff-tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,EAGL,KAAK,aAAa,EAClB,KAAK,UAAU,EAEhB,MAAM,oBAAoB,CAAA;AAE3B,oGAAoG;AACpG,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,aAAa,EAAE,CAAC,CAAA;IACzB,QAAQ,CAAC,MAAM,EAAE,SAAS,aAAa,EAAE,CAAA;CAC1C;AAED,eAAO,MAAM,qBAAqB,sBAAsB,CAAA;AAExD,qGAAqG;AACrG,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,YAAY,CAqBnF;AAaD,+EAA+E;AAC/E,wBAAgB,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAWnD;
|
|
1
|
+
{"version":3,"file":"diff-tool.d.ts","sourceRoot":"","sources":["../src/diff-tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,EAGL,KAAK,aAAa,EAClB,KAAK,UAAU,EAEhB,MAAM,oBAAoB,CAAA;AAE3B,oGAAoG;AACpG,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,aAAa,EAAE,CAAC,CAAA;IACzB,QAAQ,CAAC,MAAM,EAAE,SAAS,aAAa,EAAE,CAAA;CAC1C;AAED,eAAO,MAAM,qBAAqB,sBAAsB,CAAA;AAExD,qGAAqG;AACrG,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,YAAY,CAqBnF;AAaD,+EAA+E;AAC/E,wBAAgB,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAWnD;AAED,8DAA8D;AAC9D,wBAAsB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,aAAa,EAAE,CAAC,CAYpF;AAED,uEAAuE;AACvE,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAMvF;AAED,wGAAwG;AACxG,wBAAsB,OAAO,CAC3B,GAAG,EAAE,MAAM,EACX,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,GAC1B,OAAO,CAAC,OAAO,CAAC,CAiBlB"}
|
package/dist/diff-tool.js
CHANGED
|
@@ -67,7 +67,7 @@ export function formatDiff(diff) {
|
|
|
67
67
|
return `${lines.join("\n")}\n\n${summary}`;
|
|
68
68
|
}
|
|
69
69
|
/** Import `backend.ts` from `cwd` and snapshot its routes. */
|
|
70
|
-
async function snapshotBackend(cwd) {
|
|
70
|
+
export async function snapshotBackend(cwd) {
|
|
71
71
|
const backendPath = resolve(cwd, "backend.ts");
|
|
72
72
|
if (!existsSync(backendPath)) {
|
|
73
73
|
throw new Error(`[nifra] no backend.ts in ${cwd} - \`nifra snapshot\`/\`nifra diff\` compare the API contract, which lives in backend.ts.`);
|
package/dist/diff-tool.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diff-tool.js","sourceRoot":"","sources":["../src/diff-tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;;;;;;;;;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EACL,kBAAkB,EAIlB,cAAc,GACf,MAAM,oBAAoB,CAAA;AAQ3B,MAAM,CAAC,MAAM,qBAAqB,GAAG,mBAAmB,CAAA;AAExD,qGAAqG;AACrG,MAAM,UAAU,iBAAiB,CAAC,OAAe,EAAE,UAAkB;IACnE,IAAI,MAAe,CAAA;IACnB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IAC9B,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CACb,WAAW,UAAU,6DAA6D,CACnF,CAAA;IACH,CAAC;IACD,MAAM,MAAM,GAAG,MAAsC,CAAA;IACrD,IACE,MAAM,KAAK,IAAI;QACf,OAAO,MAAM,KAAK,QAAQ;QAC1B,MAAM,CAAC,aAAa,KAAK,CAAC;QAC1B,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EAC7B,CAAC;QACD,MAAM,IAAI,KAAK,CACb,WAAW,UAAU,kFAAkF,CACxG,CAAA;IACH,CAAC;IACD,OAAO,MAAsB,CAAA;AAC/B,CAAC;AAED,MAAM,aAAa,GAAG;IACpB,QAAQ,EAAE,YAAY;IACtB,UAAU,EAAE,cAAc;IAC1B,IAAI,EAAE,QAAQ;CACN,CAAA;AAEV,MAAM,cAAc,GAAG,CAAC,MAAmB,EAAU,EAAE;IACrD,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,EAAE,CAAA;IACpE,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,GAAG,KAAK,KAAK,MAAM,CAAC,OAAO,EAAE,CAAA;AACxG,CAAC,CAAA;AAED,+EAA+E;AAC/E,MAAM,UAAU,UAAU,CAAC,IAAgB;IACzC,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,0BAA0B,CAAA;IAChE,MAAM,KAAK,GAA4C,EAAE,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,CAAA;IAC9F,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC;SAC5B,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;SACrD,GAAG,CAAC,cAAc,CAAC,CAAA;IACtB,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,KAAK,UAAU,CAAC,CAAC,MAAM,CAAA;IACvF,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW;QAC9B,CAAC,CAAC,GAAG,QAAQ,mBAAmB,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,gCAAgC;QACzF,CAAC,CAAC,sBAAsB,CAAA;IAC1B,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,OAAO,EAAE,CAAA;AAC5C,CAAC;AAED,8DAA8D;AAC9D,KAAK,UAAU,eAAe,CAAC,GAAW;
|
|
1
|
+
{"version":3,"file":"diff-tool.js","sourceRoot":"","sources":["../src/diff-tool.ts"],"names":[],"mappings":"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"}
|
package/dist/docs-search.d.ts
CHANGED
|
@@ -13,18 +13,23 @@ export interface DocSection {
|
|
|
13
13
|
readonly heading: string;
|
|
14
14
|
readonly body: string;
|
|
15
15
|
}
|
|
16
|
+
export interface PreparedDocSection extends DocSection {
|
|
17
|
+
readonly headingTokens: ReadonlySet<string>;
|
|
18
|
+
readonly bodyLower: string;
|
|
19
|
+
}
|
|
16
20
|
/** Split the generated doc into its `##` sections (the `# title` intro becomes "Overview"). */
|
|
17
21
|
export declare function splitSections(markdown: string): DocSection[];
|
|
22
|
+
/** Return the immutable-build section parse and derived search fields from the process cache. */
|
|
23
|
+
export declare function getCachedDocSections(markdown: string): readonly PreparedDocSection[];
|
|
18
24
|
export interface ScoredSection extends DocSection {
|
|
19
25
|
readonly score: number;
|
|
20
26
|
}
|
|
21
27
|
/** Score sections against the query: a term in the HEADING is worth far more than body mentions
|
|
22
28
|
* (headings are curated names for exactly these lookups); body occurrences cap per term so one
|
|
23
29
|
* spammy section can't drown a precisely-titled one. */
|
|
24
|
-
export declare function searchSections(sections: readonly DocSection[], query: string, limit: number): ScoredSection[];
|
|
30
|
+
export declare function searchSections(sections: readonly (DocSection | PreparedDocSection)[], query: string, limit: number): ScoredSection[];
|
|
25
31
|
/** Render the tool result: matched sections, or the index when no query was given. */
|
|
26
32
|
export declare function renderDocsResult(markdown: string, query: string | undefined, limit: number): string;
|
|
27
|
-
/**
|
|
28
|
-
* and `dist/` (published) alike - `docs/llms-full.txt` sits at the package root next to both. */
|
|
33
|
+
/** The published corpus is immutable, so one read and one parsed-section cache are sufficient. */
|
|
29
34
|
export declare function loadDocsCorpus(): Promise<string | undefined>;
|
|
30
35
|
//# sourceMappingURL=docs-search.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"docs-search.d.ts","sourceRoot":"","sources":["../src/docs-search.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CACtB;AAED,+FAA+F;AAC/F,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,EAAE,CAoB5D;AAED,MAAM,WAAW,aAAc,SAAQ,UAAU;IAC/C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB;AAED;;wDAEwD;AACxD,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,SAAS,UAAU,EAAE,
|
|
1
|
+
{"version":3,"file":"docs-search.d.ts","sourceRoot":"","sources":["../src/docs-search.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CACtB;AAED,MAAM,WAAW,kBAAmB,SAAQ,UAAU;IACpD,QAAQ,CAAC,aAAa,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;IAC3C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAC3B;AAID,+FAA+F;AAC/F,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,EAAE,CAoB5D;AAUD,iGAAiG;AACjG,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,kBAAkB,EAAE,CAMpF;AAED,MAAM,WAAW,aAAc,SAAQ,UAAU;IAC/C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB;AAED;;wDAEwD;AACxD,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,SAAS,CAAC,UAAU,GAAG,kBAAkB,CAAC,EAAE,EACtD,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,GACZ,aAAa,EAAE,CAejB;AAMD,sFAAsF;AACtF,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,KAAK,EAAE,MAAM,GACZ,MAAM,CAmBR;AAMD,kGAAkG;AAClG,wBAAgB,cAAc,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAW5D"}
|
package/dist/docs-search.js
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* embedding infra would be complexity without a payoff.
|
|
11
11
|
*/
|
|
12
12
|
import { countBodyHits, queryTermGroups, tokenize, tokenSetHas } from "./search-terms.js";
|
|
13
|
+
const sectionCache = new Map();
|
|
13
14
|
/** Split the generated doc into its `##` sections (the `# title` intro becomes "Overview"). */
|
|
14
15
|
export function splitSections(markdown) {
|
|
15
16
|
const out = [];
|
|
@@ -34,6 +35,22 @@ export function splitSections(markdown) {
|
|
|
34
35
|
flush();
|
|
35
36
|
return out;
|
|
36
37
|
}
|
|
38
|
+
function prepareSection(section) {
|
|
39
|
+
return {
|
|
40
|
+
...section,
|
|
41
|
+
headingTokens: new Set(tokenize(section.heading)),
|
|
42
|
+
bodyLower: section.body.toLowerCase(),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/** Return the immutable-build section parse and derived search fields from the process cache. */
|
|
46
|
+
export function getCachedDocSections(markdown) {
|
|
47
|
+
const cached = sectionCache.get(markdown);
|
|
48
|
+
if (cached !== undefined)
|
|
49
|
+
return cached;
|
|
50
|
+
const prepared = splitSections(markdown).map(prepareSection);
|
|
51
|
+
sectionCache.set(markdown, prepared);
|
|
52
|
+
return prepared;
|
|
53
|
+
}
|
|
37
54
|
/** Score sections against the query: a term in the HEADING is worth far more than body mentions
|
|
38
55
|
* (headings are curated names for exactly these lookups); body occurrences cap per term so one
|
|
39
56
|
* spammy section can't drown a precisely-titled one. */
|
|
@@ -43,16 +60,15 @@ export function searchSections(sections, query, limit) {
|
|
|
43
60
|
return [];
|
|
44
61
|
const scored = [];
|
|
45
62
|
for (const section of sections) {
|
|
46
|
-
const
|
|
47
|
-
const bodyLower = section.body.toLowerCase();
|
|
63
|
+
const prepared = "headingTokens" in section && "bodyLower" in section ? section : prepareSection(section);
|
|
48
64
|
let score = 0;
|
|
49
65
|
for (const term of terms) {
|
|
50
|
-
if (tokenSetHas(headingTokens, term))
|
|
66
|
+
if (tokenSetHas(prepared.headingTokens, term))
|
|
51
67
|
score += 8;
|
|
52
|
-
score += countBodyHits(bodyLower, term, 5);
|
|
68
|
+
score += countBodyHits(prepared.bodyLower, term, 5);
|
|
53
69
|
}
|
|
54
70
|
if (score > 0)
|
|
55
|
-
scored.push({
|
|
71
|
+
scored.push({ heading: section.heading, body: section.body, score });
|
|
56
72
|
}
|
|
57
73
|
return scored.sort((a, b) => b.score - a.score).slice(0, limit);
|
|
58
74
|
}
|
|
@@ -61,7 +77,7 @@ export function searchSections(sections, query, limit) {
|
|
|
61
77
|
const MAX_SECTION_CHARS = 2800;
|
|
62
78
|
/** Render the tool result: matched sections, or the index when no query was given. */
|
|
63
79
|
export function renderDocsResult(markdown, query, limit) {
|
|
64
|
-
const sections =
|
|
80
|
+
const sections = getCachedDocSections(markdown);
|
|
65
81
|
if (query === undefined || query.trim() === "") {
|
|
66
82
|
const index = sections.map((s) => `- ${s.heading}`).join("\n");
|
|
67
83
|
return `# nifra docs - section index (pass \`query\` to fetch matching sections)\n\n${index}`;
|
|
@@ -81,14 +97,19 @@ export function renderDocsResult(markdown, query, limit) {
|
|
|
81
97
|
}
|
|
82
98
|
/** Load the bundled corpus. Resolves relative to this module so it works from `src/` (repo dev)
|
|
83
99
|
* and `dist/` (published) alike - `docs/llms-full.txt` sits at the package root next to both. */
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
100
|
+
let docsCorpusPromise;
|
|
101
|
+
/** The published corpus is immutable, so one read and one parsed-section cache are sufficient. */
|
|
102
|
+
export function loadDocsCorpus() {
|
|
103
|
+
docsCorpusPromise ??= (async () => {
|
|
104
|
+
const url = new URL("../docs/llms-full.txt", import.meta.url);
|
|
105
|
+
try {
|
|
106
|
+
const text = await Bun.file(url).text();
|
|
107
|
+
return text.length > 0 ? text : undefined;
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
return undefined;
|
|
111
|
+
}
|
|
112
|
+
})();
|
|
113
|
+
return docsCorpusPromise;
|
|
93
114
|
}
|
|
94
115
|
//# sourceMappingURL=docs-search.js.map
|
package/dist/docs-search.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"docs-search.js","sourceRoot":"","sources":["../src/docs-search.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"docs-search.js","sourceRoot":"","sources":["../src/docs-search.ts"],"names":[],"mappings":"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"}
|
package/dist/doctor.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type SourceFinding } from "./check.js";
|
|
2
2
|
import { type PipelineReport } from "./pipeline-report.js";
|
|
3
|
+
import { type ResolvedTarget } from "./port.js";
|
|
3
4
|
/**
|
|
4
5
|
* Resolve an import specifier to the npm package name it would install as, or `undefined` when it isn't
|
|
5
6
|
* an npm dependency at all (a relative/absolute path, a runtime builtin, or a malformed scope like the
|
|
@@ -31,6 +32,8 @@ export interface DoctorResult {
|
|
|
31
32
|
* Advisory (never folded into `ok`): while actively editing a linked package its dist is always
|
|
32
33
|
* momentarily behind - the finding matters when a dev server starts against it. */
|
|
33
34
|
readonly staleDists: readonly StaleDistFinding[];
|
|
35
|
+
/** Static production-readiness evidence for the selected deploy target. */
|
|
36
|
+
readonly readiness?: DoctorReadiness;
|
|
34
37
|
/**
|
|
35
38
|
* Which bundler this app's `dev`/`build` phases run on, read statically, plus the config hazards
|
|
36
39
|
* that exist only because there are two. Absent when the directory is not a nifra app.
|
|
@@ -45,6 +48,21 @@ export interface DoctorResult {
|
|
|
45
48
|
/** Findings that were safe to report but not safe to write automatically. */
|
|
46
49
|
readonly skippedFixes?: readonly DoctorSkippedFix[];
|
|
47
50
|
}
|
|
51
|
+
export type DoctorReadinessStatus = "configured" | "absent" | "not-applicable";
|
|
52
|
+
export interface DoctorReadinessItem {
|
|
53
|
+
readonly id: "request-timeout" | "admission" | "request-id-tracing" | "health-route" | "log-redaction" | "graceful-lifecycle";
|
|
54
|
+
readonly label: string;
|
|
55
|
+
readonly status: DoctorReadinessStatus;
|
|
56
|
+
readonly evidence?: string;
|
|
57
|
+
}
|
|
58
|
+
export interface DoctorReadiness {
|
|
59
|
+
readonly target: string;
|
|
60
|
+
readonly targetSource: ResolvedTarget["source"] | null;
|
|
61
|
+
readonly strict: boolean;
|
|
62
|
+
/** True when every applicable rule has static evidence. */
|
|
63
|
+
readonly ok: boolean;
|
|
64
|
+
readonly items: readonly DoctorReadinessItem[];
|
|
65
|
+
}
|
|
48
66
|
export interface DuplicateInstallCopy {
|
|
49
67
|
/** Installed version, or `unknown` when package metadata is incomplete. */
|
|
50
68
|
readonly version: string;
|
|
@@ -99,12 +117,20 @@ export interface StaleDistFinding {
|
|
|
99
117
|
*/
|
|
100
118
|
export declare function collectStaleWorkspaceDists(cwd: string, rootPackage: Record<string, unknown>): Promise<StaleDistFinding[]>;
|
|
101
119
|
/** Run doctor against the project at `cwd`: diff source imports vs declared deps. */
|
|
102
|
-
export declare function collectDoctorResult(cwd: string
|
|
120
|
+
export declare function collectDoctorResult(cwd: string, opts?: {
|
|
121
|
+
readonly target?: string;
|
|
122
|
+
readonly strict?: boolean;
|
|
123
|
+
}): Promise<DoctorResult>;
|
|
103
124
|
/** Safely add undeclared imports to package.json when the version can be inferred without network I/O. */
|
|
104
|
-
export declare function applyDoctorAutoFix(cwd: string
|
|
125
|
+
export declare function applyDoctorAutoFix(cwd: string, opts?: {
|
|
126
|
+
readonly target?: string;
|
|
127
|
+
readonly strict?: boolean;
|
|
128
|
+
}): Promise<DoctorResult>;
|
|
105
129
|
/** Run doctor; print a report (`--json` for machine output) and return whether it passed. */
|
|
106
130
|
export declare function runDoctor(cwd: string, opts?: {
|
|
107
131
|
readonly json?: boolean;
|
|
108
132
|
readonly autoFix?: boolean;
|
|
133
|
+
readonly strict?: boolean;
|
|
134
|
+
readonly target?: string;
|
|
109
135
|
}): Promise<boolean>;
|
|
110
136
|
//# sourceMappingURL=doctor.d.ts.map
|
package/dist/doctor.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAoB,KAAK,aAAa,EAA6B,MAAM,YAAY,CAAA;AAC5F,OAAO,EAAyB,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAA;
|
|
1
|
+
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"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"}
|