@nifrajs/cli 3.3.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 +7 -15
- package/dist/check-diagnostics.d.ts.map +1 -1
- package/dist/check-diagnostics.js +162 -713
- package/dist/check-diagnostics.js.map +1 -1
- package/dist/check-scan.d.ts +58 -7
- package/dist/check-scan.d.ts.map +1 -1
- package/dist/check-scan.js +323 -62
- package/dist/check-scan.js.map +1 -1
- package/dist/check.d.ts +1 -0
- package/dist/check.d.ts.map +1 -1
- package/dist/check.js +145 -54
- 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 +306 -87
- package/dist/cli.js.map +1 -1
- package/dist/command-catalog.d.ts +60 -5
- package/dist/command-catalog.d.ts.map +1 -1
- package/dist/command-catalog.js +298 -33
- 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 +3 -2
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js +56 -16
- 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/diagnostics.d.ts +86 -0
- package/dist/diagnostics.d.ts.map +1 -1
- package/dist/diagnostics.js +85 -0
- package/dist/diagnostics.js.map +1 -1
- 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 +6 -4
- package/dist/introspect.d.ts.map +1 -1
- package/dist/introspect.js +93 -74
- 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 +71 -16
- 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.d.ts.map +1 -1
- package/dist/mcp-context.js +5 -6
- 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 +3 -0
- package/dist/mcp-exec.d.ts.map +1 -1
- package/dist/mcp-exec.js +263 -131
- package/dist/mcp-exec.js.map +1 -1
- package/dist/mcp-http.d.ts.map +1 -1
- package/dist/mcp-http.js +20 -5
- package/dist/mcp-http.js.map +1 -1
- package/dist/mcp-io.d.ts +26 -0
- package/dist/mcp-io.d.ts.map +1 -1
- package/dist/mcp-io.js +113 -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-path.d.ts +10 -0
- package/dist/mcp-path.d.ts.map +1 -0
- package/dist/mcp-path.js +51 -0
- package/dist/mcp-path.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-reflect.d.ts.map +1 -1
- package/dist/mcp-reflect.js +2 -2
- package/dist/mcp-reflect.js.map +1 -1
- package/dist/mcp-render.d.ts.map +1 -1
- package/dist/mcp-render.js +64 -45
- 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 +124 -25
- 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 +159 -55
- 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 +18 -5
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +165 -82
- 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 +28 -4
- package/dist/project-facts.d.ts.map +1 -1
- package/dist/project-facts.js +12 -2
- 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 +21 -0
- package/dist/review.d.ts.map +1 -0
- package/dist/review.js +823 -0
- package/dist/review.js.map +1 -0
- 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 +3 -1
- package/dist/rules/legacy.d.ts.map +1 -1
- package/dist/rules/legacy.js +829 -34
- 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 +154 -90
- 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 +8 -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 +3 -0
- package/dist/work-graph.d.ts.map +1 -1
- package/dist/work-graph.js +33 -16
- package/dist/work-graph.js.map +1 -1
- package/docs/examples.json +185 -29
- package/docs/llms-full.txt +4123 -548
- package/docs/types.json +14391 -10060
- package/package.json +19 -11
- 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 +199 -797
- package/src/check-scan.ts +394 -63
- package/src/check.ts +146 -58
- package/src/cli.ts +347 -92
- package/src/command-catalog.ts +407 -45
- package/src/config-target.ts +47 -0
- package/src/contracts.ts +66 -15
- 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/diagnostics.ts +179 -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 +93 -82
- package/src/learn.ts +3 -3
- package/src/levels-tool.ts +47 -2
- package/src/load.ts +144 -32
- package/src/manifest-tool.ts +3 -2
- package/src/mcp-app-tool.ts +2 -0
- package/src/mcp-context.ts +5 -7
- package/src/mcp-delegate.ts +162 -0
- package/src/mcp-docs-tools.ts +23 -5
- package/src/mcp-exec.ts +301 -161
- package/src/mcp-http.ts +22 -5
- package/src/mcp-io.ts +130 -0
- package/src/mcp-isolate.ts +287 -0
- package/src/mcp-path.ts +50 -0
- package/src/mcp-project-child.ts +182 -0
- package/src/mcp-reflect.ts +3 -2
- package/src/mcp-render.ts +72 -42
- package/src/mcp-root.ts +130 -24
- package/src/mcp-run.ts +190 -56
- package/src/mcp-ws.ts +4 -1
- package/src/mcp.ts +193 -91
- 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 +42 -8
- 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 +988 -0
- 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 +947 -35
- 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 +175 -98
- 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 +27 -0
- package/src/verification.ts +50 -12
- package/src/web-app-options.ts +57 -0
- package/src/work-graph.ts +40 -16
|
@@ -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
|
@@ -9,9 +9,16 @@
|
|
|
9
9
|
import { existsSync } from "node:fs"
|
|
10
10
|
import { readFile, stat } from "node:fs/promises"
|
|
11
11
|
import { basename, resolve } from "node:path"
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
type ProjectEvidenceSnapshot,
|
|
14
|
+
reflectedRoutesFromEvidence,
|
|
15
|
+
snapshotProjectEvidence,
|
|
16
|
+
} from "@nifrajs/core/evidence"
|
|
17
|
+
import type { ReflectedRoute } from "@nifrajs/core/reflection"
|
|
13
18
|
import { Glob } from "bun"
|
|
19
|
+
import { BACKEND_APP_FILE, CONFIG_FILE, FRAMEWORK_FILE } from "./app-files.ts"
|
|
14
20
|
import { digestRoute } from "./contracts.ts"
|
|
21
|
+
import { codeUnitOrder } from "./internal/code-unit-order.ts"
|
|
15
22
|
|
|
16
23
|
export type WorkGraphNodeKind =
|
|
17
24
|
| "route"
|
|
@@ -52,6 +59,8 @@ export interface WorkGraphSourceFile {
|
|
|
52
59
|
|
|
53
60
|
export interface WorkGraphBuildInput {
|
|
54
61
|
readonly source: unknown
|
|
62
|
+
/** Reuse a canonical route-evidence pass when the caller already has one. */
|
|
63
|
+
readonly evidence?: ProjectEvidenceSnapshot
|
|
55
64
|
readonly files?: readonly WorkGraphSourceFile[]
|
|
56
65
|
readonly freshness?: BuildFreshness
|
|
57
66
|
}
|
|
@@ -126,8 +135,11 @@ export interface ProjectWorkGraphResult {
|
|
|
126
135
|
readonly evidence: EvidenceBundle
|
|
127
136
|
}
|
|
128
137
|
|
|
129
|
-
|
|
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}")
|
|
130
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)\//
|
|
131
143
|
const MANIFEST_NAMES = new Set([
|
|
132
144
|
"server-manifest.ts",
|
|
133
145
|
"nifra-manifest.json",
|
|
@@ -169,13 +181,13 @@ export function evaluateBuildFreshness(input: {
|
|
|
169
181
|
|
|
170
182
|
export async function inspectBuildFreshness(cwd: string): Promise<BuildFreshness> {
|
|
171
183
|
const sourcePaths: string[] = []
|
|
172
|
-
for (const name of [
|
|
184
|
+
for (const name of [BACKEND_APP_FILE, FRAMEWORK_FILE, CONFIG_FILE]) {
|
|
173
185
|
const path = resolve(cwd, name)
|
|
174
186
|
if (existsSync(path)) sourcePaths.push(path)
|
|
175
187
|
}
|
|
176
188
|
for await (const rawPath of SOURCE_GLOB.scan({ cwd, dot: false })) {
|
|
177
189
|
const path = rawPath.replaceAll("\\", "/")
|
|
178
|
-
if (!IGNORED.test(path) &&
|
|
190
|
+
if (!IGNORED.test(path) && APP_SOURCE_DIR.test(path)) sourcePaths.push(resolve(cwd, path))
|
|
179
191
|
}
|
|
180
192
|
const sourceTimes = await fileTimes(sourcePaths)
|
|
181
193
|
for (const buildDirName of ["dist", "build"]) {
|
|
@@ -208,8 +220,8 @@ export async function collectProjectWorkGraph(
|
|
|
208
220
|
): Promise<ProjectWorkGraphResult> {
|
|
209
221
|
const freshness = await inspectBuildFreshness(cwd)
|
|
210
222
|
if (!freshness.ok) throw new StaleBuildError(freshness)
|
|
211
|
-
const backendPath = resolve(cwd,
|
|
212
|
-
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}`)
|
|
213
225
|
const loadedValue: unknown = await import(`${backendPath}?nifra-work-graph=${Date.now()}`)
|
|
214
226
|
const loaded = recordOf(loadedValue)
|
|
215
227
|
if (loaded?.backend === undefined)
|
|
@@ -224,7 +236,8 @@ export async function buildProjectWorkGraph(
|
|
|
224
236
|
): Promise<ProjectWorkGraphResult> {
|
|
225
237
|
const freshness = input.freshness ?? { ok: true }
|
|
226
238
|
if (!freshness.ok) throw new StaleBuildError(freshness)
|
|
227
|
-
const
|
|
239
|
+
const projectEvidence = input.evidence ?? snapshotProjectEvidence(input.source)
|
|
240
|
+
const graph = await buildWorkGraph({ ...input, evidence: projectEvidence })
|
|
228
241
|
const impact = queryImpact(graph, options.changedFiles ?? [])
|
|
229
242
|
const plan = planProofs(graph, impact, options.minLevel ?? 1)
|
|
230
243
|
const evidence = createEvidenceBundle(graph, impact, plan)
|
|
@@ -232,7 +245,9 @@ export async function buildProjectWorkGraph(
|
|
|
232
245
|
}
|
|
233
246
|
|
|
234
247
|
export async function buildWorkGraph(input: WorkGraphBuildInput): Promise<WorkGraph> {
|
|
235
|
-
const routes =
|
|
248
|
+
const routes = reflectedRoutesFromEvidence(
|
|
249
|
+
input.evidence ?? snapshotProjectEvidence(input.source),
|
|
250
|
+
)
|
|
236
251
|
const files = input.files ?? []
|
|
237
252
|
const nodes = new Map<string, WorkGraphNode>()
|
|
238
253
|
const edges: WorkGraphEdge[] = []
|
|
@@ -280,8 +295,8 @@ export async function buildWorkGraph(input: WorkGraphBuildInput): Promise<WorkGr
|
|
|
280
295
|
})
|
|
281
296
|
for (const file of routeFiles)
|
|
282
297
|
addEdge({ from: `file:${file}`, to: routeId, relation: "implements" })
|
|
283
|
-
if (routeFiles.length === 0 && sourceFiles.some((file) => file.path ===
|
|
284
|
-
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" })
|
|
285
300
|
for (const [name, schema] of Object.entries(route.schema ?? {})) {
|
|
286
301
|
if (schema === undefined || name === "errors") continue
|
|
287
302
|
const schemaId = `schema:${routeKey}:${name}`
|
|
@@ -324,9 +339,9 @@ export async function buildWorkGraph(input: WorkGraphBuildInput): Promise<WorkGr
|
|
|
324
339
|
for (const file of manifestFiles)
|
|
325
340
|
addEdge({ from: `manifest:${file.path}`, to: routeId, relation: "describes" })
|
|
326
341
|
}
|
|
327
|
-
const sortedNodes = [...nodes.values()].sort((a, b) => a.id
|
|
342
|
+
const sortedNodes = [...nodes.values()].sort((a, b) => codeUnitOrder(a.id, b.id))
|
|
328
343
|
const sortedEdges = edges.sort((a, b) =>
|
|
329
|
-
`${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}`),
|
|
330
345
|
)
|
|
331
346
|
const digest = await digestJson({ nodes: sortedNodes, edges: sortedEdges })
|
|
332
347
|
return Object.freeze({
|
|
@@ -343,7 +358,9 @@ export function queryImpact(graph: WorkGraph, changedFiles: readonly string[]):
|
|
|
343
358
|
...new Set(changedFiles.map((file) => file.replace(/^\.\//, "").replaceAll("\\", "/"))),
|
|
344
359
|
]
|
|
345
360
|
const seeds = new Set<string>()
|
|
361
|
+
const unmodeled: string[] = []
|
|
346
362
|
for (const file of normalized) {
|
|
363
|
+
let seeded = false
|
|
347
364
|
for (const node of graph.nodes) {
|
|
348
365
|
if (
|
|
349
366
|
(node.kind === "file" || node.kind === "test" || node.kind === "manifest") &&
|
|
@@ -351,11 +368,18 @@ export function queryImpact(graph: WorkGraph, changedFiles: readonly string[]):
|
|
|
351
368
|
node.id === `test:${file}` ||
|
|
352
369
|
node.id === `manifest:${file}` ||
|
|
353
370
|
node.files.includes(file))
|
|
354
|
-
)
|
|
371
|
+
) {
|
|
355
372
|
seeds.add(node.id)
|
|
373
|
+
seeded = true
|
|
374
|
+
}
|
|
356
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)
|
|
357
379
|
}
|
|
358
|
-
|
|
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)))
|
|
359
383
|
for (const node of graph.nodes) if (node.kind === "route") seeds.add(node.id)
|
|
360
384
|
const impacted = new Set(seeds)
|
|
361
385
|
const queue = [...seeds]
|
|
@@ -434,7 +458,7 @@ export function createEvidenceBundle(
|
|
|
434
458
|
plan: ProofPlan,
|
|
435
459
|
proofs: readonly ProofEvidence[] = [],
|
|
436
460
|
): EvidenceBundle {
|
|
437
|
-
const evidence = [...proofs].sort((a, b) => a.id
|
|
461
|
+
const evidence = [...proofs].sort((a, b) => codeUnitOrder(a.id, b.id))
|
|
438
462
|
// Levels are not cumulative (assure does not typecheck), so every planned step needs its own
|
|
439
463
|
// passing proof; a higher-level pass never subsumes a lower one.
|
|
440
464
|
const done =
|
|
@@ -571,7 +595,7 @@ function filesForRoute(
|
|
|
571
595
|
const matches = files
|
|
572
596
|
.filter(
|
|
573
597
|
(file) =>
|
|
574
|
-
file.path ===
|
|
598
|
+
file.path === BACKEND_APP_FILE ||
|
|
575
599
|
(file.path.startsWith("routes/") && file.content.includes(route.path)),
|
|
576
600
|
)
|
|
577
601
|
.map((file) => file.path)
|