@nifrajs/cli 3.5.0 → 4.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 +42 -3
- package/dist/app-files.d.ts +11 -0
- package/dist/app-files.d.ts.map +1 -0
- package/dist/app-files.js +34 -0
- package/dist/app-files.js.map +1 -0
- package/dist/assure-hydration.d.ts +7 -1
- package/dist/assure-hydration.d.ts.map +1 -1
- package/dist/assure-hydration.js +128 -43
- package/dist/assure-hydration.js.map +1 -1
- package/dist/assure.d.ts.map +1 -1
- package/dist/assure.js +16 -2
- package/dist/assure.js.map +1 -1
- package/dist/capabilities-tool.d.ts +5 -1
- package/dist/capabilities-tool.d.ts.map +1 -1
- package/dist/capabilities-tool.js +32 -10
- package/dist/capabilities-tool.js.map +1 -1
- package/dist/cdn-check.d.ts +41 -0
- package/dist/cdn-check.d.ts.map +1 -0
- package/dist/cdn-check.js +207 -0
- package/dist/cdn-check.js.map +1 -0
- package/dist/check-diagnostics.d.ts +4 -0
- package/dist/check-diagnostics.d.ts.map +1 -1
- package/dist/check-diagnostics.js +13 -0
- package/dist/check-diagnostics.js.map +1 -1
- package/dist/check-scan.d.ts +49 -7
- package/dist/check-scan.d.ts.map +1 -1
- package/dist/check-scan.js +291 -62
- package/dist/check-scan.js.map +1 -1
- package/dist/check.d.ts.map +1 -1
- package/dist/check.js +99 -63
- package/dist/check.js.map +1 -1
- package/dist/cli.d.ts +42 -16
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +262 -82
- package/dist/cli.js.map +1 -1
- package/dist/command-catalog.d.ts +57 -5
- package/dist/command-catalog.d.ts.map +1 -1
- package/dist/command-catalog.js +270 -26
- package/dist/command-catalog.js.map +1 -1
- package/dist/config-target.d.ts +8 -0
- package/dist/config-target.d.ts.map +1 -0
- package/dist/config-target.js +45 -0
- package/dist/config-target.js.map +1 -0
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js +52 -13
- package/dist/contracts.js.map +1 -1
- package/dist/db-audit.d.ts +37 -0
- package/dist/db-audit.d.ts.map +1 -0
- package/dist/db-audit.js +99 -0
- package/dist/db-audit.js.map +1 -0
- package/dist/db-child.d.ts +64 -0
- package/dist/db-child.d.ts.map +1 -0
- package/dist/db-child.js +213 -0
- package/dist/db-child.js.map +1 -0
- package/dist/db-config.d.ts +60 -0
- package/dist/db-config.d.ts.map +1 -0
- package/dist/db-config.js +176 -0
- package/dist/db-config.js.map +1 -0
- package/dist/db-tool.d.ts +84 -0
- package/dist/db-tool.d.ts.map +1 -0
- package/dist/db-tool.js +537 -0
- package/dist/db-tool.js.map +1 -0
- package/dist/dev-bun-config.d.ts +20 -13
- package/dist/dev-bun-config.d.ts.map +1 -1
- package/dist/dev-bun-config.js +98 -41
- package/dist/dev-bun-config.js.map +1 -1
- package/dist/dev-feed-tool.d.ts +106 -0
- package/dist/dev-feed-tool.d.ts.map +1 -0
- package/dist/dev-feed-tool.js +713 -0
- package/dist/dev-feed-tool.js.map +1 -0
- package/dist/dev-server-client.d.ts +67 -0
- package/dist/dev-server-client.d.ts.map +1 -0
- package/dist/dev-server-client.js +195 -0
- package/dist/dev-server-client.js.map +1 -0
- package/dist/diff-tool.d.ts +3 -3
- package/dist/diff-tool.d.ts.map +1 -1
- package/dist/diff-tool.js +6 -5
- package/dist/diff-tool.js.map +1 -1
- package/dist/docs-search.d.ts.map +1 -1
- package/dist/docs-search.js +12 -4
- package/dist/docs-search.js.map +1 -1
- package/dist/doctor.d.ts +17 -0
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +76 -15
- package/dist/doctor.js.map +1 -1
- package/dist/env-file.d.ts +15 -0
- package/dist/env-file.d.ts.map +1 -1
- package/dist/env-file.js +73 -1
- package/dist/env-file.js.map +1 -1
- package/dist/fix-recipes.d.ts.map +1 -1
- package/dist/fix-recipes.js +41 -21
- package/dist/fix-recipes.js.map +1 -1
- package/dist/frontend-guidance.js +5 -5
- package/dist/frontend-guidance.js.map +1 -1
- package/dist/i18n-check.d.ts +16 -0
- package/dist/i18n-check.d.ts.map +1 -0
- package/dist/i18n-check.js +154 -0
- package/dist/i18n-check.js.map +1 -0
- package/dist/init-agents.d.ts +49 -13
- package/dist/init-agents.d.ts.map +1 -1
- package/dist/init-agents.js +239 -34
- package/dist/init-agents.js.map +1 -1
- package/dist/internal/code-unit-order.d.ts +4 -0
- package/dist/internal/code-unit-order.d.ts.map +1 -0
- package/dist/internal/code-unit-order.js +6 -0
- package/dist/internal/code-unit-order.js.map +1 -0
- package/dist/internal/script-kind.d.ts +7 -0
- package/dist/internal/script-kind.d.ts.map +1 -0
- package/dist/internal/script-kind.js +12 -0
- package/dist/internal/script-kind.js.map +1 -0
- package/dist/internal/source-facts.d.ts +5 -0
- package/dist/internal/source-facts.d.ts.map +1 -1
- package/dist/internal/source-facts.js +61 -5
- package/dist/internal/source-facts.js.map +1 -1
- package/dist/internal/typescript-import.d.ts +49 -24
- package/dist/internal/typescript-import.d.ts.map +1 -1
- package/dist/internal/typescript-import.js +507 -67
- package/dist/internal/typescript-import.js.map +1 -1
- package/dist/introspect.d.ts +5 -1
- package/dist/introspect.d.ts.map +1 -1
- package/dist/introspect.js +92 -27
- package/dist/introspect.js.map +1 -1
- package/dist/learn.js +3 -3
- package/dist/learn.js.map +1 -1
- package/dist/levels-tool.d.ts +10 -0
- package/dist/levels-tool.d.ts.map +1 -1
- package/dist/levels-tool.js +33 -3
- package/dist/levels-tool.js.map +1 -1
- package/dist/load.d.ts +67 -17
- package/dist/load.d.ts.map +1 -1
- package/dist/load.js +78 -18
- package/dist/load.js.map +1 -1
- package/dist/manifest-tool.d.ts.map +1 -1
- package/dist/manifest-tool.js +3 -2
- package/dist/manifest-tool.js.map +1 -1
- package/dist/mcp-app-tool.d.ts.map +1 -1
- package/dist/mcp-app-tool.js +2 -0
- package/dist/mcp-app-tool.js.map +1 -1
- package/dist/mcp-context.js +1 -1
- package/dist/mcp-context.js.map +1 -1
- package/dist/mcp-delegate.d.ts +57 -0
- package/dist/mcp-delegate.d.ts.map +1 -0
- package/dist/mcp-delegate.js +130 -0
- package/dist/mcp-delegate.js.map +1 -0
- package/dist/mcp-docs-tools.d.ts.map +1 -1
- package/dist/mcp-docs-tools.js +23 -5
- package/dist/mcp-docs-tools.js.map +1 -1
- package/dist/mcp-exec.d.ts +2 -0
- package/dist/mcp-exec.d.ts.map +1 -1
- package/dist/mcp-exec.js +132 -108
- package/dist/mcp-exec.js.map +1 -1
- package/dist/mcp-http.d.ts.map +1 -1
- package/dist/mcp-http.js +17 -5
- package/dist/mcp-http.js.map +1 -1
- package/dist/mcp-io.d.ts +14 -0
- package/dist/mcp-io.d.ts.map +1 -1
- package/dist/mcp-io.js +45 -0
- package/dist/mcp-io.js.map +1 -1
- package/dist/mcp-isolate.d.ts +48 -0
- package/dist/mcp-isolate.d.ts.map +1 -0
- package/dist/mcp-isolate.js +222 -0
- package/dist/mcp-isolate.js.map +1 -0
- package/dist/mcp-project-child.d.ts +74 -0
- package/dist/mcp-project-child.d.ts.map +1 -0
- package/dist/mcp-project-child.js +130 -0
- package/dist/mcp-project-child.js.map +1 -0
- package/dist/mcp-render.js +2 -2
- package/dist/mcp-render.js.map +1 -1
- package/dist/mcp-root.d.ts +37 -9
- package/dist/mcp-root.d.ts.map +1 -1
- package/dist/mcp-root.js +110 -23
- package/dist/mcp-root.js.map +1 -1
- package/dist/mcp-run.d.ts +18 -1
- package/dist/mcp-run.d.ts.map +1 -1
- package/dist/mcp-run.js +82 -9
- package/dist/mcp-run.js.map +1 -1
- package/dist/mcp-ws.js +4 -1
- package/dist/mcp-ws.js.map +1 -1
- package/dist/mcp.d.ts +16 -3
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +81 -53
- package/dist/mcp.js.map +1 -1
- package/dist/migrate-layout.d.ts +44 -0
- package/dist/migrate-layout.d.ts.map +1 -0
- package/dist/migrate-layout.js +982 -0
- package/dist/migrate-layout.js.map +1 -0
- package/dist/openapi-tool.d.ts +2 -2
- package/dist/openapi-tool.d.ts.map +1 -1
- package/dist/openapi-tool.js.map +1 -1
- package/dist/openapi-types.d.ts +2 -1
- package/dist/openapi-types.d.ts.map +1 -1
- package/dist/openapi-types.js +240 -12
- package/dist/openapi-types.js.map +1 -1
- package/dist/pipeline-report.d.ts +3 -2
- package/dist/pipeline-report.d.ts.map +1 -1
- package/dist/pipeline-report.js +19 -16
- package/dist/pipeline-report.js.map +1 -1
- package/dist/port.d.ts +5 -4
- package/dist/port.d.ts.map +1 -1
- package/dist/port.js +46 -29
- package/dist/port.js.map +1 -1
- package/dist/project-facts.d.ts +5 -0
- package/dist/project-facts.d.ts.map +1 -1
- package/dist/project-facts.js.map +1 -1
- package/dist/recipes/4.0.0.d.ts +9 -0
- package/dist/recipes/4.0.0.d.ts.map +1 -0
- package/dist/recipes/4.0.0.js +34 -0
- package/dist/recipes/4.0.0.js.map +1 -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/release-verification.d.ts +11 -1
- package/dist/release-verification.d.ts.map +1 -1
- package/dist/release-verification.js +47 -4
- package/dist/release-verification.js.map +1 -1
- package/dist/review.d.ts.map +1 -1
- package/dist/review.js +12 -8
- package/dist/review.js.map +1 -1
- package/dist/route-types.d.ts +28 -0
- package/dist/route-types.d.ts.map +1 -0
- package/dist/route-types.js +106 -0
- package/dist/route-types.js.map +1 -0
- package/dist/rules/codes.d.ts +9 -0
- package/dist/rules/codes.d.ts.map +1 -1
- package/dist/rules/codes.js +9 -0
- package/dist/rules/codes.js.map +1 -1
- package/dist/rules/data-guard.d.ts +12 -0
- package/dist/rules/data-guard.d.ts.map +1 -0
- package/dist/rules/data-guard.js +213 -0
- package/dist/rules/data-guard.js.map +1 -0
- package/dist/rules/index.d.ts +3 -0
- package/dist/rules/index.d.ts.map +1 -1
- package/dist/rules/index.js +17 -5
- package/dist/rules/index.js.map +1 -1
- package/dist/rules/islands.d.ts.map +1 -1
- package/dist/rules/islands.js +7 -4
- package/dist/rules/islands.js.map +1 -1
- package/dist/rules/legacy.d.ts.map +1 -1
- package/dist/rules/legacy.js +71 -38
- package/dist/rules/legacy.js.map +1 -1
- package/dist/rules/nano.d.ts.map +1 -1
- package/dist/rules/nano.js +15 -6
- package/dist/rules/nano.js.map +1 -1
- package/dist/rules/pages.d.ts +15 -0
- package/dist/rules/pages.d.ts.map +1 -0
- package/dist/rules/pages.js +88 -0
- package/dist/rules/pages.js.map +1 -0
- package/dist/rules/routes.d.ts +11 -0
- package/dist/rules/routes.d.ts.map +1 -1
- package/dist/rules/routes.js +180 -2
- package/dist/rules/routes.js.map +1 -1
- package/dist/rules/secrets.d.ts +10 -0
- package/dist/rules/secrets.d.ts.map +1 -0
- package/dist/rules/secrets.js +169 -0
- package/dist/rules/secrets.js.map +1 -0
- package/dist/rules/security.d.ts +7 -0
- package/dist/rules/security.d.ts.map +1 -1
- package/dist/rules/security.js +171 -65
- package/dist/rules/security.js.map +1 -1
- package/dist/rules/typescript.d.ts +16 -0
- package/dist/rules/typescript.d.ts.map +1 -0
- package/dist/rules/typescript.js +59 -0
- package/dist/rules/typescript.js.map +1 -0
- package/dist/rules/zones.d.ts +17 -0
- package/dist/rules/zones.d.ts.map +1 -0
- package/dist/rules/zones.js +174 -0
- package/dist/rules/zones.js.map +1 -0
- package/dist/scaffold.d.ts +25 -12
- package/dist/scaffold.d.ts.map +1 -1
- package/dist/scaffold.js +132 -87
- package/dist/scaffold.js.map +1 -1
- package/dist/sdk.d.ts +17 -3
- package/dist/sdk.d.ts.map +1 -1
- package/dist/sdk.js +941 -153
- package/dist/sdk.js.map +1 -1
- package/dist/search-terms.d.ts +2 -0
- package/dist/search-terms.d.ts.map +1 -1
- package/dist/search-terms.js +23 -8
- package/dist/search-terms.js.map +1 -1
- package/dist/smoke.d.ts +79 -0
- package/dist/smoke.d.ts.map +1 -0
- package/dist/smoke.js +494 -0
- package/dist/smoke.js.map +1 -0
- package/dist/sync-manifest.d.ts.map +1 -1
- package/dist/sync-manifest.js +2 -1
- package/dist/sync-manifest.js.map +1 -1
- package/dist/sync-routes.d.ts +4 -3
- package/dist/sync-routes.d.ts.map +1 -1
- package/dist/sync-routes.js +4 -3
- package/dist/sync-routes.js.map +1 -1
- package/dist/test-tool.d.ts.map +1 -1
- package/dist/test-tool.js +30 -11
- package/dist/test-tool.js.map +1 -1
- package/dist/types-search.d.ts.map +1 -1
- package/dist/types-search.js +11 -5
- package/dist/types-search.js.map +1 -1
- package/dist/upgrade.d.ts +36 -6
- package/dist/upgrade.d.ts.map +1 -1
- package/dist/upgrade.js +167 -29
- package/dist/upgrade.js.map +1 -1
- package/dist/verification-plan.d.ts.map +1 -1
- package/dist/verification-plan.js +4 -0
- package/dist/verification-plan.js.map +1 -1
- package/dist/verification.d.ts.map +1 -1
- package/dist/verification.js +45 -12
- package/dist/verification.js.map +1 -1
- package/dist/web-app-options.d.ts +19 -0
- package/dist/web-app-options.d.ts.map +1 -0
- package/dist/web-app-options.js +49 -0
- package/dist/web-app-options.js.map +1 -0
- package/dist/work-graph.d.ts.map +1 -1
- package/dist/work-graph.js +29 -13
- package/dist/work-graph.js.map +1 -1
- package/docs/examples.json +185 -29
- package/docs/llms-full.txt +3807 -580
- package/docs/types.json +14229 -10939
- package/package.json +19 -12
- package/src/app-files.ts +40 -0
- package/src/assure-hydration.ts +139 -46
- package/src/assure.ts +17 -2
- package/src/capabilities-tool.ts +35 -9
- package/src/cdn-check.ts +268 -0
- package/src/check-diagnostics.ts +17 -0
- package/src/check-scan.ts +358 -63
- package/src/check.ts +97 -62
- package/src/cli.ts +296 -87
- package/src/command-catalog.ts +374 -38
- package/src/config-target.ts +47 -0
- package/src/contracts.ts +54 -12
- package/src/db-audit.ts +128 -0
- package/src/db-child.ts +285 -0
- package/src/db-config.ts +224 -0
- package/src/db-tool.ts +690 -0
- package/src/dev-bun-config.ts +116 -40
- package/src/dev-feed-tool.ts +912 -0
- package/src/dev-server-client.ts +267 -0
- package/src/diff-tool.ts +6 -5
- package/src/docs-search.ts +10 -3
- package/src/doctor.ts +98 -15
- package/src/env-file.ts +78 -1
- package/src/fix-recipes.ts +44 -31
- package/src/frontend-guidance.ts +5 -5
- package/src/i18n-check.ts +179 -0
- package/src/init-agents.ts +301 -38
- package/src/internal/code-unit-order.ts +5 -0
- package/src/internal/script-kind.ts +11 -0
- package/src/internal/source-facts.ts +96 -22
- package/src/internal/typescript-import.ts +663 -68
- package/src/introspect.ts +90 -27
- package/src/learn.ts +3 -3
- package/src/levels-tool.ts +47 -2
- package/src/load.ts +140 -33
- package/src/manifest-tool.ts +3 -2
- package/src/mcp-app-tool.ts +2 -0
- package/src/mcp-context.ts +1 -1
- package/src/mcp-delegate.ts +162 -0
- package/src/mcp-docs-tools.ts +23 -5
- package/src/mcp-exec.ts +160 -132
- package/src/mcp-http.ts +19 -5
- package/src/mcp-io.ts +57 -0
- package/src/mcp-isolate.ts +287 -0
- package/src/mcp-project-child.ts +182 -0
- package/src/mcp-render.ts +2 -2
- package/src/mcp-root.ts +117 -22
- package/src/mcp-run.ts +104 -10
- package/src/mcp-ws.ts +4 -1
- package/src/mcp.ts +106 -64
- package/src/migrate-layout.ts +1121 -0
- package/src/openapi-tool.ts +7 -3
- package/src/openapi-types.ts +315 -13
- package/src/pipeline-report.ts +22 -18
- package/src/port.ts +53 -30
- package/src/project-facts.ts +5 -0
- package/src/recipes/4.0.0.ts +35 -0
- package/src/recipes/index.ts +2 -0
- package/src/release-verification.ts +74 -5
- package/src/review.ts +13 -8
- package/src/route-types.ts +133 -0
- package/src/rules/codes.ts +9 -0
- package/src/rules/data-guard.ts +230 -0
- package/src/rules/index.ts +18 -5
- package/src/rules/islands.ts +12 -4
- package/src/rules/legacy.ts +71 -39
- package/src/rules/nano.ts +18 -6
- package/src/rules/pages.ts +99 -0
- package/src/rules/routes.ts +181 -2
- package/src/rules/secrets.ts +174 -0
- package/src/rules/security.ts +198 -70
- package/src/rules/typescript.ts +77 -0
- package/src/rules/zones.ts +195 -0
- package/src/scaffold.ts +147 -95
- package/src/sdk.ts +1215 -158
- package/src/search-terms.ts +24 -7
- package/src/smoke.ts +607 -0
- package/src/sync-manifest.ts +2 -1
- package/src/sync-routes.ts +4 -3
- package/src/test-tool.ts +32 -11
- package/src/types-search.ts +11 -4
- package/src/upgrade.ts +205 -25
- package/src/verification-plan.ts +13 -0
- package/src/verification.ts +50 -12
- package/src/web-app-options.ts +57 -0
- package/src/work-graph.ts +27 -13
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `createWebApp` options a CLI-run app takes from its framework config and `backend/app.ts`,
|
|
3
|
+
* built in one place. `nifra dev`, the static prerender, `nifra mcp`'s render tool and the
|
|
4
|
+
* hydration gate each construct the app themselves, and the generated server entry constructs it in
|
|
5
|
+
* production; when each call site picked its own subset, the app they served drifted from the one
|
|
6
|
+
* that ships.
|
|
7
|
+
*/
|
|
8
|
+
import { inProcessClient } from "@nifrajs/client"
|
|
9
|
+
import type { CreateWebAppOptions } from "@nifrajs/web"
|
|
10
|
+
import { FRAMEWORK_WEB_OPTIONS, type FrameworkWebOption, type NifraFramework } from "./load.ts"
|
|
11
|
+
|
|
12
|
+
type FrameworkWebAppOptions = Pick<
|
|
13
|
+
CreateWebAppOptions,
|
|
14
|
+
"use" | "api" | "apiPrefix" | "apiStrip" | "mounts" | "csp" | "nonce"
|
|
15
|
+
>
|
|
16
|
+
|
|
17
|
+
/** `use`, the backend as `api`, and every forwarded framework field the config sets. */
|
|
18
|
+
export function frameworkWebAppOptions(
|
|
19
|
+
fw: NifraFramework,
|
|
20
|
+
backend: unknown,
|
|
21
|
+
): FrameworkWebAppOptions {
|
|
22
|
+
const options: Record<string, unknown> = {}
|
|
23
|
+
if (fw.use !== undefined) options.use = fw.use
|
|
24
|
+
if (backend !== undefined) options.api = inProcessClient(backend as never)
|
|
25
|
+
for (const name of FRAMEWORK_WEB_OPTIONS) {
|
|
26
|
+
if (fw[name] !== undefined) options[name] = fw[name]
|
|
27
|
+
}
|
|
28
|
+
return options as FrameworkWebAppOptions
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* The mount paths the app will serve ahead of page routing, read from the config alone (no app is
|
|
33
|
+
* built): each `mounts` entry, plus the backend at `apiPrefix` when `backend/app.ts` exports one. A
|
|
34
|
+
* mount added inside `use` is not visible here; `createWebApp` checks its own mount table at
|
|
35
|
+
* startup.
|
|
36
|
+
*/
|
|
37
|
+
export function frameworkMountPaths(fw: NifraFramework, hasBackend: boolean): string[] {
|
|
38
|
+
const paths: string[] = []
|
|
39
|
+
for (const mount of fw.mounts ?? []) {
|
|
40
|
+
if (typeof mount?.path === "string") paths.push(mount.path)
|
|
41
|
+
}
|
|
42
|
+
const apiPrefix = fw.apiPrefix ?? "/api"
|
|
43
|
+
if (hasBackend && apiPrefix !== "") paths.push(apiPrefix)
|
|
44
|
+
return paths
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** The generated server entry's imports for the forwarded fields the config sets, all from the
|
|
48
|
+
* edge-safe framework module. */
|
|
49
|
+
export function frameworkOptionImports(
|
|
50
|
+
fw: NifraFramework,
|
|
51
|
+
frameworkFile: string,
|
|
52
|
+
): { optionImports?: Partial<Record<FrameworkWebOption, string>> } {
|
|
53
|
+
const imports: Partial<Record<FrameworkWebOption, string>> = {}
|
|
54
|
+
for (const name of FRAMEWORK_WEB_OPTIONS)
|
|
55
|
+
if (fw[name] !== undefined) imports[name] = frameworkFile
|
|
56
|
+
return Object.keys(imports).length === 0 ? {} : { optionImports: imports }
|
|
57
|
+
}
|
package/src/work-graph.ts
CHANGED
|
@@ -16,7 +16,9 @@ import {
|
|
|
16
16
|
} from "@nifrajs/core/evidence"
|
|
17
17
|
import type { ReflectedRoute } from "@nifrajs/core/reflection"
|
|
18
18
|
import { Glob } from "bun"
|
|
19
|
+
import { BACKEND_APP_FILE, CONFIG_FILE, FRAMEWORK_FILE } from "./app-files.ts"
|
|
19
20
|
import { digestRoute } from "./contracts.ts"
|
|
21
|
+
import { codeUnitOrder } from "./internal/code-unit-order.ts"
|
|
20
22
|
|
|
21
23
|
export type WorkGraphNodeKind =
|
|
22
24
|
| "route"
|
|
@@ -133,8 +135,11 @@ export interface ProjectWorkGraphResult {
|
|
|
133
135
|
readonly evidence: EvidenceBundle
|
|
134
136
|
}
|
|
135
137
|
|
|
136
|
-
|
|
138
|
+
// Framework component, content, and style files are app source too: an edit to one makes a build stale.
|
|
139
|
+
const SOURCE_GLOB = new Glob("**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs,json,svelte,vue,mdx,css}")
|
|
137
140
|
const IGNORED = /(^|\/)(node_modules|dist|build|\.nifra|\.git|\.wrangler|coverage)\//
|
|
141
|
+
const APP_SOURCE_DIR = /^(?:routes|frontend|backend|shared)\//
|
|
142
|
+
const BACKEND_SOURCE_DIR = /^(?:backend|shared)\//
|
|
138
143
|
const MANIFEST_NAMES = new Set([
|
|
139
144
|
"server-manifest.ts",
|
|
140
145
|
"nifra-manifest.json",
|
|
@@ -176,13 +181,13 @@ export function evaluateBuildFreshness(input: {
|
|
|
176
181
|
|
|
177
182
|
export async function inspectBuildFreshness(cwd: string): Promise<BuildFreshness> {
|
|
178
183
|
const sourcePaths: string[] = []
|
|
179
|
-
for (const name of [
|
|
184
|
+
for (const name of [BACKEND_APP_FILE, FRAMEWORK_FILE, CONFIG_FILE]) {
|
|
180
185
|
const path = resolve(cwd, name)
|
|
181
186
|
if (existsSync(path)) sourcePaths.push(path)
|
|
182
187
|
}
|
|
183
188
|
for await (const rawPath of SOURCE_GLOB.scan({ cwd, dot: false })) {
|
|
184
189
|
const path = rawPath.replaceAll("\\", "/")
|
|
185
|
-
if (!IGNORED.test(path) &&
|
|
190
|
+
if (!IGNORED.test(path) && APP_SOURCE_DIR.test(path)) sourcePaths.push(resolve(cwd, path))
|
|
186
191
|
}
|
|
187
192
|
const sourceTimes = await fileTimes(sourcePaths)
|
|
188
193
|
for (const buildDirName of ["dist", "build"]) {
|
|
@@ -215,8 +220,8 @@ export async function collectProjectWorkGraph(
|
|
|
215
220
|
): Promise<ProjectWorkGraphResult> {
|
|
216
221
|
const freshness = await inspectBuildFreshness(cwd)
|
|
217
222
|
if (!freshness.ok) throw new StaleBuildError(freshness)
|
|
218
|
-
const backendPath = resolve(cwd,
|
|
219
|
-
if (!existsSync(backendPath)) throw new Error(`[nifra] no
|
|
223
|
+
const backendPath = resolve(cwd, BACKEND_APP_FILE)
|
|
224
|
+
if (!existsSync(backendPath)) throw new Error(`[nifra] no ${BACKEND_APP_FILE} in ${cwd}`)
|
|
220
225
|
const loadedValue: unknown = await import(`${backendPath}?nifra-work-graph=${Date.now()}`)
|
|
221
226
|
const loaded = recordOf(loadedValue)
|
|
222
227
|
if (loaded?.backend === undefined)
|
|
@@ -290,8 +295,8 @@ export async function buildWorkGraph(input: WorkGraphBuildInput): Promise<WorkGr
|
|
|
290
295
|
})
|
|
291
296
|
for (const file of routeFiles)
|
|
292
297
|
addEdge({ from: `file:${file}`, to: routeId, relation: "implements" })
|
|
293
|
-
if (routeFiles.length === 0 && sourceFiles.some((file) => file.path ===
|
|
294
|
-
addEdge({ from:
|
|
298
|
+
if (routeFiles.length === 0 && sourceFiles.some((file) => file.path === BACKEND_APP_FILE))
|
|
299
|
+
addEdge({ from: `file:${BACKEND_APP_FILE}`, to: routeId, relation: "implements" })
|
|
295
300
|
for (const [name, schema] of Object.entries(route.schema ?? {})) {
|
|
296
301
|
if (schema === undefined || name === "errors") continue
|
|
297
302
|
const schemaId = `schema:${routeKey}:${name}`
|
|
@@ -334,9 +339,9 @@ export async function buildWorkGraph(input: WorkGraphBuildInput): Promise<WorkGr
|
|
|
334
339
|
for (const file of manifestFiles)
|
|
335
340
|
addEdge({ from: `manifest:${file.path}`, to: routeId, relation: "describes" })
|
|
336
341
|
}
|
|
337
|
-
const sortedNodes = [...nodes.values()].sort((a, b) => a.id
|
|
342
|
+
const sortedNodes = [...nodes.values()].sort((a, b) => codeUnitOrder(a.id, b.id))
|
|
338
343
|
const sortedEdges = edges.sort((a, b) =>
|
|
339
|
-
`${a.from}\n${a.to}\n${a.relation}
|
|
344
|
+
codeUnitOrder(`${a.from}\n${a.to}\n${a.relation}`, `${b.from}\n${b.to}\n${b.relation}`),
|
|
340
345
|
)
|
|
341
346
|
const digest = await digestJson({ nodes: sortedNodes, edges: sortedEdges })
|
|
342
347
|
return Object.freeze({
|
|
@@ -353,7 +358,9 @@ export function queryImpact(graph: WorkGraph, changedFiles: readonly string[]):
|
|
|
353
358
|
...new Set(changedFiles.map((file) => file.replace(/^\.\//, "").replaceAll("\\", "/"))),
|
|
354
359
|
]
|
|
355
360
|
const seeds = new Set<string>()
|
|
361
|
+
const unmodeled: string[] = []
|
|
356
362
|
for (const file of normalized) {
|
|
363
|
+
let seeded = false
|
|
357
364
|
for (const node of graph.nodes) {
|
|
358
365
|
if (
|
|
359
366
|
(node.kind === "file" || node.kind === "test" || node.kind === "manifest") &&
|
|
@@ -361,11 +368,18 @@ export function queryImpact(graph: WorkGraph, changedFiles: readonly string[]):
|
|
|
361
368
|
node.id === `test:${file}` ||
|
|
362
369
|
node.id === `manifest:${file}` ||
|
|
363
370
|
node.files.includes(file))
|
|
364
|
-
)
|
|
371
|
+
) {
|
|
365
372
|
seeds.add(node.id)
|
|
373
|
+
seeded = true
|
|
374
|
+
}
|
|
366
375
|
}
|
|
376
|
+
// An app file the graph does not model (deleted, or a type it does not read) has an unknown
|
|
377
|
+
// reach, so it stands for itself and impacts every route rather than proving nothing.
|
|
378
|
+
if (!seeded && APP_SOURCE_DIR.test(file)) unmodeled.push(file)
|
|
367
379
|
}
|
|
368
|
-
|
|
380
|
+
for (const file of unmodeled) seeds.add(`file:${file}`)
|
|
381
|
+
// Any backend or shared module can reach every handler through backend/app.ts.
|
|
382
|
+
if (unmodeled.length > 0 || normalized.some((file) => BACKEND_SOURCE_DIR.test(file)))
|
|
369
383
|
for (const node of graph.nodes) if (node.kind === "route") seeds.add(node.id)
|
|
370
384
|
const impacted = new Set(seeds)
|
|
371
385
|
const queue = [...seeds]
|
|
@@ -444,7 +458,7 @@ export function createEvidenceBundle(
|
|
|
444
458
|
plan: ProofPlan,
|
|
445
459
|
proofs: readonly ProofEvidence[] = [],
|
|
446
460
|
): EvidenceBundle {
|
|
447
|
-
const evidence = [...proofs].sort((a, b) => a.id
|
|
461
|
+
const evidence = [...proofs].sort((a, b) => codeUnitOrder(a.id, b.id))
|
|
448
462
|
// Levels are not cumulative (assure does not typecheck), so every planned step needs its own
|
|
449
463
|
// passing proof; a higher-level pass never subsumes a lower one.
|
|
450
464
|
const done =
|
|
@@ -581,7 +595,7 @@ function filesForRoute(
|
|
|
581
595
|
const matches = files
|
|
582
596
|
.filter(
|
|
583
597
|
(file) =>
|
|
584
|
-
file.path ===
|
|
598
|
+
file.path === BACKEND_APP_FILE ||
|
|
585
599
|
(file.path.startsWith("routes/") && file.content.includes(route.path)),
|
|
586
600
|
)
|
|
587
601
|
.map((file) => file.path)
|