@nifrajs/cli 4.0.2 → 5.0.0
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 +3 -0
- package/dist/agent-files.d.ts +107 -0
- package/dist/agent-files.d.ts.map +1 -0
- package/dist/agent-files.js +162 -0
- package/dist/agent-files.js.map +1 -0
- package/dist/app-files.d.ts +6 -0
- package/dist/app-files.d.ts.map +1 -1
- package/dist/app-files.js +27 -2
- package/dist/app-files.js.map +1 -1
- package/dist/assure-hydration.d.ts.map +1 -1
- package/dist/assure-hydration.js +7 -2
- package/dist/assure-hydration.js.map +1 -1
- package/dist/capabilities-tool.d.ts.map +1 -1
- package/dist/capabilities-tool.js +13 -3
- package/dist/capabilities-tool.js.map +1 -1
- package/dist/check-diagnostics.d.ts +20 -2
- package/dist/check-diagnostics.d.ts.map +1 -1
- package/dist/check-diagnostics.js +54 -7
- package/dist/check-diagnostics.js.map +1 -1
- package/dist/check-scan.d.ts +75 -22
- package/dist/check-scan.d.ts.map +1 -1
- package/dist/check-scan.js +1475 -310
- package/dist/check-scan.js.map +1 -1
- package/dist/check.d.ts +2 -2
- package/dist/check.d.ts.map +1 -1
- package/dist/check.js +192 -65
- package/dist/check.js.map +1 -1
- package/dist/cli.d.ts +7 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +112 -5
- package/dist/cli.js.map +1 -1
- package/dist/client-module.d.ts +18 -0
- package/dist/client-module.d.ts.map +1 -0
- package/dist/client-module.js +49 -0
- package/dist/client-module.js.map +1 -0
- package/dist/command-catalog.d.ts +16 -5
- package/dist/command-catalog.d.ts.map +1 -1
- package/dist/command-catalog.js +133 -29
- package/dist/command-catalog.js.map +1 -1
- package/dist/component-check.d.ts +13 -0
- package/dist/component-check.d.ts.map +1 -0
- package/dist/component-check.js +59 -0
- package/dist/component-check.js.map +1 -0
- package/dist/contract-proof.d.ts +1 -1
- package/dist/contract-proof.d.ts.map +1 -1
- package/dist/contract-proof.js +2 -24
- package/dist/contract-proof.js.map +1 -1
- package/dist/contracts.d.ts +19 -0
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js +50 -3
- package/dist/contracts.js.map +1 -1
- package/dist/db-tool.d.ts.map +1 -1
- package/dist/db-tool.js +4 -3
- package/dist/db-tool.js.map +1 -1
- package/dist/dev-bun-config.d.ts +5 -1
- package/dist/dev-bun-config.d.ts.map +1 -1
- package/dist/dev-bun-config.js +44 -11
- package/dist/dev-bun-config.js.map +1 -1
- package/dist/diagnostics.d.ts +3 -0
- package/dist/diagnostics.d.ts.map +1 -1
- package/dist/diagnostics.js.map +1 -1
- package/dist/diff-tool.d.ts +9 -8
- package/dist/diff-tool.d.ts.map +1 -1
- package/dist/diff-tool.js +28 -24
- package/dist/diff-tool.js.map +1 -1
- package/dist/doctor.d.ts +13 -0
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +23 -15
- package/dist/doctor.js.map +1 -1
- package/dist/env-file.d.ts +6 -0
- package/dist/env-file.d.ts.map +1 -1
- package/dist/env-file.js +6 -0
- package/dist/env-file.js.map +1 -1
- package/dist/fix-recipes.d.ts.map +1 -1
- package/dist/fix-recipes.js +21 -2
- package/dist/fix-recipes.js.map +1 -1
- package/dist/hand-built-manifest.d.ts +27 -0
- package/dist/hand-built-manifest.d.ts.map +1 -0
- package/dist/hand-built-manifest.js +124 -0
- package/dist/hand-built-manifest.js.map +1 -0
- package/dist/hooks-report.d.ts +23 -0
- package/dist/hooks-report.d.ts.map +1 -0
- package/dist/hooks-report.js +104 -0
- package/dist/hooks-report.js.map +1 -0
- package/dist/init-agents.d.ts +2 -2
- package/dist/init-agents.d.ts.map +1 -1
- package/dist/init-agents.js +17 -11
- package/dist/init-agents.js.map +1 -1
- package/dist/internal/nifra-project.d.ts +41 -0
- package/dist/internal/nifra-project.d.ts.map +1 -0
- package/dist/internal/nifra-project.js +183 -0
- package/dist/internal/nifra-project.js.map +1 -0
- package/dist/internal/project-specifiers.d.ts +16 -0
- package/dist/internal/project-specifiers.d.ts.map +1 -0
- package/dist/internal/project-specifiers.js +396 -0
- package/dist/internal/project-specifiers.js.map +1 -0
- package/dist/internal/script-kind.d.ts.map +1 -1
- package/dist/internal/script-kind.js +2 -1
- package/dist/internal/script-kind.js.map +1 -1
- package/dist/internal/source-facts.d.ts +2 -0
- package/dist/internal/source-facts.d.ts.map +1 -1
- package/dist/internal/source-facts.js +11 -0
- package/dist/internal/source-facts.js.map +1 -1
- package/dist/internal/typescript-import.d.ts +1 -1
- package/dist/internal/typescript-import.d.ts.map +1 -1
- package/dist/internal/typescript-import.js +5 -3
- package/dist/internal/typescript-import.js.map +1 -1
- package/dist/introspect.d.ts +6 -6
- package/dist/introspect.d.ts.map +1 -1
- package/dist/introspect.js +55 -24
- package/dist/introspect.js.map +1 -1
- package/dist/levels-tool.d.ts.map +1 -1
- package/dist/levels-tool.js +93 -15
- package/dist/levels-tool.js.map +1 -1
- package/dist/load.d.ts +31 -8
- package/dist/load.d.ts.map +1 -1
- package/dist/load.js +37 -7
- package/dist/load.js.map +1 -1
- package/dist/mcp-context.d.ts +5 -5
- package/dist/mcp-context.d.ts.map +1 -1
- package/dist/mcp-context.js +2 -2
- package/dist/mcp-context.js.map +1 -1
- package/dist/mcp-exec.d.ts +12 -4
- package/dist/mcp-exec.d.ts.map +1 -1
- package/dist/mcp-exec.js +50 -13
- package/dist/mcp-exec.js.map +1 -1
- package/dist/mcp-http.js +1 -1
- package/dist/mcp-io.d.ts +17 -0
- package/dist/mcp-io.d.ts.map +1 -1
- package/dist/mcp-io.js +40 -0
- package/dist/mcp-io.js.map +1 -1
- package/dist/mcp-isolate.d.ts.map +1 -1
- package/dist/mcp-isolate.js +3 -2
- package/dist/mcp-isolate.js.map +1 -1
- package/dist/mcp-project-child.js +1 -1
- package/dist/mcp-project-child.js.map +1 -1
- package/dist/mcp-root.d.ts.map +1 -1
- package/dist/mcp-root.js +50 -10
- package/dist/mcp-root.js.map +1 -1
- package/dist/mcp-ws.d.ts.map +1 -1
- package/dist/mcp-ws.js +3 -1
- package/dist/mcp-ws.js.map +1 -1
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +8 -2
- package/dist/mcp.js.map +1 -1
- package/dist/migrate-layout.d.ts +7 -0
- package/dist/migrate-layout.d.ts.map +1 -1
- package/dist/migrate-layout.js +778 -64
- package/dist/migrate-layout.js.map +1 -1
- package/dist/output-schemas.d.ts +94 -0
- package/dist/output-schemas.d.ts.map +1 -0
- package/dist/output-schemas.js +864 -0
- package/dist/output-schemas.js.map +1 -0
- package/dist/port.d.ts.map +1 -1
- package/dist/port.js +3 -2
- package/dist/port.js.map +1 -1
- package/dist/project-facts.d.ts +15 -4
- package/dist/project-facts.d.ts.map +1 -1
- package/dist/project-facts.js +1 -0
- package/dist/project-facts.js.map +1 -1
- package/dist/recipes/5.0.0.d.ts +11 -0
- package/dist/recipes/5.0.0.d.ts.map +1 -0
- package/dist/recipes/5.0.0.js +34 -0
- package/dist/recipes/5.0.0.js.map +1 -0
- package/dist/recipes/index.d.ts +7 -0
- package/dist/recipes/index.d.ts.map +1 -1
- package/dist/recipes/index.js +2 -0
- package/dist/recipes/index.js.map +1 -1
- package/dist/replay.d.ts.map +1 -1
- package/dist/replay.js +12 -3
- package/dist/replay.js.map +1 -1
- package/dist/review.d.ts +3 -1
- package/dist/review.d.ts.map +1 -1
- package/dist/review.js +38 -7
- package/dist/review.js.map +1 -1
- package/dist/rules/codes.d.ts +10 -0
- package/dist/rules/codes.d.ts.map +1 -1
- package/dist/rules/codes.js +10 -0
- package/dist/rules/codes.js.map +1 -1
- package/dist/rules/comment-markers.d.ts +16 -7
- package/dist/rules/comment-markers.d.ts.map +1 -1
- package/dist/rules/comment-markers.js +58 -19
- package/dist/rules/comment-markers.js.map +1 -1
- package/dist/rules/contract-visibility.d.ts +3 -0
- package/dist/rules/contract-visibility.d.ts.map +1 -0
- package/dist/rules/contract-visibility.js +337 -0
- package/dist/rules/contract-visibility.js.map +1 -0
- package/dist/rules/data-guard.d.ts +7 -0
- package/dist/rules/data-guard.d.ts.map +1 -1
- package/dist/rules/data-guard.js +319 -37
- package/dist/rules/data-guard.js.map +1 -1
- package/dist/rules/layout.d.ts +4 -0
- package/dist/rules/layout.d.ts.map +1 -0
- package/dist/rules/layout.js +19 -0
- package/dist/rules/layout.js.map +1 -0
- package/dist/rules/legacy.d.ts.map +1 -1
- package/dist/rules/legacy.js +158 -43
- package/dist/rules/legacy.js.map +1 -1
- package/dist/rules/pages.d.ts +24 -0
- package/dist/rules/pages.d.ts.map +1 -1
- package/dist/rules/pages.js +221 -3
- package/dist/rules/pages.js.map +1 -1
- package/dist/rules/routes.d.ts +6 -0
- package/dist/rules/routes.d.ts.map +1 -1
- package/dist/rules/routes.js +111 -16
- package/dist/rules/routes.js.map +1 -1
- package/dist/rules/secrets.js +2 -2
- package/dist/rules/secrets.js.map +1 -1
- package/dist/rules/security.d.ts +12 -1
- package/dist/rules/security.d.ts.map +1 -1
- package/dist/rules/security.js +281 -68
- package/dist/rules/security.js.map +1 -1
- package/dist/rules/zones.d.ts +13 -0
- package/dist/rules/zones.d.ts.map +1 -1
- package/dist/rules/zones.js +192 -40
- package/dist/rules/zones.js.map +1 -1
- package/dist/scaffold.d.ts.map +1 -1
- package/dist/scaffold.js +6 -4
- package/dist/scaffold.js.map +1 -1
- package/dist/sdk.d.ts.map +1 -1
- package/dist/sdk.js +14 -5
- package/dist/sdk.js.map +1 -1
- package/dist/stylex-migrate.d.ts.map +1 -1
- package/dist/stylex-migrate.js +163 -7
- package/dist/stylex-migrate.js.map +1 -1
- package/dist/test-tool.d.ts.map +1 -1
- package/dist/test-tool.js +12 -3
- package/dist/test-tool.js.map +1 -1
- package/dist/typecheck-coverage.d.ts +20 -0
- package/dist/typecheck-coverage.d.ts.map +1 -0
- package/dist/typecheck-coverage.js +129 -0
- package/dist/typecheck-coverage.js.map +1 -0
- package/dist/upgrade.d.ts +69 -0
- package/dist/upgrade.d.ts.map +1 -1
- package/dist/upgrade.js +420 -77
- package/dist/upgrade.js.map +1 -1
- package/dist/verification-plan.d.ts.map +1 -1
- package/dist/verification-plan.js +11 -0
- package/dist/verification-plan.js.map +1 -1
- package/dist/version-drift.d.ts +22 -0
- package/dist/version-drift.d.ts.map +1 -0
- package/dist/version-drift.js +42 -0
- package/dist/version-drift.js.map +1 -0
- package/dist/web-app-options.d.ts +1 -1
- package/dist/web-app-options.d.ts.map +1 -1
- package/dist/web-app-options.js +1 -1
- package/dist/web-app-options.js.map +1 -1
- package/dist/work-graph.d.ts.map +1 -1
- package/dist/work-graph.js +20 -8
- package/dist/work-graph.js.map +1 -1
- package/docs/examples.json +54 -6
- package/docs/llms-full.txt +1539 -138
- package/docs/types.json +1456 -206
- package/package.json +11 -12
- package/src/agent-files.ts +203 -0
- package/src/app-files.ts +34 -4
- package/src/assure-hydration.ts +15 -2
- package/src/capabilities-tool.ts +15 -3
- package/src/check-diagnostics.ts +73 -9
- package/src/check-scan.ts +1773 -381
- package/src/check.ts +237 -76
- package/src/cli.ts +141 -5
- package/src/client-module.ts +61 -0
- package/src/command-catalog.ts +166 -37
- package/src/component-check.ts +79 -0
- package/src/contract-proof.ts +3 -25
- package/src/contracts.ts +60 -3
- package/src/db-tool.ts +5 -2
- package/src/dev-bun-config.ts +51 -10
- package/src/diagnostics.ts +3 -0
- package/src/diff-tool.ts +33 -26
- package/src/doctor.ts +43 -21
- package/src/env-file.ts +7 -0
- package/src/fix-recipes.ts +25 -2
- package/src/hand-built-manifest.ts +144 -0
- package/src/hooks-report.ts +135 -0
- package/src/init-agents.ts +17 -11
- package/src/internal/nifra-project.ts +191 -0
- package/src/internal/project-specifiers.ts +424 -0
- package/src/internal/script-kind.ts +2 -1
- package/src/internal/source-facts.ts +25 -0
- package/src/internal/typescript-import.ts +10 -3
- package/src/introspect.ts +65 -27
- package/src/levels-tool.ts +117 -20
- package/src/load.ts +78 -14
- package/src/mcp-context.ts +7 -7
- package/src/mcp-exec.ts +60 -17
- package/src/mcp-http.ts +1 -1
- package/src/mcp-io.ts +41 -0
- package/src/mcp-isolate.ts +9 -2
- package/src/mcp-project-child.ts +1 -1
- package/src/mcp-root.ts +58 -8
- package/src/mcp-ws.ts +4 -2
- package/src/mcp.ts +8 -3
- package/src/migrate-layout.ts +885 -63
- package/src/output-schemas.ts +1084 -0
- package/src/port.ts +3 -2
- package/src/project-facts.ts +17 -3
- package/src/recipes/5.0.0.ts +35 -0
- package/src/recipes/index.ts +10 -0
- package/src/replay.ts +14 -3
- package/src/review.ts +39 -10
- package/src/rules/codes.ts +10 -0
- package/src/rules/comment-markers.ts +57 -21
- package/src/rules/contract-visibility.ts +383 -0
- package/src/rules/data-guard.ts +351 -42
- package/src/rules/layout.ts +22 -0
- package/src/rules/legacy.ts +184 -51
- package/src/rules/pages.ts +238 -3
- package/src/rules/routes.ts +124 -16
- package/src/rules/secrets.ts +2 -2
- package/src/rules/security.ts +352 -71
- package/src/rules/zones.ts +205 -38
- package/src/scaffold.ts +6 -4
- package/src/sdk.ts +14 -5
- package/src/stylex-migrate.ts +134 -7
- package/src/test-tool.ts +18 -3
- package/src/typecheck-coverage.ts +134 -0
- package/src/upgrade.ts +487 -71
- package/src/verification-plan.ts +24 -0
- package/src/version-drift.ts +67 -0
- package/src/web-app-options.ts +2 -2
- package/src/work-graph.ts +17 -12
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NF-C039: contract operations the source implements but `backend/app.ts` does not serve. The contract
|
|
3
|
+
* lock, the typed client checks and `nifra routes` read the backend that file exports, so an
|
|
4
|
+
* `implement(contract, handlers)` app built anywhere else is invisible to every one of them.
|
|
5
|
+
*
|
|
6
|
+
* The served routes come from the backend the contract-lock check already loaded; this rule runs no
|
|
7
|
+
* project code of its own. Without a lock the backend is not loaded and the comparison is skipped.
|
|
8
|
+
*/
|
|
9
|
+
import { existsSync, readFileSync, realpathSync } from "node:fs";
|
|
10
|
+
import { join, relative } from "node:path";
|
|
11
|
+
import { BACKEND_APP_FILE } from "../app-files.js";
|
|
12
|
+
import { diagnostic } from "../diagnostics.js";
|
|
13
|
+
import { createSpecifierResolver } from "../internal/project-specifiers.js";
|
|
14
|
+
import { scriptKindOf } from "../internal/script-kind.js";
|
|
15
|
+
import { loadRuleTypeScript } from "./typescript.js";
|
|
16
|
+
const CONTRACT_MODULE = "@nifrajs/core/contract";
|
|
17
|
+
const CODE_FILE = /\.[cm]?[jt]sx?$/;
|
|
18
|
+
// `export { implement } from "@nifrajs/core/contract"` or `export * from ...`: a project module that
|
|
19
|
+
// passes the contract API through.
|
|
20
|
+
const PASSES_THROUGH = (name) => new RegExp(`export\\s*(?:\\*|\\{[^}]*\\b${name}\\b[^}]*\\})\\s*from\\s*["']${CONTRACT_MODULE}["']`);
|
|
21
|
+
const LISTED = 6;
|
|
22
|
+
function unwrap(ts, node) {
|
|
23
|
+
let current = node;
|
|
24
|
+
while (ts.isAsExpression(current) ||
|
|
25
|
+
ts.isSatisfiesExpression(current) ||
|
|
26
|
+
ts.isParenthesizedExpression(current))
|
|
27
|
+
current = current.expression;
|
|
28
|
+
return current;
|
|
29
|
+
}
|
|
30
|
+
function bindings(ts, tree, file, root, resolve) {
|
|
31
|
+
const named = new Map();
|
|
32
|
+
const namespaces = new Set();
|
|
33
|
+
const imported = new Map();
|
|
34
|
+
for (const statement of tree.statements) {
|
|
35
|
+
if (!ts.isImportDeclaration(statement) || !ts.isStringLiteral(statement.moduleSpecifier))
|
|
36
|
+
continue;
|
|
37
|
+
const specifier = statement.moduleSpecifier.text;
|
|
38
|
+
const clause = statement.importClause;
|
|
39
|
+
if (clause === undefined || clause.isTypeOnly)
|
|
40
|
+
continue;
|
|
41
|
+
const bound = clause.namedBindings;
|
|
42
|
+
if (bound !== undefined && ts.isNamespaceImport(bound)) {
|
|
43
|
+
if (specifier === CONTRACT_MODULE)
|
|
44
|
+
namespaces.add(bound.name.text);
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
if (bound === undefined)
|
|
48
|
+
continue;
|
|
49
|
+
// A project module may pass the API through; one hop is followed.
|
|
50
|
+
let passesThrough;
|
|
51
|
+
if (specifier !== CONTRACT_MODULE) {
|
|
52
|
+
const target = resolve(join(root, file), specifier);
|
|
53
|
+
const text = target === undefined ? undefined : readText(target);
|
|
54
|
+
passesThrough =
|
|
55
|
+
text === undefined ? () => false : (name) => PASSES_THROUGH(name).test(text);
|
|
56
|
+
}
|
|
57
|
+
for (const element of bound.elements) {
|
|
58
|
+
if (element.isTypeOnly)
|
|
59
|
+
continue;
|
|
60
|
+
const name = (element.propertyName ?? element.name).text;
|
|
61
|
+
if (name === "implement" || name === "defineContract") {
|
|
62
|
+
if (passesThrough === undefined || passesThrough(name))
|
|
63
|
+
named.set(element.name.text, name);
|
|
64
|
+
}
|
|
65
|
+
else if (passesThrough !== undefined)
|
|
66
|
+
imported.set(element.name.text, { specifier, name });
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return { named, namespaces, imported };
|
|
70
|
+
}
|
|
71
|
+
function readText(path) {
|
|
72
|
+
try {
|
|
73
|
+
return readFileSync(path, "utf8");
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/** Whether `callee` names the contract API's `api` function under these bindings. */
|
|
80
|
+
function calls(ts, callee, bound, api) {
|
|
81
|
+
if (ts.isIdentifier(callee))
|
|
82
|
+
return bound.named.get(callee.text) === api;
|
|
83
|
+
return (ts.isPropertyAccessExpression(callee) &&
|
|
84
|
+
ts.isIdentifier(callee.expression) &&
|
|
85
|
+
bound.namespaces.has(callee.expression.text) &&
|
|
86
|
+
callee.name.text === api);
|
|
87
|
+
}
|
|
88
|
+
/** The operations an object literal of a contract declares, and what could not be read. */
|
|
89
|
+
function operationsOf(ts, literal) {
|
|
90
|
+
const operations = [];
|
|
91
|
+
const unreadable = [];
|
|
92
|
+
for (const property of literal.properties) {
|
|
93
|
+
if (!ts.isPropertyAssignment(property)) {
|
|
94
|
+
unreadable.push("an operation spread or written as a method");
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
const name = property.name.getText().replace(/^["']|["']$/g, "");
|
|
98
|
+
const op = unwrap(ts, property.initializer);
|
|
99
|
+
if (!ts.isObjectLiteralExpression(op)) {
|
|
100
|
+
unreadable.push(`operation "${name}" is not an object literal`);
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
const field = (key) => {
|
|
104
|
+
for (const member of op.properties) {
|
|
105
|
+
if (!ts.isPropertyAssignment(member) || member.name.getText() !== key)
|
|
106
|
+
continue;
|
|
107
|
+
const value = unwrap(ts, member.initializer);
|
|
108
|
+
return ts.isStringLiteralLike(value) ? value.text : undefined;
|
|
109
|
+
}
|
|
110
|
+
return undefined;
|
|
111
|
+
};
|
|
112
|
+
const method = field("method");
|
|
113
|
+
const path = field("path");
|
|
114
|
+
if (method === undefined || path === undefined)
|
|
115
|
+
unreadable.push(`operation "${name}" has a method or path that is not a string literal`);
|
|
116
|
+
else
|
|
117
|
+
operations.push({ name, method: method.toUpperCase(), path });
|
|
118
|
+
}
|
|
119
|
+
return { operations, unreadable };
|
|
120
|
+
}
|
|
121
|
+
export const contractVisibilityRule = {
|
|
122
|
+
code: "NF-C039",
|
|
123
|
+
title: "Implemented contract operation the backend does not serve",
|
|
124
|
+
async scan(ctx) {
|
|
125
|
+
// The backend compared against is this package's, so a file in a nested package is not read.
|
|
126
|
+
const ownPackage = new Map();
|
|
127
|
+
const inOwnPackage = (dir) => {
|
|
128
|
+
if (dir === "")
|
|
129
|
+
return true;
|
|
130
|
+
const cached = ownPackage.get(dir);
|
|
131
|
+
if (cached !== undefined)
|
|
132
|
+
return cached;
|
|
133
|
+
const own = !existsSync(join(ctx.root, dir, "package.json")) &&
|
|
134
|
+
inOwnPackage(dir.slice(0, Math.max(dir.lastIndexOf("/"), 0)));
|
|
135
|
+
ownPackage.set(dir, own);
|
|
136
|
+
return own;
|
|
137
|
+
};
|
|
138
|
+
const candidates = ctx.sources.files.filter((file) => {
|
|
139
|
+
if (!CODE_FILE.test(file) || file.endsWith(".d.ts"))
|
|
140
|
+
return false;
|
|
141
|
+
if (!inOwnPackage(file.slice(0, Math.max(file.lastIndexOf("/"), 0))))
|
|
142
|
+
return false;
|
|
143
|
+
const text = ctx.sources.read(file);
|
|
144
|
+
return text?.includes("implement") === true;
|
|
145
|
+
});
|
|
146
|
+
if (candidates.length === 0)
|
|
147
|
+
return [];
|
|
148
|
+
const loaded = await loadRuleTypeScript(ctx);
|
|
149
|
+
const ts = loaded.compiler;
|
|
150
|
+
if (ts === undefined)
|
|
151
|
+
return [];
|
|
152
|
+
const resolve = createSpecifierResolver();
|
|
153
|
+
// The resolver answers with real paths, so the root is read as one to name files project-relative.
|
|
154
|
+
const realRoot = (() => {
|
|
155
|
+
try {
|
|
156
|
+
return realpathSync(ctx.root);
|
|
157
|
+
}
|
|
158
|
+
catch {
|
|
159
|
+
return ctx.root;
|
|
160
|
+
}
|
|
161
|
+
})();
|
|
162
|
+
const parsedCache = new Map();
|
|
163
|
+
/** A project file, by its project-relative name, parsed with its contract bindings. */
|
|
164
|
+
const parse = (file, text) => {
|
|
165
|
+
if (parsedCache.has(file))
|
|
166
|
+
return parsedCache.get(file);
|
|
167
|
+
const tree = text === undefined
|
|
168
|
+
? undefined
|
|
169
|
+
: ts.createSourceFile(file, text, ts.ScriptTarget.Latest, true, scriptKindOf(ts, file));
|
|
170
|
+
const parsed = tree === undefined
|
|
171
|
+
? undefined
|
|
172
|
+
: { tree, bound: bindings(ts, tree, file, ctx.root, resolve) };
|
|
173
|
+
parsedCache.set(file, parsed);
|
|
174
|
+
return parsed;
|
|
175
|
+
};
|
|
176
|
+
/** The object literal `defineContract({...})` gives the const `name` in `file`, followed one hop
|
|
177
|
+
* into a project module it is imported from. */
|
|
178
|
+
const contractLiteral = (file, parsed, name, hops = 0) => {
|
|
179
|
+
for (const statement of parsed.tree.statements) {
|
|
180
|
+
if (!ts.isVariableStatement(statement))
|
|
181
|
+
continue;
|
|
182
|
+
for (const declaration of statement.declarationList.declarations) {
|
|
183
|
+
if (!ts.isIdentifier(declaration.name) || declaration.name.text !== name)
|
|
184
|
+
continue;
|
|
185
|
+
if (declaration.initializer === undefined)
|
|
186
|
+
return undefined;
|
|
187
|
+
const init = unwrap(ts, declaration.initializer);
|
|
188
|
+
if (ts.isObjectLiteralExpression(init))
|
|
189
|
+
return init;
|
|
190
|
+
if (!ts.isCallExpression(init) ||
|
|
191
|
+
!calls(ts, init.expression, parsed.bound, "defineContract"))
|
|
192
|
+
return undefined;
|
|
193
|
+
const arg = init.arguments[0];
|
|
194
|
+
const literal = arg === undefined ? undefined : unwrap(ts, arg);
|
|
195
|
+
return literal !== undefined && ts.isObjectLiteralExpression(literal)
|
|
196
|
+
? literal
|
|
197
|
+
: undefined;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
const from = parsed.bound.imported.get(name);
|
|
201
|
+
if (from === undefined || hops > 0)
|
|
202
|
+
return undefined;
|
|
203
|
+
const target = resolve(join(ctx.root, file), from.specifier);
|
|
204
|
+
if (target === undefined)
|
|
205
|
+
return undefined;
|
|
206
|
+
const rel = relative(realRoot, target).replaceAll("\\", "/");
|
|
207
|
+
const next = parse(rel, readText(target));
|
|
208
|
+
return next === undefined ? undefined : contractLiteral(rel, next, from.name, hops + 1);
|
|
209
|
+
};
|
|
210
|
+
const implementations = [];
|
|
211
|
+
for (const file of candidates) {
|
|
212
|
+
const parsed = parse(file, ctx.sources.read(file));
|
|
213
|
+
if (parsed === undefined ||
|
|
214
|
+
(parsed.bound.named.size === 0 && parsed.bound.namespaces.size === 0))
|
|
215
|
+
continue;
|
|
216
|
+
const visit = (node) => {
|
|
217
|
+
if (ts.isCallExpression(node) && calls(ts, node.expression, parsed.bound, "implement")) {
|
|
218
|
+
const line = parsed.tree.getLineAndCharacterOfPosition(node.getStart()).line + 1;
|
|
219
|
+
const arg = node.arguments[0] === undefined ? undefined : unwrap(ts, node.arguments[0]);
|
|
220
|
+
let literal;
|
|
221
|
+
let contract = arg?.getText() ?? "(none)";
|
|
222
|
+
if (arg !== undefined && ts.isIdentifier(arg))
|
|
223
|
+
literal = contractLiteral(file, parsed, arg.text);
|
|
224
|
+
else if (arg !== undefined && ts.isObjectLiteralExpression(arg)) {
|
|
225
|
+
literal = arg;
|
|
226
|
+
contract = "an inline contract";
|
|
227
|
+
}
|
|
228
|
+
else if (arg !== undefined &&
|
|
229
|
+
ts.isCallExpression(arg) &&
|
|
230
|
+
calls(ts, arg.expression, parsed.bound, "defineContract")) {
|
|
231
|
+
const inner = arg.arguments[0] === undefined ? undefined : unwrap(ts, arg.arguments[0]);
|
|
232
|
+
if (inner !== undefined && ts.isObjectLiteralExpression(inner))
|
|
233
|
+
literal = inner;
|
|
234
|
+
contract = "an inline contract";
|
|
235
|
+
}
|
|
236
|
+
if (literal === undefined) {
|
|
237
|
+
implementations.push({
|
|
238
|
+
file,
|
|
239
|
+
line,
|
|
240
|
+
contract,
|
|
241
|
+
operations: [],
|
|
242
|
+
unreadable: [
|
|
243
|
+
`the contract ${contract} is not a defineContract({...}) the scan can read`,
|
|
244
|
+
],
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
else
|
|
248
|
+
implementations.push({ file, line, contract, ...operationsOf(ts, literal) });
|
|
249
|
+
}
|
|
250
|
+
ts.forEachChild(node, visit);
|
|
251
|
+
};
|
|
252
|
+
visit(parsed.tree);
|
|
253
|
+
}
|
|
254
|
+
if (implementations.length === 0)
|
|
255
|
+
return [];
|
|
256
|
+
const findings = [];
|
|
257
|
+
for (const { file, line, contract, unreadable } of implementations) {
|
|
258
|
+
if (unreadable.length === 0)
|
|
259
|
+
continue;
|
|
260
|
+
findings.push(diagnostic({
|
|
261
|
+
code: "NF-C039",
|
|
262
|
+
severity: "warn",
|
|
263
|
+
file,
|
|
264
|
+
line,
|
|
265
|
+
message: `implement(${contract}): the static scan cannot read every operation (${unreadable.join("; ")}), so NF-C039 cannot tell whether backend/app.ts serves them. Write each operation's method and path as string literals in a defineContract({...}) const`,
|
|
266
|
+
verify: "nifra check --lints-only",
|
|
267
|
+
}));
|
|
268
|
+
}
|
|
269
|
+
if (!existsSync(join(ctx.root, BACKEND_APP_FILE))) {
|
|
270
|
+
const count = implementations.reduce((sum, item) => sum + item.operations.length, 0);
|
|
271
|
+
const first = implementations[0];
|
|
272
|
+
if (count > 0 && first !== undefined) {
|
|
273
|
+
findings.push(diagnostic({
|
|
274
|
+
code: "NF-C039",
|
|
275
|
+
severity: "warn",
|
|
276
|
+
file: first.file,
|
|
277
|
+
line: first.line,
|
|
278
|
+
message: `${count} contract operation(s) are implemented in source, but there is no ${BACKEND_APP_FILE}, so the contract lock, the typed client checks and nifra routes see none of them. Export the implementing app from ${BACKEND_APP_FILE} as \`backend\`, built with stub dependencies if it needs any`,
|
|
279
|
+
verify: "nifra check --lints-only",
|
|
280
|
+
}));
|
|
281
|
+
}
|
|
282
|
+
return findings;
|
|
283
|
+
}
|
|
284
|
+
const served = ctx.project.check.contracts.served;
|
|
285
|
+
if (served === undefined)
|
|
286
|
+
return findings;
|
|
287
|
+
const routes = served.map((key) => {
|
|
288
|
+
const at = key.indexOf(" ");
|
|
289
|
+
return { method: key.slice(0, at), path: key.slice(at + 1) };
|
|
290
|
+
});
|
|
291
|
+
const servedKeys = new Set(served);
|
|
292
|
+
const servedAt = (prefix, op) => op.path === "/"
|
|
293
|
+
? servedKeys.has(`${op.method} ${prefix === "" ? "/" : prefix}`) ||
|
|
294
|
+
servedKeys.has(`${op.method} ${prefix}/`)
|
|
295
|
+
: servedKeys.has(`${op.method} ${prefix}${op.path}`);
|
|
296
|
+
// A mount or group prefix serves every operation of the app under it, so one prefix must serve
|
|
297
|
+
// them all. Matching each operation on its own lets `/` match any route and `/:id` any `.../:id`.
|
|
298
|
+
const unserved = (operations) => {
|
|
299
|
+
const prefixes = new Set([""]);
|
|
300
|
+
for (const op of operations) {
|
|
301
|
+
for (const route of routes) {
|
|
302
|
+
if (route.method !== op.method)
|
|
303
|
+
continue;
|
|
304
|
+
if (op.path === "/")
|
|
305
|
+
prefixes.add(route.path.replace(/\/$/, ""));
|
|
306
|
+
else if (route.path.endsWith(op.path))
|
|
307
|
+
prefixes.add(route.path.slice(0, -op.path.length));
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
let fewest = operations;
|
|
311
|
+
for (const prefix of prefixes) {
|
|
312
|
+
const missing = operations.filter((op) => !servedAt(prefix, op));
|
|
313
|
+
if (missing.length < fewest.length)
|
|
314
|
+
fewest = missing;
|
|
315
|
+
}
|
|
316
|
+
return fewest;
|
|
317
|
+
};
|
|
318
|
+
for (const { file, line, contract, operations } of implementations) {
|
|
319
|
+
const missing = unserved(operations);
|
|
320
|
+
if (missing.length === 0)
|
|
321
|
+
continue;
|
|
322
|
+
const listed = missing.slice(0, LISTED).map((op) => `${op.method} ${op.path}`);
|
|
323
|
+
const more = missing.length > LISTED ? ` and ${missing.length - LISTED} more` : "";
|
|
324
|
+
findings.push(diagnostic({
|
|
325
|
+
code: "NF-C039",
|
|
326
|
+
severity: "warn",
|
|
327
|
+
file,
|
|
328
|
+
line,
|
|
329
|
+
message: `implement(${contract}) serves ${missing.length} operation(s) that ${BACKEND_APP_FILE} does not: ${listed.join(", ")}${more}. The contract lock, the typed client checks and nifra routes read only the backend that file exports, so they cannot see these. Mount this app in ${BACKEND_APP_FILE}, built with stub dependencies if it needs any`,
|
|
330
|
+
evidence: missing.map((op) => `${op.name}: ${op.method} ${op.path}`),
|
|
331
|
+
verify: "nifra check",
|
|
332
|
+
}));
|
|
333
|
+
}
|
|
334
|
+
return findings;
|
|
335
|
+
},
|
|
336
|
+
};
|
|
337
|
+
//# sourceMappingURL=contract-visibility.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract-visibility.js","sourceRoot":"","sources":["../../src/rules/contract-visibility.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
import type { CheckRule } from "./index.js";
|
|
2
|
+
/** The export statement of `name` in a code-position mask: a declaration or an `export { }` list. */
|
|
3
|
+
export declare const exported: (mask: string, name: string) => RegExpExecArray | null;
|
|
4
|
+
/** Where an expression starting at `start` ends: a `,`, `;` or closer at its own depth. */
|
|
5
|
+
export declare function expressionEnd(mask: string, start: number): number;
|
|
2
6
|
export interface MissingOutputSchema {
|
|
3
7
|
readonly name: "loader" | "action";
|
|
4
8
|
readonly schema: "loaderOutput" | "actionOutput";
|
|
5
9
|
readonly line: number;
|
|
10
|
+
/** Its own body returns a data literal, so every request that reaches that return fails. */
|
|
11
|
+
readonly proven: boolean;
|
|
6
12
|
}
|
|
7
13
|
/** The loader and action a route's backend half exports, may return data from, and gives no schema. */
|
|
8
14
|
export declare function missingOutputSchemas(content: string): MissingOutputSchema[];
|
|
9
15
|
export declare const missingOutputRule: CheckRule;
|
|
10
16
|
export declare const sensitiveOutputRule: CheckRule;
|
|
17
|
+
export declare const staleGeneratedOutputRule: CheckRule;
|
|
11
18
|
export declare const dataGuardRules: readonly CheckRule[];
|
|
12
19
|
//# sourceMappingURL=data-guard.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-guard.d.ts","sourceRoot":"","sources":["../../src/rules/data-guard.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"data-guard.d.ts","sourceRoot":"","sources":["../../src/rules/data-guard.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAQ3C,qGAAqG;AACrG,eAAO,MAAM,QAAQ,GAAI,MAAM,MAAM,EAAE,MAAM,MAAM,KAAG,eAAe,GAAG,IAG1D,CAAA;AA4Id,2FAA2F;AAC3F,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAsBjE;AAuCD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,QAAQ,CAAA;IAClC,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,cAAc,CAAA;IAChD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,4FAA4F;IAC5F,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;CACzB;AAID,uGAAuG;AACvG,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,mBAAmB,EAAE,CAsB3E;AAED,eAAO,MAAM,iBAAiB,EAAE,SAgC/B,CAAA;AA+GD,eAAO,MAAM,mBAAmB,EAAE,SA+DjC,CAAA;AAED,eAAO,MAAM,wBAAwB,EAAE,SA0DtC,CAAA;AAED,eAAO,MAAM,cAAc,sBAIzB,CAAA"}
|