@hominis/fireforge 0.49.2 → 0.51.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/CHANGELOG.md +87 -1
- package/README.md +1 -1
- package/dist/bin/fireforge.js +6 -0
- package/dist/build-info.json +4 -4
- package/dist/src/commands/build-prelock.d.ts +20 -0
- package/dist/src/commands/build-prelock.js +50 -0
- package/dist/src/commands/build.d.ts +3 -1
- package/dist/src/commands/build.js +13 -6
- package/dist/src/commands/check-report.d.ts +41 -0
- package/dist/src/commands/check-report.js +91 -0
- package/dist/src/commands/check-run.d.ts +33 -0
- package/dist/src/commands/check-run.js +112 -0
- package/dist/src/commands/check-steps.d.ts +75 -0
- package/dist/src/commands/check-steps.js +200 -0
- package/dist/src/commands/check.d.ts +32 -0
- package/dist/src/commands/check.js +160 -0
- package/dist/src/commands/config.js +5 -6
- package/dist/src/commands/declarations-report.d.ts +43 -0
- package/dist/src/commands/declarations-report.js +76 -0
- package/dist/src/commands/doctor-engine-eslint.js +6 -1
- package/dist/src/commands/doctor-source-pin.js +4 -1
- package/dist/src/commands/export-adopt-check.d.ts +38 -0
- package/dist/src/commands/export-adopt-check.js +98 -0
- package/dist/src/commands/export-flow.js +29 -14
- package/dist/src/commands/export-placement-gate.d.ts +6 -2
- package/dist/src/commands/export-placement-gate.js +8 -0
- package/dist/src/commands/export-shared.d.ts +2 -1
- package/dist/src/commands/export-staged-registration.d.ts +46 -0
- package/dist/src/commands/export-staged-registration.js +91 -0
- package/dist/src/commands/forward-import-remedy.d.ts +32 -0
- package/dist/src/commands/forward-import-remedy.js +63 -0
- package/dist/src/commands/furnace/apply.js +3 -3
- package/dist/src/commands/furnace/chrome-doc-remove.d.ts +2 -1
- package/dist/src/commands/furnace/chrome-doc-remove.js +2 -2
- package/dist/src/commands/furnace/chrome-doc.d.ts +2 -1
- package/dist/src/commands/furnace/chrome-doc.js +2 -2
- package/dist/src/commands/furnace/create.js +2 -2
- package/dist/src/commands/furnace/deploy-named.d.ts +48 -0
- package/dist/src/commands/furnace/deploy-named.js +107 -0
- package/dist/src/commands/furnace/deploy.d.ts +3 -2
- package/dist/src/commands/furnace/deploy.js +50 -86
- package/dist/src/commands/furnace/diff.js +26 -3
- package/dist/src/commands/furnace/index.js +66 -41
- package/dist/src/commands/furnace/init.js +13 -6
- package/dist/src/commands/furnace/override.js +4 -2
- package/dist/src/commands/furnace/preview.js +4 -3
- package/dist/src/commands/furnace/refresh.js +2 -2
- package/dist/src/commands/furnace/remove.js +4 -3
- package/dist/src/commands/furnace/rename-dry-run.d.ts +29 -0
- package/dist/src/commands/furnace/rename-dry-run.js +127 -0
- package/dist/src/commands/furnace/rename-helpers.d.ts +7 -0
- package/dist/src/commands/furnace/rename-helpers.js +15 -1
- package/dist/src/commands/furnace/rename-registrations.d.ts +41 -0
- package/dist/src/commands/furnace/rename-registrations.js +98 -0
- package/dist/src/commands/furnace/rename.d.ts +2 -1
- package/dist/src/commands/furnace/rename.js +28 -66
- package/dist/src/commands/furnace/scan.d.ts +9 -4
- package/dist/src/commands/furnace/scan.js +11 -9
- package/dist/src/commands/furnace/sync.js +3 -2
- package/dist/src/commands/furnace/validate-report.d.ts +45 -0
- package/dist/src/commands/furnace/validate-report.js +91 -0
- package/dist/src/commands/furnace/validate.d.ts +1 -1
- package/dist/src/commands/furnace/validate.js +151 -113
- package/dist/src/commands/furnace/validation-output.js +14 -3
- package/dist/src/commands/lint-per-patch.js +36 -61
- package/dist/src/commands/lint-per-run-checkjs.js +2 -2
- package/dist/src/commands/lint-report.d.ts +8 -4
- package/dist/src/commands/lint-report.js +20 -5
- package/dist/src/commands/lint.js +15 -34
- package/dist/src/commands/manifest.js +4 -0
- package/dist/src/commands/park.d.ts +22 -0
- package/dist/src/commands/park.js +232 -0
- package/dist/src/commands/patch/delete-gap-notice.js +3 -1
- package/dist/src/commands/patch/delete.d.ts +1 -1
- package/dist/src/commands/patch/delete.js +24 -104
- package/dist/src/commands/patch/index.d.ts +3 -3
- package/dist/src/commands/patch/index.js +10 -4
- package/dist/src/commands/patch/lint-ignore-from.d.ts +44 -0
- package/dist/src/commands/patch/lint-ignore-from.js +142 -0
- package/dist/src/commands/patch/lint-ignore.d.ts +5 -1
- package/dist/src/commands/patch/lint-ignore.js +78 -31
- package/dist/src/commands/patch/move-files-create.js +34 -18
- package/dist/src/commands/patch/move-files-into.js +15 -7
- package/dist/src/commands/patch/move-files.js +6 -2
- package/dist/src/commands/patch/removal-created-files.d.ts +48 -0
- package/dist/src/commands/patch/removal-created-files.js +83 -0
- package/dist/src/commands/patch/removal-dependents.d.ts +63 -0
- package/dist/src/commands/patch/removal-dependents.js +133 -0
- package/dist/src/commands/patch/rename.js +20 -1
- package/dist/src/commands/patch/reserve.d.ts +33 -0
- package/dist/src/commands/patch/reserve.js +152 -0
- package/dist/src/commands/patch/retire.d.ts +34 -0
- package/dist/src/commands/patch/retire.js +133 -0
- package/dist/src/commands/patch/split-plan.d.ts +17 -8
- package/dist/src/commands/patch/split-plan.js +60 -28
- package/dist/src/commands/patch/split-staged.d.ts +108 -0
- package/dist/src/commands/patch/split-staged.js +202 -0
- package/dist/src/commands/patch/split.d.ts +5 -0
- package/dist/src/commands/patch/split.js +62 -17
- package/dist/src/commands/patch/stage.d.ts +34 -0
- package/dist/src/commands/patch/stage.js +153 -0
- package/dist/src/commands/patch/staged-dependency-batch.d.ts +48 -0
- package/dist/src/commands/patch/staged-dependency-batch.js +176 -0
- package/dist/src/commands/patch/staged-dependency-entries.d.ts +36 -0
- package/dist/src/commands/patch/staged-dependency-entries.js +52 -0
- package/dist/src/commands/patch/staged-dependency-from.d.ts +14 -0
- package/dist/src/commands/patch/staged-dependency-from.js +108 -0
- package/dist/src/commands/patch/staged-dependency-remove.d.ts +31 -0
- package/dist/src/commands/patch/staged-dependency-remove.js +80 -0
- package/dist/src/commands/patch/staged-dependency.js +54 -139
- package/dist/src/commands/re-export-adjacent-registrations.d.ts +20 -0
- package/dist/src/commands/re-export-adjacent-registrations.js +75 -0
- package/dist/src/commands/re-export-adjacent.d.ts +50 -2
- package/dist/src/commands/re-export-adjacent.js +160 -40
- package/dist/src/commands/re-export-bulk-scan.d.ts +2 -1
- package/dist/src/commands/re-export-bulk-scan.js +22 -7
- package/dist/src/commands/re-export-drift.d.ts +36 -8
- package/dist/src/commands/re-export-drift.js +73 -49
- package/dist/src/commands/re-export-files.js +11 -8
- package/dist/src/commands/re-export-hunks.d.ts +35 -0
- package/dist/src/commands/re-export-hunks.js +220 -0
- package/dist/src/commands/re-export-lint.d.ts +2 -1
- package/dist/src/commands/re-export-lint.js +23 -10
- package/dist/src/commands/re-export-options.js +74 -6
- package/dist/src/commands/re-export-preflight.d.ts +23 -0
- package/dist/src/commands/re-export-preflight.js +160 -0
- package/dist/src/commands/re-export-purity-scope.d.ts +18 -0
- package/dist/src/commands/re-export-purity-scope.js +131 -0
- package/dist/src/commands/re-export-register.js +56 -17
- package/dist/src/commands/re-export-removed.d.ts +13 -2
- package/dist/src/commands/re-export-removed.js +57 -12
- package/dist/src/commands/re-export-scan-owner.d.ts +44 -0
- package/dist/src/commands/re-export-scan-owner.js +116 -0
- package/dist/src/commands/re-export-scan.d.ts +19 -9
- package/dist/src/commands/re-export-scan.js +60 -24
- package/dist/src/commands/re-export-single.js +122 -46
- package/dist/src/commands/re-export-stale-registrations.d.ts +18 -0
- package/dist/src/commands/re-export-stale-registrations.js +62 -0
- package/dist/src/commands/re-export-summary.d.ts +28 -0
- package/dist/src/commands/re-export-summary.js +36 -0
- package/dist/src/commands/re-export.js +71 -57
- package/dist/src/commands/rebase/index.js +17 -17
- package/dist/src/commands/run.js +16 -2
- package/dist/src/commands/status-check.d.ts +55 -16
- package/dist/src/commands/status-check.js +92 -37
- package/dist/src/commands/status-json.d.ts +22 -9
- package/dist/src/commands/status-json.js +47 -32
- package/dist/src/commands/status-output.js +3 -1
- package/dist/src/commands/status-scope.d.ts +37 -0
- package/dist/src/commands/status-scope.js +54 -0
- package/dist/src/commands/status.js +66 -23
- package/dist/src/commands/test-browser-preflight.js +19 -3
- package/dist/src/commands/test-build-furnace.d.ts +22 -0
- package/dist/src/commands/test-build-furnace.js +54 -0
- package/dist/src/commands/test-build-phase.js +64 -41
- package/dist/src/commands/test-checkjs.js +10 -2
- package/dist/src/commands/test-diagnose.js +7 -0
- package/dist/src/commands/test-dispatch.d.ts +39 -0
- package/dist/src/commands/test-dispatch.js +211 -0
- package/dist/src/commands/test-furnace-reach.d.ts +37 -0
- package/dist/src/commands/test-furnace-reach.js +132 -0
- package/dist/src/commands/test-modes.d.ts +16 -1
- package/dist/src/commands/test-modes.js +24 -1
- package/dist/src/commands/test-multi-verdict.d.ts +61 -0
- package/dist/src/commands/test-multi-verdict.js +111 -0
- package/dist/src/commands/test-orchestrate.d.ts +52 -0
- package/dist/src/commands/test-orchestrate.js +240 -0
- package/dist/src/commands/test-perf-scope.d.ts +50 -0
- package/dist/src/commands/test-perf-scope.js +138 -0
- package/dist/src/commands/test-prelock.d.ts +51 -0
- package/dist/src/commands/test-prelock.js +273 -0
- package/dist/src/commands/test-register.js +69 -10
- package/dist/src/commands/test-results.d.ts +62 -0
- package/dist/src/commands/test-results.js +62 -0
- package/dist/src/commands/test-run.d.ts +13 -55
- package/dist/src/commands/test-run.js +74 -99
- package/dist/src/commands/test-shards.d.ts +110 -0
- package/dist/src/commands/test-shards.js +255 -0
- package/dist/src/commands/test-stale-gate.d.ts +5 -1
- package/dist/src/commands/test-stale-gate.js +60 -28
- package/dist/src/commands/test-verdict.d.ts +11 -1
- package/dist/src/commands/test-verdict.js +28 -1
- package/dist/src/commands/test.d.ts +6 -1
- package/dist/src/commands/test.js +120 -124
- package/dist/src/commands/token-lint.d.ts +14 -0
- package/dist/src/commands/token-lint.js +151 -0
- package/dist/src/commands/token.js +10 -0
- package/dist/src/commands/verify-scope.d.ts +28 -0
- package/dist/src/commands/verify-scope.js +67 -0
- package/dist/src/commands/verify.d.ts +10 -2
- package/dist/src/commands/verify.js +67 -36
- package/dist/src/core/build-baseline-types.d.ts +46 -0
- package/dist/src/core/build-baseline-validate.js +19 -0
- package/dist/src/core/build-baseline.d.ts +5 -1
- package/dist/src/core/build-baseline.js +3 -1
- package/dist/src/core/build-overwrite-guard.d.ts +50 -0
- package/dist/src/core/build-overwrite-guard.js +84 -4
- package/dist/src/core/build-prepare.d.ts +13 -0
- package/dist/src/core/build-prepare.js +42 -10
- package/dist/src/core/build-run-record.d.ts +74 -0
- package/dist/src/core/build-run-record.js +136 -0
- package/dist/src/core/checkjs-support-heads.d.ts +41 -0
- package/dist/src/core/checkjs-support-heads.js +104 -0
- package/dist/src/core/config-paths.d.ts +2 -2
- package/dist/src/core/config-paths.js +10 -0
- package/dist/src/core/config-validate-check.d.ts +8 -0
- package/dist/src/core/config-validate-check.js +219 -0
- package/dist/src/core/config-validate-file-size.d.ts +9 -6
- package/dist/src/core/config-validate-file-size.js +91 -2
- package/dist/src/core/config-validate-history.d.ts +11 -0
- package/dist/src/core/config-validate-history.js +38 -0
- package/dist/src/core/config-validate-patch-policy.js +100 -0
- package/dist/src/core/config-validate-test-toolchains.js +21 -0
- package/dist/src/core/config-validate-token-scales.d.ts +9 -0
- package/dist/src/core/config-validate-token-scales.js +92 -0
- package/dist/src/core/config-validate.js +20 -5
- package/dist/src/core/config.d.ts +5 -0
- package/dist/src/core/config.js +16 -0
- package/dist/src/core/coverage-dispatch.d.ts +24 -0
- package/dist/src/core/coverage-dispatch.js +44 -0
- package/dist/src/core/coverage-extend.d.ts +70 -45
- package/dist/src/core/coverage-extend.js +199 -144
- package/dist/src/core/coverage-records.d.ts +108 -0
- package/dist/src/core/coverage-records.js +384 -0
- package/dist/src/core/destructive.d.ts +7 -4
- package/dist/src/core/destructive.js +10 -10
- package/dist/src/core/engine-session-lock.d.ts +16 -1
- package/dist/src/core/engine-session-lock.js +38 -10
- package/dist/src/core/export-moved-code-shape.d.ts +49 -11
- package/dist/src/core/export-moved-code-shape.js +135 -44
- package/dist/src/core/file-lock-queue.d.ts +67 -0
- package/dist/src/core/file-lock-queue.js +221 -0
- package/dist/src/core/file-lock-shared.d.ts +57 -0
- package/dist/src/core/file-lock-shared.js +117 -0
- package/dist/src/core/file-lock.d.ts +13 -25
- package/dist/src/core/file-lock.js +163 -140
- package/dist/src/core/furnace-apply-output.d.ts +10 -0
- package/dist/src/core/furnace-apply-output.js +31 -1
- package/dist/src/core/furnace-apply.js +22 -12
- package/dist/src/core/furnace-composed-source.d.ts +76 -0
- package/dist/src/core/furnace-composed-source.js +167 -0
- package/dist/src/core/furnace-config-validate-exceptions.d.ts +16 -0
- package/dist/src/core/furnace-config-validate-exceptions.js +102 -0
- package/dist/src/core/furnace-config-validate.js +14 -0
- package/dist/src/core/furnace-css-fragments.d.ts +10 -0
- package/dist/src/core/furnace-css-fragments.js +26 -0
- package/dist/src/core/furnace-operation.d.ts +3 -3
- package/dist/src/core/furnace-registration-jar-inplace.d.ts +12 -0
- package/dist/src/core/furnace-registration-jar-inplace.js +80 -0
- package/dist/src/core/furnace-registration-remove.d.ts +22 -1
- package/dist/src/core/furnace-registration-remove.js +53 -17
- package/dist/src/core/furnace-registration-rename.d.ts +26 -0
- package/dist/src/core/furnace-registration-rename.js +77 -0
- package/dist/src/core/furnace-registration.d.ts +14 -4
- package/dist/src/core/furnace-registration.js +44 -10
- package/dist/src/core/furnace-staleness.d.ts +7 -0
- package/dist/src/core/furnace-staleness.js +34 -24
- package/dist/src/core/furnace-validate-accessibility.d.ts +8 -4
- package/dist/src/core/furnace-validate-accessibility.js +71 -28
- package/dist/src/core/furnace-validate-exceptions.d.ts +48 -0
- package/dist/src/core/furnace-validate-exceptions.js +80 -0
- package/dist/src/core/furnace-validate-icon-button.d.ts +7 -0
- package/dist/src/core/furnace-validate-icon-button.js +78 -0
- package/dist/src/core/furnace-validate.js +1 -1
- package/dist/src/core/harness-port-fallback.d.ts +60 -0
- package/dist/src/core/harness-port-fallback.js +96 -0
- package/dist/src/core/history-log-file.d.ts +61 -0
- package/dist/src/core/history-log-file.js +164 -0
- package/dist/src/core/history-log.d.ts +2 -1
- package/dist/src/core/history-log.js +2 -1
- package/dist/src/core/json-preserving-edit.d.ts +22 -0
- package/dist/src/core/json-preserving-edit.js +199 -0
- package/dist/src/core/line-prefixer.d.ts +18 -0
- package/dist/src/core/line-prefixer.js +34 -0
- package/dist/src/core/mach.d.ts +7 -0
- package/dist/src/core/mach.js +32 -10
- package/dist/src/core/module-resolution-preflight.d.ts +19 -3
- package/dist/src/core/module-resolution-preflight.js +24 -6
- package/dist/src/core/negative-control-compiled.d.ts +27 -0
- package/dist/src/core/negative-control-compiled.js +73 -0
- package/dist/src/core/negative-control-diff.d.ts +51 -0
- package/dist/src/core/negative-control-diff.js +179 -0
- package/dist/src/core/negative-control.d.ts +150 -0
- package/dist/src/core/negative-control.js +399 -0
- package/dist/src/core/objdir-install-manifests.d.ts +73 -0
- package/dist/src/core/objdir-install-manifests.js +226 -0
- package/dist/src/core/park-store.d.ts +63 -0
- package/dist/src/core/park-store.js +216 -0
- package/dist/src/core/patch-export-update.d.ts +6 -0
- package/dist/src/core/patch-export-update.js +13 -3
- package/dist/src/core/patch-export.d.ts +3 -2
- package/dist/src/core/patch-export.js +22 -16
- package/dist/src/core/patch-files.js +26 -8
- package/dist/src/core/patch-lint-checkjs-any-import.d.ts +39 -0
- package/dist/src/core/patch-lint-checkjs-any-import.js +63 -0
- package/dist/src/core/patch-lint-checkjs-diagnostics.d.ts +17 -0
- package/dist/src/core/patch-lint-checkjs-diagnostics.js +32 -0
- package/dist/src/core/patch-lint-checkjs.d.ts +10 -1
- package/dist/src/core/patch-lint-checkjs.js +20 -13
- package/dist/src/core/patch-lint-code-lines.d.ts +59 -0
- package/dist/src/core/patch-lint-code-lines.js +105 -0
- package/dist/src/core/patch-lint-cross.d.ts +3 -1
- package/dist/src/core/patch-lint-cross.js +17 -4
- package/dist/src/core/patch-lint-css.d.ts +8 -2
- package/dist/src/core/patch-lint-css.js +24 -14
- package/dist/src/core/patch-lint-file-size.d.ts +12 -5
- package/dist/src/core/patch-lint-file-size.js +22 -11
- package/dist/src/core/patch-lint-forward-registration-extended.d.ts +23 -0
- package/dist/src/core/patch-lint-forward-registration-extended.js +36 -11
- package/dist/src/core/patch-lint-forward-registration.js +10 -0
- package/dist/src/core/patch-lint-ignore.d.ts +196 -0
- package/dist/src/core/patch-lint-ignore.js +429 -0
- package/dist/src/core/patch-lint-ownership.d.ts +10 -0
- package/dist/src/core/patch-lint-ownership.js +26 -0
- package/dist/src/core/patch-lint-size-thresholds.d.ts +52 -0
- package/dist/src/core/patch-lint-size-thresholds.js +110 -0
- package/dist/src/core/patch-lint-size.d.ts +117 -0
- package/dist/src/core/patch-lint-size.js +331 -0
- package/dist/src/core/patch-lint-staged-registration.d.ts +18 -1
- package/dist/src/core/patch-lint-staged-registration.js +20 -0
- package/dist/src/core/patch-lint-token-scale.d.ts +57 -0
- package/dist/src/core/patch-lint-token-scale.js +286 -0
- package/dist/src/core/patch-lint.d.ts +11 -83
- package/dist/src/core/patch-lint.js +66 -288
- package/dist/src/core/patch-lock.js +7 -6
- package/dist/src/core/patch-manifest-consistency.js +7 -6
- package/dist/src/core/patch-manifest-io.d.ts +6 -3
- package/dist/src/core/patch-manifest-io.js +27 -9
- package/dist/src/core/patch-manifest-key-order.d.ts +24 -0
- package/dist/src/core/patch-manifest-key-order.js +61 -0
- package/dist/src/core/patch-manifest-stage.d.ts +46 -0
- package/dist/src/core/patch-manifest-stage.js +96 -0
- package/dist/src/core/patch-manifest-validate.js +61 -3
- package/dist/src/core/patch-order-legal.d.ts +26 -0
- package/dist/src/core/patch-order-legal.js +88 -0
- package/dist/src/core/patch-policy-content.d.ts +40 -0
- package/dist/src/core/patch-policy-content.js +216 -0
- package/dist/src/core/patch-policy.d.ts +22 -5
- package/dist/src/core/patch-policy.js +26 -12
- package/dist/src/core/patch-retired.d.ts +57 -0
- package/dist/src/core/patch-retired.js +92 -0
- package/dist/src/core/patch-subset.d.ts +16 -0
- package/dist/src/core/patch-subset.js +66 -0
- package/dist/src/core/preflight-wait.d.ts +20 -0
- package/dist/src/core/preflight-wait.js +38 -0
- package/dist/src/core/rebase-from-version.d.ts +46 -0
- package/dist/src/core/rebase-from-version.js +71 -0
- package/dist/src/core/run-log.d.ts +26 -0
- package/dist/src/core/run-log.js +106 -4
- package/dist/src/core/run-profile.d.ts +7 -0
- package/dist/src/core/run-profile.js +7 -1
- package/dist/src/core/smoke-patterns.d.ts +5 -0
- package/dist/src/core/smoke-patterns.js +13 -0
- package/dist/src/core/test-harness-crash.d.ts +19 -1
- package/dist/src/core/test-harness-crash.js +8 -9
- package/dist/src/core/test-harness-signature.d.ts +33 -0
- package/dist/src/core/test-harness-signature.js +23 -1
- package/dist/src/core/test-raw-log.d.ts +66 -0
- package/dist/src/core/test-raw-log.js +122 -0
- package/dist/src/core/test-run-completeness.d.ts +90 -0
- package/dist/src/core/test-run-completeness.js +184 -0
- package/dist/src/core/test-stale-check.d.ts +27 -1
- package/dist/src/core/test-stale-check.js +39 -49
- package/dist/src/core/test-stale-exempt.d.ts +40 -0
- package/dist/src/core/test-stale-exempt.js +70 -0
- package/dist/src/core/test-xpcshell-retry.d.ts +2 -0
- package/dist/src/core/test-xpcshell-retry.js +2 -1
- package/dist/src/core/token-lint.d.ts +53 -0
- package/dist/src/core/token-lint.js +131 -0
- package/dist/src/core/token-sibling-sheets.d.ts +46 -0
- package/dist/src/core/token-sibling-sheets.js +119 -0
- package/dist/src/core/tree-guard.js +5 -0
- package/dist/src/core/typecheck-shim.d.ts +6 -2
- package/dist/src/core/typecheck-shim.js +205 -4
- package/dist/src/core/typecheck.js +3 -1
- package/dist/src/index.d.ts +14 -3
- package/dist/src/index.js +6 -1
- package/dist/src/types/commands/index.d.ts +2 -2
- package/dist/src/types/commands/options.d.ts +212 -24
- package/dist/src/types/commands/patches.d.ts +118 -1
- package/dist/src/types/config.d.ts +264 -0
- package/dist/src/types/config.js +9 -0
- package/dist/src/types/furnace.d.ts +63 -1
- package/dist/src/types/furnace.js +7 -0
- package/dist/src/types/index.d.ts +1 -1
- package/dist/src/utils/options.d.ts +36 -7
- package/dist/src/utils/options.js +94 -8
- package/dist/src/utils/path-glob.d.ts +15 -0
- package/dist/src/utils/path-glob.js +47 -0
- package/dist/src/utils/regex.d.ts +15 -3
- package/dist/src/utils/regex.js +37 -16
- package/docs/configuration.md +369 -11
- package/docs/exit-codes.md +18 -1
- package/docs/furnace.md +139 -3
- package/docs/lifecycle-invariants.md +65 -30
- package/docs/machine-output.md +120 -12
- package/docs/patch-workflow.md +458 -22
- package/docs/run-logs.md +20 -1
- package/docs/testing.md +346 -21
- package/package.json +3 -3
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
+
/**
|
|
3
|
+
* Engine registration edits for `furnace rename`: the customElements.js
|
|
4
|
+
* entry (rewritten in place, keeping its marker comments), the
|
|
5
|
+
* toolkit/content/jar.mn widget lines, the deployed `.ftl`, and the locale
|
|
6
|
+
* jar.mn line (re-pointed only when one existed, never for `sharedFtl`).
|
|
7
|
+
*/
|
|
8
|
+
import { readdir } from 'node:fs/promises';
|
|
9
|
+
import { join } from 'node:path';
|
|
10
|
+
import { loadConfig } from '../../core/config.js';
|
|
11
|
+
import { resolveFtlChromeSubPath, resolveFtlLocaleJarMnPath, } from '../../core/furnace-constants.js';
|
|
12
|
+
import { resolveFurnaceMarkerComment } from '../../core/furnace-marker.js';
|
|
13
|
+
import { addCustomElementRegistration, addJarMnEntries, addLocaleFtlJarMnEntry, removeCustomElementRegistration, removeLocaleFtlJarMnEntry, renameCustomElementRegistration, } from '../../core/furnace-registration.js';
|
|
14
|
+
import { renameJarMnEntriesInPlace } from '../../core/furnace-registration-jar-inplace.js';
|
|
15
|
+
import { snapshotFile } from '../../core/furnace-rollback.js';
|
|
16
|
+
import { pathExists, readText, removeFile, writeText } from '../../utils/fs.js';
|
|
17
|
+
import { renameComponentFileName } from './rename-helpers.js';
|
|
18
|
+
/**
|
|
19
|
+
* The project marker (`// <MARKER>:`) a registration line written by the
|
|
20
|
+
* rename carries, resolved exactly as `furnace apply` resolves it. An
|
|
21
|
+
* unreadable fireforge.json degrades to no marker rather than failing the
|
|
22
|
+
* rename.
|
|
23
|
+
*/
|
|
24
|
+
export async function loadMarkerComment(projectRoot) {
|
|
25
|
+
try {
|
|
26
|
+
return resolveFurnaceMarkerComment(await loadConfig(projectRoot));
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Re-points the engine-side registrations (customElements.js, jar.mn, and
|
|
34
|
+
* the localized `.ftl` entries) from the old tag name to the new one.
|
|
35
|
+
*
|
|
36
|
+
* @param options - See {@link UpdateEngineRegistrationsOptions}
|
|
37
|
+
*/
|
|
38
|
+
export async function updateEngineRegistrations(options) {
|
|
39
|
+
const { engineDir, oldName, newName, newDir, ftlDir, componentConfig, markerComment, journal } = options;
|
|
40
|
+
const customElementsPath = join(engineDir, 'toolkit/content/customElements.js');
|
|
41
|
+
const jarMnPath = join(engineDir, 'toolkit/content/jar.mn');
|
|
42
|
+
if (await pathExists(customElementsPath)) {
|
|
43
|
+
await snapshotFile(journal, customElementsPath);
|
|
44
|
+
// Rewrite the existing entry in place: it keeps its position, layout and
|
|
45
|
+
// trailing `// <MARKER>:` comments. Only when there is no entry to
|
|
46
|
+
// rewrite is a fresh one added, carrying the project marker like every
|
|
47
|
+
// line `furnace apply` writes.
|
|
48
|
+
if (!(await renameCustomElementRegistration(engineDir, oldName, newName))) {
|
|
49
|
+
await removeCustomElementRegistration(engineDir, oldName);
|
|
50
|
+
await addCustomElementRegistration(engineDir, newName, `chrome://global/content/elements/${newName}.mjs`, markerComment !== undefined ? { markerComment } : {});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
if (await pathExists(jarMnPath)) {
|
|
54
|
+
await snapshotFile(journal, jarMnPath);
|
|
55
|
+
const files = (await readdir(newDir, { withFileTypes: true }))
|
|
56
|
+
.filter((e) => e.isFile() && (e.name.endsWith('.mjs') || e.name.endsWith('.css')))
|
|
57
|
+
.map((e) => e.name);
|
|
58
|
+
// Rewrite the old lines where they stand, like the customElements.js
|
|
59
|
+
// entry above, so the rename moves no other line of the block; only a
|
|
60
|
+
// file with no line yet is inserted.
|
|
61
|
+
await renameJarMnEntriesInPlace(engineDir, oldName, newName, files, (file) => renameComponentFileName(file, oldName, newName));
|
|
62
|
+
if (files.length > 0) {
|
|
63
|
+
await addJarMnEntries(engineDir, newName, files);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// Rename FTL localization files in the engine locale directory
|
|
67
|
+
const ftlDirPath = join(engineDir, ftlDir);
|
|
68
|
+
const oldFtlPath = join(ftlDirPath, `${oldName}.ftl`);
|
|
69
|
+
const newFtlPath = join(ftlDirPath, `${newName}.ftl`);
|
|
70
|
+
if (await pathExists(oldFtlPath)) {
|
|
71
|
+
await snapshotFile(journal, oldFtlPath);
|
|
72
|
+
await snapshotFile(journal, newFtlPath);
|
|
73
|
+
const ftlContent = await readText(oldFtlPath);
|
|
74
|
+
await writeText(newFtlPath, ftlContent);
|
|
75
|
+
await removeFile(oldFtlPath);
|
|
76
|
+
}
|
|
77
|
+
// Re-point the locale jar.mn chrome registration when the component is
|
|
78
|
+
// localized. Renaming the .ftl file on disk alone leaves the locale
|
|
79
|
+
// jar.mn pointing at `locale/.../${oldName}.ftl`, so `furnace validate`
|
|
80
|
+
// passes while the engine still carries a stale registration for the
|
|
81
|
+
// now-missing file. Only an existing line is re-pointed: a `sharedFtl`
|
|
82
|
+
// component has no per-component .ftl, and adding a line for one names a
|
|
83
|
+
// file that does not exist (an unmanaged edit `mach build` trips over).
|
|
84
|
+
if (componentConfig.localized) {
|
|
85
|
+
const chromeSubPath = resolveFtlChromeSubPath(ftlDir);
|
|
86
|
+
const localeJarRel = resolveFtlLocaleJarMnPath(ftlDir);
|
|
87
|
+
if (chromeSubPath !== undefined && localeJarRel !== undefined) {
|
|
88
|
+
const localeJarAbs = join(engineDir, localeJarRel);
|
|
89
|
+
if (await pathExists(localeJarAbs)) {
|
|
90
|
+
await snapshotFile(journal, localeJarAbs);
|
|
91
|
+
const removed = await removeLocaleFtlJarMnEntry(engineDir, localeJarRel, oldName, chromeSubPath);
|
|
92
|
+
if (removed && componentConfig.sharedFtl === undefined) {
|
|
93
|
+
await addLocaleFtlJarMnEntry(engineDir, localeJarRel, newName, chromeSubPath);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import type { FurnaceRenameOptions } from '../../types/commands/index.js';
|
|
1
2
|
/**
|
|
2
3
|
* Renames a custom or override component atomically: updates directory name,
|
|
3
4
|
* file names, file contents, furnace.json, and engine registrations.
|
|
4
5
|
*/
|
|
5
|
-
export declare function furnaceRenameCommand(projectRoot: string, oldName: string, newName: string): Promise<void>;
|
|
6
|
+
export declare function furnaceRenameCommand(projectRoot: string, oldName: string, newName: string, options?: FurnaceRenameOptions): Promise<void>;
|
|
@@ -3,9 +3,8 @@ import { readdir } from 'node:fs/promises';
|
|
|
3
3
|
import { join } from 'node:path';
|
|
4
4
|
import { getProjectPaths, loadConfig } from '../../core/config.js';
|
|
5
5
|
import { getFurnacePaths, loadFurnaceConfig, writeFurnaceConfig, } from '../../core/furnace-config.js';
|
|
6
|
-
import { isComponentSourceFile,
|
|
7
|
-
import { completeJournalRollback, runFurnaceMutation } from '../../core/furnace-operation.js';
|
|
8
|
-
import { addCustomElementRegistration, addJarMnEntries, addLocaleFtlJarMnEntry, removeCustomElementRegistration, removeJarMnEntries, removeLocaleFtlJarMnEntry, } from '../../core/furnace-registration.js';
|
|
6
|
+
import { isComponentSourceFile, resolveFtlDir, tagNameToClassName, } from '../../core/furnace-constants.js';
|
|
7
|
+
import { completeJournalRollback, runFurnaceMutation, waitLockMutationOptions, } from '../../core/furnace-operation.js';
|
|
9
8
|
import { CUSTOM_ELEMENT_TAG_PATTERN, CUSTOM_ELEMENT_TAG_RULES, } from '../../core/furnace-registration-validate.js';
|
|
10
9
|
import { createRollbackJournal, recordCreatedDir, snapshotDir, snapshotFile, } from '../../core/furnace-rollback.js';
|
|
11
10
|
import { getStoriesDir } from '../../core/furnace-stories.js';
|
|
@@ -16,7 +15,9 @@ import { copyFile, ensureDir, pathExists, readText, removeDir, removeFile, write
|
|
|
16
15
|
import { info, intro, note, outro, warn } from '../../utils/logger.js';
|
|
17
16
|
import { escapeRegex } from '../../utils/regex.js';
|
|
18
17
|
import { updateBrowserChromeTestContent } from './rename-browser-test.js';
|
|
18
|
+
import { renderRenamePlan } from './rename-dry-run.js';
|
|
19
19
|
import { rekeyStateChecksums, renameComponentFileName, updateConfigForCustomRename, updateConfigForOverrideRename, } from './rename-helpers.js';
|
|
20
|
+
import { loadMarkerComment, updateEngineRegistrations } from './rename-registrations.js';
|
|
20
21
|
import { renameXpcshellTestFiles } from './rename-xpcshell.js';
|
|
21
22
|
import { browserTestFileName } from './test-file-name.js';
|
|
22
23
|
/**
|
|
@@ -165,7 +166,7 @@ async function performRenameMutations(args) {
|
|
|
165
166
|
const { projectRoot, oldName, newName } = args;
|
|
166
167
|
const oldClassName = tagNameToClassName(oldName);
|
|
167
168
|
const newClassName = tagNameToClassName(newName);
|
|
168
|
-
|
|
169
|
+
const mutate = async (ctx) => {
|
|
169
170
|
const journal = createRollbackJournal();
|
|
170
171
|
ctx.registerJournal(journal);
|
|
171
172
|
let newDir = args.newDir;
|
|
@@ -245,16 +246,16 @@ async function performRenameMutations(args) {
|
|
|
245
246
|
}
|
|
246
247
|
await writeFurnaceConfig(projectRoot, config);
|
|
247
248
|
// 3. Update engine registrations (custom components only)
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
const isLocalized = config.custom[newName].localized;
|
|
249
|
+
const newConfig = config.custom[newName];
|
|
250
|
+
if (isCustom && newConfig?.register && (await pathExists(args.engineDir))) {
|
|
251
251
|
await updateEngineRegistrations({
|
|
252
252
|
engineDir: args.engineDir,
|
|
253
253
|
oldName,
|
|
254
254
|
newName,
|
|
255
255
|
newDir,
|
|
256
|
-
ftlDir,
|
|
257
|
-
|
|
256
|
+
ftlDir: resolveFtlDir(config.ftlBasePath),
|
|
257
|
+
componentConfig: newConfig,
|
|
258
|
+
markerComment: await loadMarkerComment(projectRoot),
|
|
258
259
|
journal,
|
|
259
260
|
});
|
|
260
261
|
}
|
|
@@ -318,68 +319,15 @@ async function performRenameMutations(args) {
|
|
|
318
319
|
subject: `rename "${oldName}" → "${newName}"`,
|
|
319
320
|
});
|
|
320
321
|
}
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
/**
|
|
324
|
-
* Re-points the engine-side registrations (customElements.js, jar.mn, and
|
|
325
|
-
* the localized `.ftl` entries) from the old tag name to the new one.
|
|
326
|
-
*
|
|
327
|
-
* @param options - See {@link UpdateEngineRegistrationsOptions}
|
|
328
|
-
*/
|
|
329
|
-
async function updateEngineRegistrations(options) {
|
|
330
|
-
const { engineDir, oldName, newName, newDir, ftlDir, isLocalized, journal } = options;
|
|
331
|
-
const customElementsPath = join(engineDir, 'toolkit/content/customElements.js');
|
|
332
|
-
const jarMnPath = join(engineDir, 'toolkit/content/jar.mn');
|
|
333
|
-
if (await pathExists(customElementsPath)) {
|
|
334
|
-
await snapshotFile(journal, customElementsPath);
|
|
335
|
-
await removeCustomElementRegistration(engineDir, oldName);
|
|
336
|
-
await addCustomElementRegistration(engineDir, newName, `chrome://global/content/elements/${newName}.mjs`);
|
|
337
|
-
}
|
|
338
|
-
if (await pathExists(jarMnPath)) {
|
|
339
|
-
await snapshotFile(journal, jarMnPath);
|
|
340
|
-
await removeJarMnEntries(engineDir, oldName);
|
|
341
|
-
const files = (await readdir(newDir, { withFileTypes: true }))
|
|
342
|
-
.filter((e) => e.isFile() && (e.name.endsWith('.mjs') || e.name.endsWith('.css')))
|
|
343
|
-
.map((e) => e.name);
|
|
344
|
-
if (files.length > 0) {
|
|
345
|
-
await addJarMnEntries(engineDir, newName, files);
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
// Rename FTL localization files in the engine locale directory
|
|
349
|
-
const ftlDirPath = join(engineDir, ftlDir);
|
|
350
|
-
const oldFtlPath = join(ftlDirPath, `${oldName}.ftl`);
|
|
351
|
-
const newFtlPath = join(ftlDirPath, `${newName}.ftl`);
|
|
352
|
-
if (await pathExists(oldFtlPath)) {
|
|
353
|
-
await snapshotFile(journal, oldFtlPath);
|
|
354
|
-
await snapshotFile(journal, newFtlPath);
|
|
355
|
-
const ftlContent = await readText(oldFtlPath);
|
|
356
|
-
await writeText(newFtlPath, ftlContent);
|
|
357
|
-
await removeFile(oldFtlPath);
|
|
358
|
-
}
|
|
359
|
-
// Re-wire the locale jar.mn chrome registration when the component is
|
|
360
|
-
// localized. `updateEngineRegistrations` renames the .ftl file on disk but
|
|
361
|
-
// leaves the locale jar.mn pointing at `locale/.../${oldName}.ftl`, so
|
|
362
|
-
// `furnace validate` passes while the engine still carries a stale
|
|
363
|
-
// registration for the now-missing file.
|
|
364
|
-
if (isLocalized) {
|
|
365
|
-
const chromeSubPath = resolveFtlChromeSubPath(ftlDir);
|
|
366
|
-
const localeJarRel = resolveFtlLocaleJarMnPath(ftlDir);
|
|
367
|
-
if (chromeSubPath !== undefined && localeJarRel !== undefined) {
|
|
368
|
-
const localeJarAbs = join(engineDir, localeJarRel);
|
|
369
|
-
if (await pathExists(localeJarAbs)) {
|
|
370
|
-
await snapshotFile(journal, localeJarAbs);
|
|
371
|
-
await removeLocaleFtlJarMnEntry(engineDir, localeJarRel, oldName, chromeSubPath);
|
|
372
|
-
await addLocaleFtlJarMnEntry(engineDir, localeJarRel, newName, chromeSubPath);
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
}
|
|
322
|
+
};
|
|
323
|
+
await runFurnaceMutation(projectRoot, 'rename-rollback', mutate, waitLockMutationOptions(args.waitLockSeconds));
|
|
376
324
|
}
|
|
377
325
|
/**
|
|
378
326
|
* Renames a custom or override component atomically: updates directory name,
|
|
379
327
|
* file names, file contents, furnace.json, and engine registrations.
|
|
380
328
|
*/
|
|
381
|
-
export async function furnaceRenameCommand(projectRoot, oldName, newName) {
|
|
382
|
-
intro('Furnace Rename');
|
|
329
|
+
export async function furnaceRenameCommand(projectRoot, oldName, newName, options = {}) {
|
|
330
|
+
intro(options.dryRun ? 'Furnace Rename (dry run)' : 'Furnace Rename');
|
|
383
331
|
if (!CUSTOM_ELEMENT_TAG_PATTERN.test(oldName)) {
|
|
384
332
|
throw new InvalidArgumentError(`Invalid source name "${oldName}": ${CUSTOM_ELEMENT_TAG_RULES}`, 'old-name');
|
|
385
333
|
}
|
|
@@ -419,6 +367,19 @@ export async function furnaceRenameCommand(projectRoot, oldName, newName) {
|
|
|
419
367
|
if (await pathExists(newDir)) {
|
|
420
368
|
throw new FurnaceError(`Target directory already exists: components/${componentDirLabel}/${newName}`, newName);
|
|
421
369
|
}
|
|
370
|
+
if (options.dryRun) {
|
|
371
|
+
note(await renderRenamePlan({
|
|
372
|
+
config,
|
|
373
|
+
oldName,
|
|
374
|
+
newName,
|
|
375
|
+
oldDir,
|
|
376
|
+
componentDirLabel,
|
|
377
|
+
engineDir: paths.engine,
|
|
378
|
+
markerComment: await loadMarkerComment(projectRoot),
|
|
379
|
+
}), `${oldName} → ${newName}`);
|
|
380
|
+
outro('Dry run complete (no files modified)');
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
422
383
|
await performRenameMutations({
|
|
423
384
|
projectRoot,
|
|
424
385
|
oldName,
|
|
@@ -427,6 +388,7 @@ export async function furnaceRenameCommand(projectRoot, oldName, newName) {
|
|
|
427
388
|
furnaceConfigPath: furnacePaths.furnaceConfig,
|
|
428
389
|
furnacePaths,
|
|
429
390
|
engineDir: paths.engine,
|
|
391
|
+
waitLockSeconds: options.waitLockSeconds,
|
|
430
392
|
});
|
|
431
393
|
note(`Component renamed: ${oldName} → ${newName}\n\n` +
|
|
432
394
|
`Directory: components/${componentDirLabel}/${newName}/\n\n` +
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
+
import type { FurnaceLockWaitable } from '../../types/commands/index.js';
|
|
2
|
+
/** Options for `furnace scan`. */
|
|
3
|
+
export interface FurnaceScanOptions extends FurnaceLockWaitable {
|
|
4
|
+
/** Search additional Firefox directories beyond the default widgets path. */
|
|
5
|
+
deep?: boolean;
|
|
6
|
+
/** Persist every untracked component into furnace.json's stock section. */
|
|
7
|
+
track?: boolean;
|
|
8
|
+
}
|
|
1
9
|
/**
|
|
2
10
|
* Runs the furnace scan command to discover MozLitElement components.
|
|
3
11
|
* @param projectRoot - Root directory of the project
|
|
4
12
|
* @param options - Scan options
|
|
5
13
|
*/
|
|
6
|
-
export declare function furnaceScanCommand(projectRoot: string, options?:
|
|
7
|
-
deep?: boolean;
|
|
8
|
-
track?: boolean;
|
|
9
|
-
}): Promise<void>;
|
|
14
|
+
export declare function furnaceScanCommand(projectRoot: string, options?: FurnaceScanOptions): Promise<void>;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { confirm, multiselect, select } from '@clack/prompts';
|
|
3
3
|
import { stdioIsInteractive } from '../../core/destructive.js';
|
|
4
4
|
import { ensureFurnaceConfig, furnaceConfigExists, getFurnacePaths, loadFurnaceConfig, writeFurnaceConfig, } from '../../core/furnace-config.js';
|
|
5
|
-
import { completeJournalRollback, runFurnaceMutation } from '../../core/furnace-operation.js';
|
|
5
|
+
import { completeJournalRollback, runFurnaceMutation, waitLockMutationOptions, } from '../../core/furnace-operation.js';
|
|
6
6
|
import { assertFurnaceEngineReady } from '../../core/furnace-precondition.js';
|
|
7
7
|
import { createRollbackJournal, snapshotFile } from '../../core/furnace-rollback.js';
|
|
8
8
|
import { DEEP_SCAN_PATHS, scanWidgetsDirectory } from '../../core/furnace-scanner.js';
|
|
@@ -13,8 +13,9 @@ import { furnaceOverrideCommand } from './override.js';
|
|
|
13
13
|
* @param components - Components discovered in the engine scan
|
|
14
14
|
* @param tracked - Existing Furnace tracking map keyed by tag name
|
|
15
15
|
* @param projectRoot - Root directory of the project
|
|
16
|
+
* @param waitLockSeconds - Resolved `--wait-lock` budget for the furnace lock
|
|
16
17
|
*/
|
|
17
|
-
async function promptAddComponents(components, tracked, projectRoot) {
|
|
18
|
+
async function promptAddComponents(components, tracked, projectRoot, waitLockSeconds) {
|
|
18
19
|
const untrackedComponents = components.filter((c) => !tracked.has(c.tagName));
|
|
19
20
|
const shouldAdd = await confirm({ message: 'Add components to furnace.json?' });
|
|
20
21
|
if (isCancel(shouldAdd) || !shouldAdd) {
|
|
@@ -36,7 +37,7 @@ async function promptAddComponents(components, tracked, projectRoot) {
|
|
|
36
37
|
outro('Scan complete');
|
|
37
38
|
return;
|
|
38
39
|
}
|
|
39
|
-
await persistStockComponents(projectRoot, selected);
|
|
40
|
+
await persistStockComponents(projectRoot, selected, waitLockSeconds);
|
|
40
41
|
const addedNames = selected;
|
|
41
42
|
success(`Added ${addedNames.length} component${addedNames.length === 1 ? '' : 's'} to furnace.json`);
|
|
42
43
|
// Offer to immediately override one of the just-added stock components.
|
|
@@ -54,7 +55,7 @@ async function promptAddComponents(components, tracked, projectRoot) {
|
|
|
54
55
|
cancel('Cancelled');
|
|
55
56
|
return;
|
|
56
57
|
}
|
|
57
|
-
await furnaceOverrideCommand(projectRoot, overrideTarget);
|
|
58
|
+
await furnaceOverrideCommand(projectRoot, overrideTarget, waitLockSeconds !== undefined ? { waitLockSeconds } : {});
|
|
58
59
|
}
|
|
59
60
|
/**
|
|
60
61
|
* Persists discovered component tag names into the `stock` section of
|
|
@@ -69,8 +70,8 @@ async function promptAddComponents(components, tracked, projectRoot) {
|
|
|
69
70
|
* auto-created cleans up after itself instead of leaving an unwanted default
|
|
70
71
|
* config behind.
|
|
71
72
|
*/
|
|
72
|
-
async function persistStockComponents(projectRoot, names) {
|
|
73
|
-
|
|
73
|
+
async function persistStockComponents(projectRoot, names, waitLockSeconds) {
|
|
74
|
+
const mutate = async (ctx) => {
|
|
74
75
|
const journal = createRollbackJournal();
|
|
75
76
|
ctx.registerJournal(journal);
|
|
76
77
|
const furnacePaths = getFurnacePaths(projectRoot);
|
|
@@ -96,7 +97,8 @@ async function persistStockComponents(projectRoot, names) {
|
|
|
96
97
|
subject: `furnace.json update during scan`,
|
|
97
98
|
});
|
|
98
99
|
}
|
|
99
|
-
}
|
|
100
|
+
};
|
|
101
|
+
await runFurnaceMutation(projectRoot, 'scan-rollback', mutate, waitLockMutationOptions(waitLockSeconds));
|
|
100
102
|
}
|
|
101
103
|
/**
|
|
102
104
|
* Renders a component's discovered capabilities as a display suffix. Shared
|
|
@@ -172,14 +174,14 @@ export async function furnaceScanCommand(projectRoot, options = {}) {
|
|
|
172
174
|
return;
|
|
173
175
|
}
|
|
174
176
|
const untrackedNames = untrackedComponentList.map((c) => c.tagName);
|
|
175
|
-
await persistStockComponents(projectRoot, untrackedNames);
|
|
177
|
+
await persistStockComponents(projectRoot, untrackedNames, options.waitLockSeconds);
|
|
176
178
|
success(`Tracked ${untrackedNames.length} component${untrackedNames.length === 1 ? '' : 's'} in the stock section of furnace.json`);
|
|
177
179
|
outro('Scan complete');
|
|
178
180
|
return;
|
|
179
181
|
}
|
|
180
182
|
const isInteractive = stdioIsInteractive();
|
|
181
183
|
if (isInteractive && untrackedCount > 0) {
|
|
182
|
-
await promptAddComponents(components, tracked, projectRoot);
|
|
184
|
+
await promptAddComponents(components, tracked, projectRoot, options.waitLockSeconds);
|
|
183
185
|
return;
|
|
184
186
|
}
|
|
185
187
|
if (untrackedCount > 0) {
|
|
@@ -3,7 +3,7 @@ import { readdir } from 'node:fs/promises';
|
|
|
3
3
|
import { join } from 'node:path';
|
|
4
4
|
import { loadConfig } from '../../core/config.js';
|
|
5
5
|
import { applyAllComponents } from '../../core/furnace-apply.js';
|
|
6
|
-
import { logApplyResult } from '../../core/furnace-apply-output.js';
|
|
6
|
+
import { formatSkipBreakdown, logApplyResult } from '../../core/furnace-apply-output.js';
|
|
7
7
|
import { getFurnacePaths, loadFurnaceConfig } from '../../core/furnace-config.js';
|
|
8
8
|
import { reportJsconfigPathsSync } from '../../core/furnace-jsconfig.js';
|
|
9
9
|
import { runFurnaceMutation, waitLockMutationOptions } from '../../core/furnace-operation.js';
|
|
@@ -136,7 +136,8 @@ export async function furnaceSyncCommand(projectRoot, options = {}) {
|
|
|
136
136
|
throw new FurnaceError(`${totalFailures} component${totalFailures === 1 ? '' : 's'} failed to apply cleanly`);
|
|
137
137
|
}
|
|
138
138
|
await reportJsconfigPathsSync(projectRoot, config, false);
|
|
139
|
-
outro(`Sync complete — ${result.applied.length} applied, ${result.skipped.length} skipped`
|
|
139
|
+
outro(`Sync complete — ${result.applied.length} applied, ${result.skipped.length} skipped` +
|
|
140
|
+
formatSkipBreakdown(result.skipped));
|
|
140
141
|
}
|
|
141
142
|
else {
|
|
142
143
|
outro('Dry run complete');
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `furnace validate` result rendering: the human per-component lines and
|
|
3
|
+
* the `--json` document (schemaVersion 1, docs/machine-output.md), plus
|
|
4
|
+
* the verdict both share, so the exit code and the `passed` key can never
|
|
5
|
+
* disagree.
|
|
6
|
+
*/
|
|
7
|
+
import { type ValidationExceptionOutcome } from '../../core/furnace-validate-exceptions.js';
|
|
8
|
+
import type { ValidationIssue } from '../../types/furnace.js';
|
|
9
|
+
/** One finished `furnace validate` run. */
|
|
10
|
+
export interface FurnaceValidateReport {
|
|
11
|
+
/** Components the run judged, in validation order. */
|
|
12
|
+
components: string[];
|
|
13
|
+
/** Findings after `validationExceptions` were applied. */
|
|
14
|
+
outcome: ValidationExceptionOutcome;
|
|
15
|
+
/** `--max-warnings`, when given. */
|
|
16
|
+
maxWarnings?: number | undefined;
|
|
17
|
+
}
|
|
18
|
+
/** The verdict: counts, and whether errors or the warning budget fail it. */
|
|
19
|
+
export interface FurnaceValidateVerdict {
|
|
20
|
+
errors: number;
|
|
21
|
+
warnings: number;
|
|
22
|
+
/** True when `--max-warnings` was given and the warnings exceed it. */
|
|
23
|
+
warningBudgetExceeded: boolean;
|
|
24
|
+
passed: boolean;
|
|
25
|
+
}
|
|
26
|
+
/** Computes the verdict both renderings report. */
|
|
27
|
+
export declare function judgeValidateReport(report: FurnaceValidateReport): FurnaceValidateVerdict;
|
|
28
|
+
/**
|
|
29
|
+
* Prints one line per clean component and every finding of the rest.
|
|
30
|
+
* Findings on names outside `components` (a stale exception for a removed
|
|
31
|
+
* component, an orphaned scaffold) print after them.
|
|
32
|
+
*/
|
|
33
|
+
export declare function renderValidateHuman(components: readonly string[], issues: readonly ValidationIssue[]): void;
|
|
34
|
+
/**
|
|
35
|
+
* Writes the `--json` document and seals stdout. Every finding is listed
|
|
36
|
+
* once in `issues` (stale-exception warnings included); `excepted` and
|
|
37
|
+
* `staleExceptions` restate the exception bookkeeping for a consumer that
|
|
38
|
+
* audits the list itself.
|
|
39
|
+
*/
|
|
40
|
+
export declare function renderValidateJson(report: FurnaceValidateReport): void;
|
|
41
|
+
/**
|
|
42
|
+
* Parses `--max-warnings <n>`: a non-negative integer, or undefined when
|
|
43
|
+
* the flag was not given.
|
|
44
|
+
*/
|
|
45
|
+
export declare function parseMaxWarnings(raw: string | undefined): number | undefined;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
+
/**
|
|
3
|
+
* `furnace validate` result rendering: the human per-component lines and
|
|
4
|
+
* the `--json` document (schemaVersion 1, docs/machine-output.md), plus
|
|
5
|
+
* the verdict both share, so the exit code and the `passed` key can never
|
|
6
|
+
* disagree.
|
|
7
|
+
*/
|
|
8
|
+
import { countValidationSeverities, } from '../../core/furnace-validate-exceptions.js';
|
|
9
|
+
import { InvalidArgumentError } from '../../errors/base.js';
|
|
10
|
+
import { setStdoutSealed, success } from '../../utils/logger.js';
|
|
11
|
+
import { displayValidationIssues } from './validation-output.js';
|
|
12
|
+
/** Computes the verdict both renderings report. */
|
|
13
|
+
export function judgeValidateReport(report) {
|
|
14
|
+
const { errors, warnings } = countValidationSeverities(report.outcome.issues);
|
|
15
|
+
const warningBudgetExceeded = report.maxWarnings !== undefined && warnings > report.maxWarnings;
|
|
16
|
+
return {
|
|
17
|
+
errors,
|
|
18
|
+
warnings,
|
|
19
|
+
warningBudgetExceeded,
|
|
20
|
+
passed: errors === 0 && !warningBudgetExceeded,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/** Groups findings by component, keeping the report's component order first. */
|
|
24
|
+
function groupByComponent(components, issues) {
|
|
25
|
+
const grouped = new Map(components.map((name) => [name, []]));
|
|
26
|
+
for (const issue of issues) {
|
|
27
|
+
const list = grouped.get(issue.component) ?? [];
|
|
28
|
+
list.push(issue);
|
|
29
|
+
grouped.set(issue.component, list);
|
|
30
|
+
}
|
|
31
|
+
return grouped;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Prints one line per clean component and every finding of the rest.
|
|
35
|
+
* Findings on names outside `components` (a stale exception for a removed
|
|
36
|
+
* component, an orphaned scaffold) print after them.
|
|
37
|
+
*/
|
|
38
|
+
export function renderValidateHuman(components, issues) {
|
|
39
|
+
for (const [name, componentIssues] of groupByComponent(components, issues)) {
|
|
40
|
+
if (componentIssues.length === 0) {
|
|
41
|
+
success(`${name} — all checks passed`);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
displayValidationIssues(componentIssues);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Writes the `--json` document and seals stdout. Every finding is listed
|
|
50
|
+
* once in `issues` (stale-exception warnings included); `excepted` and
|
|
51
|
+
* `staleExceptions` restate the exception bookkeeping for a consumer that
|
|
52
|
+
* audits the list itself.
|
|
53
|
+
*/
|
|
54
|
+
export function renderValidateJson(report) {
|
|
55
|
+
const verdict = judgeValidateReport(report);
|
|
56
|
+
const grouped = groupByComponent(report.components, report.outcome.issues);
|
|
57
|
+
const payload = {
|
|
58
|
+
schemaVersion: 1,
|
|
59
|
+
passed: verdict.passed,
|
|
60
|
+
summary: {
|
|
61
|
+
components: report.components.length,
|
|
62
|
+
errors: verdict.errors,
|
|
63
|
+
warnings: verdict.warnings,
|
|
64
|
+
excepted: report.outcome.excepted.length,
|
|
65
|
+
staleExceptions: report.outcome.stale.length,
|
|
66
|
+
},
|
|
67
|
+
...(report.maxWarnings !== undefined ? { maxWarnings: report.maxWarnings } : {}),
|
|
68
|
+
components: report.components.map((name) => ({
|
|
69
|
+
name,
|
|
70
|
+
...countValidationSeverities(grouped.get(name) ?? []),
|
|
71
|
+
})),
|
|
72
|
+
issues: report.outcome.issues,
|
|
73
|
+
excepted: report.outcome.excepted,
|
|
74
|
+
staleExceptions: report.outcome.stale,
|
|
75
|
+
};
|
|
76
|
+
process.stdout.write(`${JSON.stringify(payload, null, 2)}\n`);
|
|
77
|
+
setStdoutSealed(true);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Parses `--max-warnings <n>`: a non-negative integer, or undefined when
|
|
81
|
+
* the flag was not given.
|
|
82
|
+
*/
|
|
83
|
+
export function parseMaxWarnings(raw) {
|
|
84
|
+
if (raw === undefined)
|
|
85
|
+
return undefined;
|
|
86
|
+
const value = Number(raw);
|
|
87
|
+
if (!Number.isInteger(value) || value < 0) {
|
|
88
|
+
throw new InvalidArgumentError('--max-warnings must be a non-negative integer.', '--max-warnings');
|
|
89
|
+
}
|
|
90
|
+
return value;
|
|
91
|
+
}
|
|
@@ -3,6 +3,6 @@ import type { FurnaceValidateOptions } from '../../types/commands/index.js';
|
|
|
3
3
|
* Runs the furnace validate command to perform static analysis on components.
|
|
4
4
|
* @param projectRoot - Root directory of the project
|
|
5
5
|
* @param name - Optional component name to validate (validates all if omitted)
|
|
6
|
-
* @param options - Optional command options (
|
|
6
|
+
* @param options - Optional command options (`--fix`, `--json`, `--max-warnings`)
|
|
7
7
|
*/
|
|
8
8
|
export declare function furnaceValidateCommand(projectRoot: string, name?: string, options?: FurnaceValidateOptions): Promise<void>;
|