@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
package/src/check.ts
CHANGED
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
19
|
import { existsSync, readFileSync } from "node:fs"
|
|
20
|
-
import { dirname, isAbsolute, join } from "node:path"
|
|
20
|
+
import { dirname, isAbsolute, join, relative } from "node:path"
|
|
21
|
+
import { BACKEND_APP_FILE } from "./app-files.ts"
|
|
21
22
|
import {
|
|
22
23
|
type CheckAssuranceContext,
|
|
23
24
|
type CheckConfig,
|
|
@@ -29,7 +30,7 @@ import {
|
|
|
29
30
|
import { checkContractsLock, DEFAULT_CONTRACTS_LOCK } from "./contracts.ts"
|
|
30
31
|
import { type Diagnostic, normalizeSeverity, toSarifLog } from "./diagnostics.ts"
|
|
31
32
|
import { createSourceFacts } from "./internal/source-facts.ts"
|
|
32
|
-
import {
|
|
33
|
+
import { loadProjectTypeScript, type TypeScriptApi } from "./internal/typescript-import.ts"
|
|
33
34
|
// Type-only: `pipeline-report.ts` imports this module's source scanners, so a value import here would
|
|
34
35
|
// close a cycle. Doctor is what actually runs the collector (see the `pipeline` rule below).
|
|
35
36
|
import type { ContractCheckFacts, ProjectFactsSeed } from "./project-facts.ts"
|
|
@@ -50,6 +51,7 @@ export type {
|
|
|
50
51
|
|
|
51
52
|
import {
|
|
52
53
|
createProjectSqlImports,
|
|
54
|
+
isBrowserSource,
|
|
53
55
|
type ModuleReader,
|
|
54
56
|
type ModuleResolver,
|
|
55
57
|
resolveServerOnlyChains,
|
|
@@ -69,7 +71,6 @@ import {
|
|
|
69
71
|
|
|
70
72
|
export * from "./check-scan.ts"
|
|
71
73
|
|
|
72
|
-
const ROUTE_FILE = /(^|\/)routes\//
|
|
73
74
|
interface TypecheckResult {
|
|
74
75
|
readonly ran: boolean
|
|
75
76
|
readonly ok: boolean
|
|
@@ -104,6 +105,9 @@ async function typecheck(cwd: string, signal?: AbortSignal): Promise<TypecheckRe
|
|
|
104
105
|
const tsconfig = join(cwd, "tsconfig.json")
|
|
105
106
|
if (!(await Bun.file(tsconfig).exists()))
|
|
106
107
|
return { ran: false, ok: true, note: "no tsconfig.json" }
|
|
108
|
+
// Routes import their generated `./+types` modules; bring them up to date before tsc reads them.
|
|
109
|
+
const { refreshRouteTypes } = await import("./route-types.ts")
|
|
110
|
+
refreshRouteTypes(cwd, () => {})
|
|
107
111
|
const tscBin = resolveTscBin(cwd)
|
|
108
112
|
if (tscBin === undefined) {
|
|
109
113
|
return {
|
|
@@ -114,7 +118,7 @@ async function typecheck(cwd: string, signal?: AbortSignal): Promise<TypecheckRe
|
|
|
114
118
|
}
|
|
115
119
|
}
|
|
116
120
|
if (signal?.aborted) return { ran: true, ok: false, cancelled: true, output: "cancelled" }
|
|
117
|
-
const proc = Bun.spawn([
|
|
121
|
+
const proc = Bun.spawn([process.execPath, tscBin, "--noEmit", "-p", tsconfig], {
|
|
118
122
|
cwd,
|
|
119
123
|
stdout: "pipe",
|
|
120
124
|
stderr: "pipe",
|
|
@@ -236,7 +240,7 @@ interface ProjectScan {
|
|
|
236
240
|
}
|
|
237
241
|
|
|
238
242
|
async function collectContractFacts(cwd: string): Promise<ContractCheckFacts> {
|
|
239
|
-
const hasBackend = existsSync(join(cwd,
|
|
243
|
+
const hasBackend = existsSync(join(cwd, BACKEND_APP_FILE))
|
|
240
244
|
const hasLock = existsSync(join(cwd, DEFAULT_CONTRACTS_LOCK))
|
|
241
245
|
if (!hasBackend && !hasLock) return { present: false, vacuous: false, diagnostics: [] }
|
|
242
246
|
try {
|
|
@@ -272,17 +276,13 @@ async function buildProjectScan(
|
|
|
272
276
|
const serverImports: TransitiveServerImportFinding[] = []
|
|
273
277
|
const responseRoutes: SourceFinding[] = []
|
|
274
278
|
const interpolatedSql: SourceFinding[] = []
|
|
275
|
-
const
|
|
279
|
+
const browserModules: Array<{ rel: string; content: string }> = []
|
|
276
280
|
const sourceFiles: Array<{ file: string; content: string }> = []
|
|
277
281
|
const {
|
|
278
282
|
config: checkConfig,
|
|
279
283
|
error: checkConfigError,
|
|
280
284
|
warnings: checkConfigWarnings,
|
|
281
285
|
} = await loadCheckConfig(cwd)
|
|
282
|
-
const sqlCompiler = await (opts.loadTypeScript ?? (() => importProjectTypeScript(cwd)))()
|
|
283
|
-
const sourceFacts = sqlCompiler === undefined ? undefined : createSourceFacts(sqlCompiler)
|
|
284
|
-
const sqlImports = sqlCompiler === undefined ? undefined : createProjectSqlImports(cwd)
|
|
285
|
-
|
|
286
286
|
const [typecheckResult, _, doctor, manifestDrift, contracts] = await Promise.all([
|
|
287
287
|
opts.lintsOnly
|
|
288
288
|
? Promise.resolve<TypecheckResult>({ ran: false, ok: true, note: "lints-only mode" })
|
|
@@ -291,66 +291,89 @@ async function buildProjectScan(
|
|
|
291
291
|
sourceFiles.push({ file: rel, content })
|
|
292
292
|
fetches.push(...scanFetchText(rel, content, checkConfig.externalMounts))
|
|
293
293
|
streams.push(...scanStreamText(rel, content, checkConfig.externalMounts))
|
|
294
|
-
staticRoutes.push(...scanStaticRouteText(rel, content, sourceFacts))
|
|
295
294
|
untypedClients.push(...scanUntypedClient(rel, content))
|
|
296
295
|
removedImports.push(...scanRemovedImports(rel, content))
|
|
297
|
-
if (
|
|
298
|
-
responseRoutes.push(...scanResponseRoutes(rel, content, sourceFacts))
|
|
299
|
-
if (sqlCompiler !== undefined)
|
|
300
|
-
interpolatedSql.push(...scanInterpolatedSql(rel, content, sqlCompiler, sqlImports))
|
|
296
|
+
if (isBrowserSource(rel)) browserModules.push({ rel, content })
|
|
301
297
|
}),
|
|
302
298
|
import("./doctor.ts").then((m) => m.collectDoctorResult(cwd)),
|
|
303
299
|
scanServerManifestDrift(cwd),
|
|
304
300
|
collectContractFacts(cwd),
|
|
305
301
|
])
|
|
306
302
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
303
|
+
// TypeScript 7's unstable API materializes source files through one project session. Build the
|
|
304
|
+
// source index first so every syntax-backed scanner (including the independent rule registry)
|
|
305
|
+
// shares that session instead of spawning one compiler process per rule.
|
|
306
|
+
const source = sourceIndex(sourceFiles)
|
|
307
|
+
const loadedTypeScript = await loadProjectTypeScript(cwd, opts.loadTypeScript, source)
|
|
308
|
+
try {
|
|
309
|
+
const sqlCompiler = loadedTypeScript.compiler
|
|
310
|
+
const sourceFacts = sqlCompiler === undefined ? undefined : createSourceFacts(sqlCompiler)
|
|
311
|
+
const sqlImports = sqlCompiler === undefined ? undefined : createProjectSqlImports(cwd)
|
|
312
|
+
for (const { file, content } of sourceFiles) {
|
|
313
|
+
staticRoutes.push(...scanStaticRouteText(file, content, sourceFacts))
|
|
314
|
+
responseRoutes.push(...scanResponseRoutes(file, content, sourceFacts))
|
|
315
|
+
if (sqlCompiler !== undefined)
|
|
316
|
+
interpolatedSql.push(...scanInterpolatedSql(file, content, sqlCompiler, sqlImports))
|
|
313
317
|
}
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
318
|
+
|
|
319
|
+
// Resolved modules stay project-relative, as the scanned files are: the zone of a path is read
|
|
320
|
+
// from its folders, and a checkout under a folder named `backend/` must not make it all backend.
|
|
321
|
+
const resolveModule: ModuleResolver = (fromFile, specifier) => {
|
|
322
|
+
try {
|
|
323
|
+
const fromAbs = isAbsolute(fromFile) ? fromFile : join(cwd, fromFile)
|
|
324
|
+
const resolved = Bun.resolveSync(specifier, dirname(fromAbs))
|
|
325
|
+
const rel = relative(cwd, resolved).replaceAll("\\", "/")
|
|
326
|
+
return rel.startsWith("../") || isAbsolute(rel) ? resolved : rel
|
|
327
|
+
} catch {
|
|
328
|
+
return undefined
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
const readModule: ModuleReader = (path) => {
|
|
332
|
+
try {
|
|
333
|
+
return readFileSync(isAbsolute(path) ? path : join(cwd, path), "utf8")
|
|
334
|
+
} catch {
|
|
335
|
+
return undefined
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
for (const { rel, content } of browserModules) {
|
|
339
|
+
serverImports.push(
|
|
340
|
+
...resolveServerOnlyChains(rel, content, resolveModule, readModule, sourceFacts),
|
|
341
|
+
)
|
|
320
342
|
}
|
|
321
|
-
}
|
|
322
|
-
for (const { rel, content } of routeModules) {
|
|
323
|
-
serverImports.push(
|
|
324
|
-
...resolveServerOnlyChains(rel, content, resolveModule, readModule, sourceFacts),
|
|
325
|
-
)
|
|
326
|
-
}
|
|
327
343
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
344
|
+
const facts: ProjectFactsSeed = {
|
|
345
|
+
source,
|
|
346
|
+
routes: staticRoutes,
|
|
347
|
+
importGraph: serverImports,
|
|
348
|
+
packages: { doctor, manifestDrift },
|
|
349
|
+
...(doctor.pipeline === undefined ? {} : { pipeline: doctor.pipeline }),
|
|
350
|
+
policies: { checkConfig, rulePacks: [] },
|
|
351
|
+
check: {
|
|
352
|
+
typecheck: typecheckResult,
|
|
353
|
+
sqlCompilerAvailable: sqlCompiler !== undefined,
|
|
354
|
+
...(loadedTypeScript.unsupported === undefined
|
|
355
|
+
? {}
|
|
356
|
+
: { unsupportedTypeScriptVersion: loadedTypeScript.unsupported.version }),
|
|
357
|
+
...(loadedTypeScript.session === undefined
|
|
358
|
+
? {}
|
|
359
|
+
: { typescriptSession: loadedTypeScript.session }),
|
|
360
|
+
...(checkConfigError === undefined ? {} : { checkConfigError }),
|
|
361
|
+
checkConfigWarnings,
|
|
362
|
+
contracts,
|
|
363
|
+
},
|
|
364
|
+
sourceFindings: {
|
|
365
|
+
fetches,
|
|
366
|
+
streams,
|
|
367
|
+
untypedClients,
|
|
368
|
+
removedImports,
|
|
369
|
+
responseRoutes,
|
|
370
|
+
interpolatedSql,
|
|
371
|
+
},
|
|
372
|
+
}
|
|
373
|
+
return { facts }
|
|
374
|
+
} catch (error) {
|
|
375
|
+
await loadedTypeScript.session?.close()
|
|
376
|
+
throw error
|
|
354
377
|
}
|
|
355
378
|
}
|
|
356
379
|
|
|
@@ -362,7 +385,11 @@ export async function collectCheckResult(
|
|
|
362
385
|
opts: CheckCollectionOptions = {},
|
|
363
386
|
): Promise<CheckResult> {
|
|
364
387
|
const scan = await buildProjectScan(cwd, opts)
|
|
365
|
-
|
|
388
|
+
try {
|
|
389
|
+
return await collectCheckDiagnostics(cwd, scan, opts)
|
|
390
|
+
} finally {
|
|
391
|
+
await scan.facts.check.typescriptSession?.close()
|
|
392
|
+
}
|
|
366
393
|
}
|
|
367
394
|
|
|
368
395
|
/** The named rule sections of the human report, in print order. A rule absent from this list is NOT
|
|
@@ -372,7 +399,7 @@ const REPORT_SECTIONS = [
|
|
|
372
399
|
["typecheck", "typecheck"],
|
|
373
400
|
["typed-client", "hand-rolled fetch()/EventSource/WebSocket to your own API"],
|
|
374
401
|
["untyped-client", 'client("…") missing its <typeof app> type argument'],
|
|
375
|
-
["server-only-import", "
|
|
402
|
+
["server-only-import", "backend code in browser code"],
|
|
376
403
|
["interpolated-sql", "SQL built by interpolating a value into the statement"],
|
|
377
404
|
["response-route", "route returns a raw Response (typed client → data: never)"],
|
|
378
405
|
["undeclared-dependency", "undeclared dependency in package.json"],
|
|
@@ -416,6 +443,14 @@ export function renderCheckReport(result: CheckResult): string[] {
|
|
|
416
443
|
`• intentional external mounts (not typed-client checked): ${result.externalMounts.join(", ")}`,
|
|
417
444
|
)
|
|
418
445
|
}
|
|
446
|
+
for (const gap of result.knownGaps ?? []) {
|
|
447
|
+
lines.push(`• known gap, not capability-analyzed: ${gap.path} - ${gap.reason}`)
|
|
448
|
+
}
|
|
449
|
+
const deduplicated = result.identityPreflight?.deduplicated ?? []
|
|
450
|
+
if (deduplicated.length > 0) {
|
|
451
|
+
const packages = deduplicated.map((finding) => finding.package).join(", ")
|
|
452
|
+
lines.push(`• identity-sensitive duplicate installs handled by singleCopy: ${packages}`)
|
|
453
|
+
}
|
|
419
454
|
if (result.ruleOverrides !== undefined) {
|
|
420
455
|
const active = Object.entries(result.ruleOverrides).map(([rule, override]) => {
|
|
421
456
|
const parts: string[] = []
|
|
@@ -542,7 +577,7 @@ export async function runCheck(
|
|
|
542
577
|
|
|
543
578
|
console.log(renderCheckReport(result).join("\n"))
|
|
544
579
|
// Discoverability nudge: a project with no `.mcp.json` hasn't wired its nifra MCP for coding agents.
|
|
545
|
-
// `nifra init-agents` writes it (+ .cursor/mcp.json +
|
|
580
|
+
// `nifra init-agents` writes it (+ .cursor/mcp.json + each agent's pointer to AGENTS.md), no-clobber. A non-fatal
|
|
546
581
|
// one-line tip in the human report only (the `--json` path returns above, unaffected).
|
|
547
582
|
if (!existsSync(join(cwd, ".mcp.json"))) {
|
|
548
583
|
console.log(
|