@nifrajs/cli 4.0.2 → 5.1.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 +10 -2
- 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 +9 -2
- package/dist/assure-hydration.js.map +1 -1
- package/dist/assure.d.ts +12 -2
- package/dist/assure.d.ts.map +1 -1
- package/dist/assure.js +59 -8
- package/dist/assure.js.map +1 -1
- package/dist/capabilities-tool.d.ts.map +1 -1
- package/dist/capabilities-tool.js +36 -9
- package/dist/capabilities-tool.js.map +1 -1
- package/dist/check-diagnostics.d.ts +22 -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 +83 -24
- package/dist/check-scan.d.ts.map +1 -1
- package/dist/check-scan.js +1516 -318
- 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 +203 -70
- package/dist/check.js.map +1 -1
- package/dist/cli.d.ts +9 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +215 -50
- package/dist/cli.js.map +1 -1
- package/dist/client-module.d.ts +20 -0
- package/dist/client-module.d.ts.map +1 -0
- package/dist/client-module.js +73 -0
- package/dist/client-module.js.map +1 -0
- package/dist/command-catalog.d.ts +24 -5
- package/dist/command-catalog.d.ts.map +1 -1
- package/dist/command-catalog.js +194 -45
- 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/dev-feed-tool.d.ts +18 -1
- package/dist/dev-feed-tool.d.ts.map +1 -1
- package/dist/dev-feed-tool.js +93 -0
- package/dist/dev-feed-tool.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 +2 -0
- package/dist/fix-recipes.d.ts.map +1 -1
- package/dist/fix-recipes.js +102 -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 +18 -2
- package/dist/init-agents.d.ts.map +1 -1
- package/dist/init-agents.js +20 -13
- package/dist/init-agents.js.map +1 -1
- package/dist/internal/config-paths.d.ts +16 -0
- package/dist/internal/config-paths.d.ts.map +1 -0
- package/dist/internal/config-paths.js +124 -0
- package/dist/internal/config-paths.js.map +1 -0
- package/dist/internal/installed-package.d.ts +4 -0
- package/dist/internal/installed-package.d.ts.map +1 -0
- package/dist/internal/installed-package.js +17 -0
- package/dist/internal/installed-package.js.map +1 -0
- 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 +29 -0
- package/dist/internal/project-specifiers.d.ts.map +1 -0
- package/dist/internal/project-specifiers.js +435 -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 +8 -1
- package/dist/internal/source-facts.d.ts.map +1 -1
- package/dist/internal/source-facts.js +22 -5
- 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 +10 -6
- package/dist/internal/typescript-import.js.map +1 -1
- package/dist/introspect.d.ts +15 -6
- package/dist/introspect.d.ts.map +1 -1
- package/dist/introspect.js +87 -25
- package/dist/introspect.js.map +1 -1
- package/dist/levels-tool.d.ts.map +1 -1
- package/dist/levels-tool.js +98 -23
- package/dist/levels-tool.js.map +1 -1
- package/dist/load.d.ts +33 -10
- package/dist/load.d.ts.map +1 -1
- package/dist/load.js +60 -10
- 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 +8 -23
- package/dist/mcp-context.js.map +1 -1
- package/dist/mcp-delegate.d.ts +2 -2
- package/dist/mcp-delegate.d.ts.map +1 -1
- package/dist/mcp-delegate.js +19 -7
- package/dist/mcp-delegate.js.map +1 -1
- package/dist/mcp-exec.d.ts +13 -4
- package/dist/mcp-exec.d.ts.map +1 -1
- package/dist/mcp-exec.js +56 -14
- package/dist/mcp-exec.js.map +1 -1
- package/dist/mcp-http.js +1 -1
- package/dist/mcp-io.d.ts +30 -0
- package/dist/mcp-io.d.ts.map +1 -1
- package/dist/mcp-io.js +63 -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-path.d.ts +2 -1
- package/dist/mcp-path.d.ts.map +1 -1
- package/dist/mcp-path.js +9 -24
- package/dist/mcp-path.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 +48 -19
- package/dist/mcp.js.map +1 -1
- package/dist/migrate-layout.d.ts +47 -1
- package/dist/migrate-layout.d.ts.map +1 -1
- package/dist/migrate-layout.js +1972 -170
- package/dist/migrate-layout.js.map +1 -1
- package/dist/output-schemas.d.ts +128 -0
- package/dist/output-schemas.d.ts.map +1 -0
- package/dist/output-schemas.js +975 -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/project-path.d.ts +6 -0
- package/dist/project-path.d.ts.map +1 -1
- package/dist/project-path.js +48 -14
- package/dist/project-path.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/release-verification.d.ts +5 -0
- package/dist/release-verification.d.ts.map +1 -1
- package/dist/release-verification.js +14 -0
- package/dist/release-verification.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 +43 -7
- package/dist/review.js.map +1 -1
- package/dist/rules/codes.d.ts +12 -0
- package/dist/rules/codes.d.ts.map +1 -1
- package/dist/rules/codes.js +12 -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 +13 -0
- package/dist/rules/data-guard.d.ts.map +1 -1
- package/dist/rules/data-guard.js +356 -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 +178 -44
- package/dist/rules/legacy.js.map +1 -1
- package/dist/rules/pages.d.ts +50 -0
- package/dist/rules/pages.d.ts.map +1 -1
- package/dist/rules/pages.js +436 -4
- 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 +13 -1
- package/dist/rules/security.d.ts.map +1 -1
- package/dist/rules/security.js +313 -69
- 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 +218 -44
- 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 +290 -24
- package/dist/stylex-migrate.js.map +1 -1
- package/dist/test-tool.d.ts.map +1 -1
- package/dist/test-tool.js +6 -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 +84 -0
- package/dist/upgrade.d.ts.map +1 -1
- package/dist/upgrade.js +498 -78
- package/dist/upgrade.js.map +1 -1
- package/dist/verification-plan.d.ts.map +1 -1
- package/dist/verification-plan.js +16 -2
- 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 +94 -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 +55 -7
- package/docs/llms-full.txt +2043 -222
- package/docs/types.json +1573 -246
- package/package.json +11 -12
- package/src/agent-files.ts +203 -0
- package/src/app-files.ts +34 -4
- package/src/assure-hydration.ts +18 -2
- package/src/assure.ts +88 -10
- package/src/capabilities-tool.ts +47 -9
- package/src/check-diagnostics.ts +75 -9
- package/src/check-scan.ts +1816 -377
- package/src/check.ts +258 -81
- package/src/cli.ts +242 -37
- package/src/client-module.ts +97 -0
- package/src/command-catalog.ts +237 -52
- 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/dev-feed-tool.ts +112 -1
- 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 +116 -2
- package/src/hand-built-manifest.ts +144 -0
- package/src/hooks-report.ts +135 -0
- package/src/init-agents.ts +21 -14
- package/src/internal/config-paths.ts +154 -0
- package/src/internal/installed-package.ts +15 -0
- package/src/internal/nifra-project.ts +191 -0
- package/src/internal/project-specifiers.ts +477 -0
- package/src/internal/script-kind.ts +2 -1
- package/src/internal/source-facts.ts +48 -5
- package/src/internal/typescript-import.ts +15 -6
- package/src/introspect.ts +104 -28
- package/src/levels-tool.ts +124 -29
- package/src/load.ts +107 -17
- package/src/mcp-context.ts +12 -25
- package/src/mcp-delegate.ts +22 -10
- package/src/mcp-exec.ts +68 -18
- package/src/mcp-http.ts +1 -1
- package/src/mcp-io.ts +74 -0
- package/src/mcp-isolate.ts +9 -2
- package/src/mcp-path.ts +8 -22
- 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 +56 -22
- package/src/migrate-layout.ts +2257 -176
- package/src/output-schemas.ts +1240 -0
- package/src/port.ts +3 -2
- package/src/project-facts.ts +17 -3
- package/src/project-path.ts +44 -13
- package/src/recipes/5.0.0.ts +35 -0
- package/src/recipes/index.ts +10 -0
- package/src/release-verification.ts +20 -0
- package/src/replay.ts +14 -3
- package/src/review.ts +44 -10
- package/src/rules/codes.ts +12 -0
- package/src/rules/comment-markers.ts +57 -21
- package/src/rules/contract-visibility.ts +383 -0
- package/src/rules/data-guard.ts +391 -42
- package/src/rules/layout.ts +22 -0
- package/src/rules/legacy.ts +206 -52
- package/src/rules/pages.ts +481 -4
- package/src/rules/routes.ts +124 -16
- package/src/rules/secrets.ts +2 -2
- package/src/rules/security.ts +391 -72
- package/src/rules/zones.ts +232 -42
- package/src/scaffold.ts +6 -4
- package/src/sdk.ts +14 -5
- package/src/stylex-migrate.ts +251 -24
- package/src/test-tool.ts +12 -3
- package/src/typecheck-coverage.ts +134 -0
- package/src/upgrade.ts +576 -72
- package/src/verification-plan.ts +33 -2
- package/src/version-drift.ts +118 -0
- package/src/web-app-options.ts +2 -2
- package/src/work-graph.ts +17 -12
package/src/verification-plan.ts
CHANGED
|
@@ -37,6 +37,11 @@ const GATES = Object.freeze([
|
|
|
37
37
|
"Run `bun run typecheck` and fix the reported TypeScript errors.",
|
|
38
38
|
),
|
|
39
39
|
gate("tests", [["run", "test"]], "Run `bun run test` and fix the first failing test."),
|
|
40
|
+
gate(
|
|
41
|
+
"rest-tests",
|
|
42
|
+
[["run", "test:rest"]],
|
|
43
|
+
"Run `bun run test:rest` and fix the first failing test.",
|
|
44
|
+
),
|
|
40
45
|
gate(
|
|
41
46
|
"docs",
|
|
42
47
|
[["run", "check:docs"]],
|
|
@@ -178,12 +183,32 @@ const GATES = Object.freeze([
|
|
|
178
183
|
[["run", "check:verification-parity"]],
|
|
179
184
|
"Run `bun run check:verification-parity` and reconcile the release plan with CI.",
|
|
180
185
|
),
|
|
186
|
+
gate(
|
|
187
|
+
"server-components-contracts",
|
|
188
|
+
[["run", "check:server-components:contracts"]],
|
|
189
|
+
"Run `bun run check:server-components:contracts` and fix the component admission, transport or lifecycle regression.",
|
|
190
|
+
),
|
|
191
|
+
gate(
|
|
192
|
+
"server-components",
|
|
193
|
+
[
|
|
194
|
+
["run", "check:server-components"],
|
|
195
|
+
["run", "check:server-components:consumers"],
|
|
196
|
+
],
|
|
197
|
+
"Run the server-components matrix and packaged-consumer commands; every adapter and required row must pass.",
|
|
198
|
+
),
|
|
199
|
+
gate(
|
|
200
|
+
"server-components-performance",
|
|
201
|
+
[["run", "check:server-components:performance"]],
|
|
202
|
+
"Run the five-run component performance comparison and investigate the measured regression.",
|
|
203
|
+
{ workflowRequired: false },
|
|
204
|
+
),
|
|
181
205
|
])
|
|
182
206
|
|
|
183
207
|
const DEFAULT_PLAN = Object.freeze([
|
|
184
208
|
"lint",
|
|
185
209
|
"typecheck",
|
|
186
210
|
"tests",
|
|
211
|
+
"server-components-contracts",
|
|
187
212
|
"docs",
|
|
188
213
|
"api-corpus",
|
|
189
214
|
"cards-corpus",
|
|
@@ -196,14 +221,17 @@ const DEFAULT_PLAN = Object.freeze([
|
|
|
196
221
|
"changesets",
|
|
197
222
|
] as const)
|
|
198
223
|
|
|
224
|
+
// `coverage` fails on any failing test, so it is the release plan's run of the library suites;
|
|
225
|
+
// `rest-tests` runs the suites it leaves out, and `tests` would only repeat the two.
|
|
199
226
|
const RELEASE_PLAN = Object.freeze([
|
|
200
227
|
"build",
|
|
201
228
|
"lint",
|
|
202
229
|
"typecheck",
|
|
203
|
-
"tests",
|
|
204
|
-
"cli-isolation",
|
|
205
230
|
"coverage",
|
|
231
|
+
"rest-tests",
|
|
232
|
+
"cli-isolation",
|
|
206
233
|
"corpus",
|
|
234
|
+
"sitemap",
|
|
207
235
|
"docs",
|
|
208
236
|
"public-boundary",
|
|
209
237
|
"public-manifest",
|
|
@@ -222,6 +250,9 @@ const RELEASE_PLAN = Object.freeze([
|
|
|
222
250
|
"pipeline-parity",
|
|
223
251
|
"leak-matrix",
|
|
224
252
|
"verification-parity",
|
|
253
|
+
"server-components",
|
|
254
|
+
"server-components-performance",
|
|
255
|
+
"server-components-contracts",
|
|
225
256
|
"changesets",
|
|
226
257
|
] as const)
|
|
227
258
|
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs"
|
|
2
|
+
import { join, sep } from "node:path"
|
|
3
|
+
import {
|
|
4
|
+
compareSemverSpec,
|
|
5
|
+
groupDeclaredNames,
|
|
6
|
+
groupPinVersions,
|
|
7
|
+
installedGroupPackages,
|
|
8
|
+
isFixedGroup,
|
|
9
|
+
type LinkedGroupInstall,
|
|
10
|
+
} from "./upgrade.ts"
|
|
11
|
+
|
|
12
|
+
/** The fixed-group packages the package installed at `dir` depends on. */
|
|
13
|
+
function groupDependenciesAt(dir: string): string[] {
|
|
14
|
+
try {
|
|
15
|
+
const manifest: unknown = JSON.parse(readFileSync(join(dir, "package.json"), "utf8"))
|
|
16
|
+
if (typeof manifest !== "object" || manifest === null) return []
|
|
17
|
+
return ["dependencies", "peerDependencies", "optionalDependencies"].flatMap((field) => {
|
|
18
|
+
const deps: unknown = Reflect.get(manifest, field)
|
|
19
|
+
return typeof deps === "object" && deps !== null ? Object.keys(deps).filter(isFixedGroup) : []
|
|
20
|
+
})
|
|
21
|
+
} catch {
|
|
22
|
+
return []
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** One version of the fixed release group, and where the workspace carries it. */
|
|
27
|
+
export interface GroupVersion {
|
|
28
|
+
readonly version: string
|
|
29
|
+
readonly sources: readonly string[]
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* More than one version of the fixed release group (`@nifrajs/*`, `nifra`, `create-nifra`) in one
|
|
34
|
+
* workspace. Read only: package.json pins, installed packages (followed to their real location, so a
|
|
35
|
+
* linked repo reports its own version) and the running CLI. Nothing is spawned.
|
|
36
|
+
*/
|
|
37
|
+
export interface VersionDrift {
|
|
38
|
+
/** Oldest first. */
|
|
39
|
+
readonly versions: readonly GroupVersion[]
|
|
40
|
+
readonly highest: string
|
|
41
|
+
/** `nifra upgrade` edits the workspace only; these are listed, never edited. */
|
|
42
|
+
readonly linkedOutside: readonly LinkedGroupInstall[]
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function collectVersionDrift(cwd: string, cliVersion?: string): VersionDrift | undefined {
|
|
46
|
+
const sources = new Map<string, string[]>()
|
|
47
|
+
const add = (version: string, source: string): void => {
|
|
48
|
+
const list = sources.get(version) ?? []
|
|
49
|
+
list.push(source)
|
|
50
|
+
sources.set(version, list)
|
|
51
|
+
}
|
|
52
|
+
for (const [version, files] of groupPinVersions(cwd)) {
|
|
53
|
+
for (const file of files) add(version, `pinned in ${file}`)
|
|
54
|
+
}
|
|
55
|
+
const linkedOutside: LinkedGroupInstall[] = []
|
|
56
|
+
const installs = installedGroupPackages(cwd)
|
|
57
|
+
// An install nothing declares, such as one an older install left behind, loads nowhere, and no
|
|
58
|
+
// upgrade re-pins it: counting it would report drift that never clears.
|
|
59
|
+
const declared = new Set(groupDeclaredNames(cwd))
|
|
60
|
+
for (const { path } of installs) for (const name of groupDependenciesAt(path)) declared.add(name)
|
|
61
|
+
for (const { package: name, path, version, inside } of installs) {
|
|
62
|
+
if (!declared.has(name)) continue
|
|
63
|
+
add(version, `installed ${name}${inside ? "" : ` (linked from ${path})`}`)
|
|
64
|
+
if (!inside) linkedOutside.push({ package: name, path, version })
|
|
65
|
+
}
|
|
66
|
+
if (cliVersion !== undefined) add(cliVersion, "the running nifra CLI")
|
|
67
|
+
if (sources.size < 2) return undefined
|
|
68
|
+
const versions = [...sources]
|
|
69
|
+
.sort(([a], [b]) => compareSemverSpec(a, b))
|
|
70
|
+
.map(([version, list]) => ({ version, sources: list }))
|
|
71
|
+
return {
|
|
72
|
+
versions,
|
|
73
|
+
highest: versions[versions.length - 1]!.version,
|
|
74
|
+
linkedOutside,
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** The install a package belongs to: the folder above its last `node_modules`, or the package itself. */
|
|
79
|
+
const installRoot = (path: string): string => {
|
|
80
|
+
const parts = path.split(sep)
|
|
81
|
+
const last = parts.lastIndexOf("node_modules")
|
|
82
|
+
return last <= 0 ? path : parts.slice(0, last).join(sep)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** Linked installs, one phrase per install and version: a linked repository brings its whole group. */
|
|
86
|
+
function linkedGroups(installs: readonly LinkedGroupInstall[]): string[] {
|
|
87
|
+
const groups = new Map<string, LinkedGroupInstall[]>()
|
|
88
|
+
for (const install of installs) {
|
|
89
|
+
const key = `${installRoot(install.path)}\0${install.version}`
|
|
90
|
+
groups.set(key, [...(groups.get(key) ?? []), install])
|
|
91
|
+
}
|
|
92
|
+
return [...groups.values()].map((group) => {
|
|
93
|
+
const [first] = group
|
|
94
|
+
if (first === undefined) return ""
|
|
95
|
+
if (group.length === 1) return `${first.package} ${first.version} at ${first.path}`
|
|
96
|
+
const names = group.map((install) => install.package).sort()
|
|
97
|
+
const listed =
|
|
98
|
+
names.length > 3
|
|
99
|
+
? `${names.slice(0, 3).join(", ")} and ${names.length - 3} more`
|
|
100
|
+
: names.join(", ")
|
|
101
|
+
return `${group.length} packages at ${first.version} under ${installRoot(first.path)} (${listed})`
|
|
102
|
+
})
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/** The advisory both `nifra doctor` and `nifra check` print. */
|
|
106
|
+
export function versionDriftMessage(drift: VersionDrift): string {
|
|
107
|
+
const listed = drift.versions
|
|
108
|
+
.map(
|
|
109
|
+
({ version, sources }) =>
|
|
110
|
+
`${version} (${sources.slice(0, 3).join("; ")}${sources.length > 3 ? `; and ${sources.length - 3} more` : ""})`,
|
|
111
|
+
)
|
|
112
|
+
.join(", ")
|
|
113
|
+
const linked =
|
|
114
|
+
drift.linkedOutside.length === 0
|
|
115
|
+
? ""
|
|
116
|
+
: ` It does not edit ${linkedGroups(drift.linkedOutside).join(", ")}, linked from outside the workspace root; upgrade that repository on its own.`
|
|
117
|
+
return `mixed nifra versions in this workspace: ${listed}. Run \`nifra upgrade ${drift.highest}\` (it runs each release's migration steps, then re-pins).${linked}`
|
|
118
|
+
}
|
package/src/web-app-options.ts
CHANGED
|
@@ -11,7 +11,7 @@ import { FRAMEWORK_WEB_OPTIONS, type FrameworkWebOption, type NifraFramework } f
|
|
|
11
11
|
|
|
12
12
|
type FrameworkWebAppOptions = Pick<
|
|
13
13
|
CreateWebAppOptions,
|
|
14
|
-
"use" | "api" | "apiPrefix" | "apiStrip" | "mounts" | "csp" | "nonce"
|
|
14
|
+
"use" | "api" | "apiPrefix" | "apiStrip" | "mounts" | "csp" | "nonce" | "serverComponents"
|
|
15
15
|
>
|
|
16
16
|
|
|
17
17
|
/** `use`, the backend as `api`, and every forwarded framework field the config sets. */
|
|
@@ -39,7 +39,7 @@ export function frameworkMountPaths(fw: NifraFramework, hasBackend: boolean): st
|
|
|
39
39
|
for (const mount of fw.mounts ?? []) {
|
|
40
40
|
if (typeof mount?.path === "string") paths.push(mount.path)
|
|
41
41
|
}
|
|
42
|
-
const apiPrefix = fw.apiPrefix ?? "
|
|
42
|
+
const apiPrefix = fw.apiPrefix ?? ""
|
|
43
43
|
if (hasBackend && apiPrefix !== "") paths.push(apiPrefix)
|
|
44
44
|
return paths
|
|
45
45
|
}
|
package/src/work-graph.ts
CHANGED
|
@@ -251,16 +251,15 @@ export async function buildWorkGraph(input: WorkGraphBuildInput): Promise<WorkGr
|
|
|
251
251
|
const files = input.files ?? []
|
|
252
252
|
const nodes = new Map<string, WorkGraphNode>()
|
|
253
253
|
const edges: WorkGraphEdge[] = []
|
|
254
|
+
const edgeKeys = new Set<string>()
|
|
254
255
|
const addNode = (node: WorkGraphNode): void => {
|
|
255
256
|
if (!nodes.has(node.id)) nodes.set(node.id, node)
|
|
256
257
|
}
|
|
257
258
|
const addEdge = (edge: WorkGraphEdge): void => {
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
)
|
|
263
|
-
edges.push(edge)
|
|
259
|
+
const key = `${edge.from}\n${edge.to}\n${edge.relation}`
|
|
260
|
+
if (edgeKeys.has(key)) return
|
|
261
|
+
edgeKeys.add(key)
|
|
262
|
+
edges.push(edge)
|
|
264
263
|
}
|
|
265
264
|
for (const file of files) {
|
|
266
265
|
const kind =
|
|
@@ -381,14 +380,20 @@ export function queryImpact(graph: WorkGraph, changedFiles: readonly string[]):
|
|
|
381
380
|
// Any backend or shared module can reach every handler through backend/app.ts.
|
|
382
381
|
if (unmodeled.length > 0 || normalized.some((file) => BACKEND_SOURCE_DIR.test(file)))
|
|
383
382
|
for (const node of graph.nodes) if (node.kind === "route") seeds.add(node.id)
|
|
383
|
+
const targets = new Map<string, string[]>()
|
|
384
|
+
for (const edge of graph.edges) {
|
|
385
|
+
const from = targets.get(edge.from)
|
|
386
|
+
if (from === undefined) targets.set(edge.from, [edge.to])
|
|
387
|
+
else from.push(edge.to)
|
|
388
|
+
}
|
|
384
389
|
const impacted = new Set(seeds)
|
|
385
390
|
const queue = [...seeds]
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
for (const
|
|
389
|
-
if (
|
|
390
|
-
impacted.add(
|
|
391
|
-
queue.push(
|
|
391
|
+
// Iterating an array visits what is pushed onto it meanwhile, so this is the breadth-first walk.
|
|
392
|
+
for (const current of queue) {
|
|
393
|
+
for (const to of targets.get(current) ?? []) {
|
|
394
|
+
if (impacted.has(to)) continue
|
|
395
|
+
impacted.add(to)
|
|
396
|
+
queue.push(to)
|
|
392
397
|
}
|
|
393
398
|
}
|
|
394
399
|
const impactedRoutes = graph.nodes
|