@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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// SPDX-License-Identifier: EUPL-1.2
|
|
2
2
|
import { Command, Option } from 'commander';
|
|
3
3
|
import { withEngineSessionLock } from '../../core/engine-session-lock.js';
|
|
4
|
-
import { addWaitLockOption, pickDefined, resolveWaitLockSeconds } from '../../utils/options.js';
|
|
4
|
+
import { addWaitLockOption, pickDefined, resolveWaitLockSeconds, } from '../../utils/options.js';
|
|
5
5
|
import { furnaceApplyCommand } from './apply.js';
|
|
6
6
|
import { furnaceChromeDocCreateCommand } from './chrome-doc.js';
|
|
7
7
|
import { furnaceChromeDocRemoveCommand } from './chrome-doc-remove.js';
|
|
@@ -19,6 +19,18 @@ import { furnaceScanCommand } from './scan.js';
|
|
|
19
19
|
import { furnaceStatusCommand } from './status.js';
|
|
20
20
|
import { furnaceSyncCommand } from './sync.js';
|
|
21
21
|
import { furnaceValidateCommand } from './validate.js';
|
|
22
|
+
import { parseMaxWarnings } from './validate-report.js';
|
|
23
|
+
/**
|
|
24
|
+
* Splits the raw `--wait-lock` value off a furnace leaf's parsed options and
|
|
25
|
+
* resolves it into `waitLockSeconds` (flag, else `FIREFORGE_WAIT_LOCK`, else
|
|
26
|
+
* undefined) for the furnace lock `runFurnaceMutation` takes. Used by the
|
|
27
|
+
* leaves that take only Furnace's lock, where the flag used to be accepted
|
|
28
|
+
* and ignored.
|
|
29
|
+
*/
|
|
30
|
+
function withFurnaceLockBudget(options) {
|
|
31
|
+
const { waitLock, ...rest } = options;
|
|
32
|
+
return pickDefined({ ...rest, waitLockSeconds: resolveWaitLockSeconds(waitLock) });
|
|
33
|
+
}
|
|
22
34
|
async function runEngineLockedFurnaceCommand(context, command, operation, waitLockSeconds) {
|
|
23
35
|
const projectRoot = context.getProjectRoot();
|
|
24
36
|
await withEngineSessionLock(projectRoot, command, () => operation(projectRoot), {
|
|
@@ -51,16 +63,24 @@ function registerFurnaceApplyCommand(furnace, context) {
|
|
|
51
63
|
function registerFurnaceDeployCommand(furnace, context) {
|
|
52
64
|
const { getProjectRoot, withErrorHandling } = context;
|
|
53
65
|
const deploy = furnace
|
|
54
|
-
.command('deploy [
|
|
55
|
-
.description('Apply components and validate in one step')
|
|
66
|
+
.command('deploy [names...]')
|
|
67
|
+
.description('Apply components and validate in one step (name several to deploy them under one lock hold)')
|
|
56
68
|
.option('--dry-run', 'Show what would be changed without writing (reads may overlap concurrent mutations)')
|
|
57
69
|
.option('--force', 'Proceed despite baseVersion drift (stale overrides)')
|
|
58
|
-
.option('--skip-validate', 'Skip the validation step (apply only)')
|
|
59
|
-
|
|
70
|
+
.option('--skip-validate', 'Skip the validation step (apply only)')
|
|
71
|
+
.addHelpText('after', [
|
|
72
|
+
'',
|
|
73
|
+
'Deploy registers every .mjs and .css file in a custom component directory in',
|
|
74
|
+
'toolkit/content/jar.mn, including extra modules beside the main one (e.g.',
|
|
75
|
+
'components/custom/<tag>/<tag>-rows.mjs). Add the file to the directory and run',
|
|
76
|
+
'`fireforge furnace deploy <tag>` instead of writing the jar.mn line by hand; a line',
|
|
77
|
+
'that already exists anywhere in jar.mn is kept and never duplicated.',
|
|
78
|
+
].join('\n'));
|
|
79
|
+
addWaitLockOption(deploy).action(withErrorHandling(async (names, options) => {
|
|
60
80
|
const { waitLock, ...rest } = options ?? {};
|
|
61
81
|
const waitLockSeconds = resolveWaitLockSeconds(waitLock);
|
|
62
82
|
const parsed = pickDefined({ ...rest, waitLockSeconds });
|
|
63
|
-
const run = (projectRoot) => furnaceDeployCommand(projectRoot,
|
|
83
|
+
const run = (projectRoot) => furnaceDeployCommand(projectRoot, names, parsed);
|
|
64
84
|
if (parsed.dryRun === true) {
|
|
65
85
|
await run(getProjectRoot());
|
|
66
86
|
return;
|
|
@@ -103,15 +123,15 @@ function registerFurnaceInfoCommands(furnace, context) {
|
|
|
103
123
|
}));
|
|
104
124
|
registerFurnaceApplyCommand(furnace, context);
|
|
105
125
|
registerFurnaceDeployCommand(furnace, context);
|
|
106
|
-
furnace
|
|
126
|
+
const scan = furnace
|
|
107
127
|
.command('scan')
|
|
108
128
|
.description('Scan engine for available components. Report-only by default: persist the discovered ' +
|
|
109
129
|
'inventory into the stock section of furnace.json with --track (or the interactive ' +
|
|
110
130
|
'prompt); deploy/validate consume the inventory from there.')
|
|
111
131
|
.option('--deep', 'Search additional Firefox directories beyond the default widgets path')
|
|
112
|
-
.option('--track', 'Persist every discovered untracked component into the stock section of furnace.json (non-interactive)')
|
|
113
|
-
|
|
114
|
-
await furnaceScanCommand(getProjectRoot(),
|
|
132
|
+
.option('--track', 'Persist every discovered untracked component into the stock section of furnace.json (non-interactive)');
|
|
133
|
+
addWaitLockOption(scan).action(withErrorHandling(async (options) => {
|
|
134
|
+
await furnaceScanCommand(getProjectRoot(), withFurnaceLockBudget(options));
|
|
115
135
|
}));
|
|
116
136
|
furnace
|
|
117
137
|
.command('init')
|
|
@@ -122,7 +142,7 @@ function registerFurnaceInfoCommands(furnace, context) {
|
|
|
122
142
|
.action(withErrorHandling(async (options) => {
|
|
123
143
|
await furnaceInitCommand(getProjectRoot(), options);
|
|
124
144
|
}));
|
|
125
|
-
furnace
|
|
145
|
+
const create = furnace
|
|
126
146
|
.command('create [name]')
|
|
127
147
|
.description('Create a new custom component')
|
|
128
148
|
.option('-d, --description <desc>', 'Component description')
|
|
@@ -140,9 +160,9 @@ function registerFurnaceInfoCommands(furnace, context) {
|
|
|
140
160
|
.option('--compose <tags>', 'Record stock tags composed internally (metadata only, comma-separated)', (val) => val.split(',').map((s) => s.trim()))
|
|
141
161
|
.option('--shared-ftl <path>', 'Participate in an existing feature-scoped .ftl at this path (e.g. "browser/mybrowser-dock.ftl"); skips the per-component .ftl scaffold (implies --localized)')
|
|
142
162
|
.option('--dry-run', 'Show the planned file set and furnace.json changes without writing')
|
|
143
|
-
.option('--allow-prefix-mismatch', 'Create the component even when its name does not start with the configured `componentPrefix` in furnace.json. Without this flag the command refuses to write anything on a prefix mismatch.')
|
|
144
|
-
|
|
145
|
-
await furnaceCreateCommand(getProjectRoot(), name, options);
|
|
163
|
+
.option('--allow-prefix-mismatch', 'Create the component even when its name does not start with the configured `componentPrefix` in furnace.json. Without this flag the command refuses to write anything on a prefix mismatch.');
|
|
164
|
+
addWaitLockOption(create).action(withErrorHandling(async (name, options) => {
|
|
165
|
+
await furnaceCreateCommand(getProjectRoot(), name, withFurnaceLockBudget(options));
|
|
146
166
|
}));
|
|
147
167
|
registerChromeDocCommands(furnace, context);
|
|
148
168
|
}
|
|
@@ -151,23 +171,23 @@ function registerChromeDocCommands(furnace, context) {
|
|
|
151
171
|
const chromeDoc = furnace
|
|
152
172
|
.command('chrome-doc')
|
|
153
173
|
.description('Scaffold top-level chrome documents (xhtml + js + css + ftl + jar.mn)');
|
|
154
|
-
chromeDoc
|
|
174
|
+
const chromeDocCreate = chromeDoc
|
|
155
175
|
.command('create <name>')
|
|
156
176
|
.description('Scaffold a new top-level chrome document')
|
|
157
177
|
.option('--no-titlebar', 'Frameless overlay-style document (omits titlebar-buttonbox)')
|
|
158
178
|
.option('--browser-window', 'Emit the browser.xhtml-like main-window skeleton (<html id="main-window"> with windowtype/chromehidden/persist root attributes platform C++ reads before scripts run) for the document configured as the fork\'s main browser window; implies the titlebar markup')
|
|
159
179
|
.option('--with-tests', 'Scaffold an xpcshell packaging-verification test that probes XCurProcD/chrome/browser/... directly (bypasses the xpcshell chrome:// URI limitation).')
|
|
160
|
-
.option('--dry-run', 'Show the chrome-doc scaffold plan without writing')
|
|
161
|
-
|
|
162
|
-
await furnaceChromeDocCreateCommand(getProjectRoot(), name,
|
|
180
|
+
.option('--dry-run', 'Show the chrome-doc scaffold plan without writing');
|
|
181
|
+
addWaitLockOption(chromeDocCreate).action(withErrorHandling(async (name, options) => {
|
|
182
|
+
await furnaceChromeDocCreateCommand(getProjectRoot(), name, withFurnaceLockBudget(options));
|
|
163
183
|
}));
|
|
164
|
-
chromeDoc
|
|
184
|
+
const chromeDocRemove = chromeDoc
|
|
165
185
|
.command('remove <name>')
|
|
166
186
|
.description('Remove a scaffolded top-level chrome document')
|
|
167
187
|
.option('-y, --yes', 'Skip confirmation')
|
|
168
|
-
.option('--dry-run', 'Show the chrome-doc removal plan without writing')
|
|
169
|
-
|
|
170
|
-
await furnaceChromeDocRemoveCommand(getProjectRoot(), name,
|
|
188
|
+
.option('--dry-run', 'Show the chrome-doc removal plan without writing');
|
|
189
|
+
addWaitLockOption(chromeDocRemove).action(withErrorHandling(async (name, options) => {
|
|
190
|
+
await furnaceChromeDocRemoveCommand(getProjectRoot(), name, withFurnaceLockBudget(options));
|
|
171
191
|
}));
|
|
172
192
|
}
|
|
173
193
|
/**
|
|
@@ -178,12 +198,13 @@ function registerChromeDocCommands(furnace, context) {
|
|
|
178
198
|
*/
|
|
179
199
|
function registerFurnaceModifyCommands(furnace, context) {
|
|
180
200
|
const { getProjectRoot, withErrorHandling } = context;
|
|
181
|
-
furnace
|
|
201
|
+
const override = furnace
|
|
182
202
|
.command('override [names...]')
|
|
183
203
|
.description('Fork one or more existing components for modification')
|
|
184
204
|
.addOption(new Option('-t, --type <type>', 'Override type').choices(['css-only', 'full']))
|
|
185
|
-
.option('-d, --description <desc>', 'Description')
|
|
186
|
-
|
|
205
|
+
.option('-d, --description <desc>', 'Description');
|
|
206
|
+
addWaitLockOption(override).action(withErrorHandling(async (names, rawOptions) => {
|
|
207
|
+
const options = withFurnaceLockBudget(rawOptions);
|
|
187
208
|
if (names.length <= 1) {
|
|
188
209
|
await furnaceOverrideCommand(getProjectRoot(), names[0], options);
|
|
189
210
|
}
|
|
@@ -198,26 +219,29 @@ function registerFurnaceModifyCommands(furnace, context) {
|
|
|
198
219
|
.action(withErrorHandling(async (options) => {
|
|
199
220
|
await furnaceListCommand(getProjectRoot(), options);
|
|
200
221
|
}));
|
|
201
|
-
furnace
|
|
222
|
+
const remove = furnace
|
|
202
223
|
.command('remove <name>')
|
|
203
224
|
.description('Remove a component from the workspace')
|
|
204
|
-
.option('-y, --yes', 'Skip confirmation')
|
|
205
|
-
|
|
206
|
-
await furnaceRemoveCommand(getProjectRoot(), name, options);
|
|
225
|
+
.option('-y, --yes', 'Skip confirmation');
|
|
226
|
+
addWaitLockOption(remove).action(withErrorHandling(async (name, options) => {
|
|
227
|
+
await furnaceRemoveCommand(getProjectRoot(), name, withFurnaceLockBudget(options));
|
|
207
228
|
}));
|
|
208
|
-
furnace
|
|
229
|
+
const preview = furnace
|
|
209
230
|
.command('preview')
|
|
210
231
|
.description('Start component preview (Storybook)')
|
|
211
|
-
.option('--install', 'Force reinstall Storybook dependencies')
|
|
212
|
-
|
|
213
|
-
await furnacePreviewCommand(getProjectRoot(), options);
|
|
232
|
+
.option('--install', 'Force reinstall Storybook dependencies');
|
|
233
|
+
addWaitLockOption(preview).action(withErrorHandling(async (options) => {
|
|
234
|
+
await furnacePreviewCommand(getProjectRoot(), withFurnaceLockBudget(options));
|
|
214
235
|
}));
|
|
215
236
|
furnace
|
|
216
237
|
.command('validate [name]')
|
|
217
238
|
.description('Run accessibility and compatibility checks')
|
|
218
239
|
.option('--fix', 'Auto-fix registration issues (missing jar.mn entries, customElements.js)')
|
|
240
|
+
.option('--json', 'Write the result as one JSON document (findings, excepted findings, stale exceptions, verdict) to stdout')
|
|
241
|
+
.option('--max-warnings <n>', 'Fail when more than <n> warnings remain after furnace.json validationExceptions (0 for a warning-clean gate)')
|
|
219
242
|
.action(withErrorHandling(async (name, options) => {
|
|
220
|
-
|
|
243
|
+
const { maxWarnings, ...rest } = options ?? {};
|
|
244
|
+
await furnaceValidateCommand(getProjectRoot(), name, pickDefined({ ...rest, maxWarnings: parseMaxWarnings(maxWarnings) }));
|
|
221
245
|
}));
|
|
222
246
|
furnace
|
|
223
247
|
.command('diff [name]')
|
|
@@ -225,21 +249,22 @@ function registerFurnaceModifyCommands(furnace, context) {
|
|
|
225
249
|
.action(withErrorHandling(async (name) => {
|
|
226
250
|
await furnaceDiffCommand(getProjectRoot(), name);
|
|
227
251
|
}));
|
|
228
|
-
furnace
|
|
252
|
+
const refresh = furnace
|
|
229
253
|
.command('refresh [name]')
|
|
230
254
|
.description('Merge upstream Firefox changes into overrides (three-way merge)')
|
|
231
255
|
.option('--dry-run', 'Show what would change without modifying files')
|
|
232
256
|
.option('-a, --all', 'Refresh all overrides in a single batch')
|
|
233
257
|
.addOption(new Option('-s, --strategy <strategy>', 'Auto-resolve conflicts (ours = keep local, theirs = accept upstream)').choices(['ours', 'theirs']))
|
|
234
|
-
.option('--reset-base', 'Reset baseline to current engine HEAD (skips three-way merge, recovers from missing baseCommit)')
|
|
235
|
-
|
|
236
|
-
await furnaceRefreshCommand(getProjectRoot(), name,
|
|
258
|
+
.option('--reset-base', 'Reset baseline to current engine HEAD (skips three-way merge, recovers from missing baseCommit)');
|
|
259
|
+
addWaitLockOption(refresh).action(withErrorHandling(async (name, options) => {
|
|
260
|
+
await furnaceRefreshCommand(getProjectRoot(), name, withFurnaceLockBudget(options));
|
|
237
261
|
}));
|
|
238
|
-
furnace
|
|
262
|
+
const rename = furnace
|
|
239
263
|
.command('rename <old-name> <new-name>')
|
|
240
264
|
.description('Rename a component (updates files, config, and registrations)')
|
|
241
|
-
.
|
|
242
|
-
|
|
265
|
+
.option('--dry-run', 'Show the planned file moves, furnace.json change and engine registration edits without writing');
|
|
266
|
+
addWaitLockOption(rename).action(withErrorHandling(async (oldName, newName, options) => {
|
|
267
|
+
await furnaceRenameCommand(getProjectRoot(), oldName, newName, withFurnaceLockBudget(options));
|
|
243
268
|
}));
|
|
244
269
|
registerFurnaceSyncCommand(furnace, context);
|
|
245
270
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { stat } from 'node:fs/promises';
|
|
3
3
|
import { basename, dirname, isAbsolute, join, posix } from 'node:path';
|
|
4
4
|
import { text } from '@clack/prompts';
|
|
5
|
-
import { getProjectPaths, loadConfig, mutateConfig,
|
|
5
|
+
import { getProjectPaths, loadConfig, loadRawConfigDocument, mutateConfig, validateConfig, withConfigFileLock, writeConfigDocument, } from '../../core/config.js';
|
|
6
6
|
import { stdioIsInteractive } from '../../core/destructive.js';
|
|
7
7
|
import { createDefaultFurnaceConfig, furnaceConfigExists, writeFurnaceConfig, } from '../../core/furnace-config.js';
|
|
8
8
|
import { DEFAULT_LICENSE } from '../../core/license-headers.js';
|
|
@@ -239,14 +239,21 @@ async function scaffoldTokensCss(projectRoot) {
|
|
|
239
239
|
// `fireforge lint` after a `token add` fails on raw-color-value issues for
|
|
240
240
|
// tokens the operator just created. The add is idempotent, so re-running
|
|
241
241
|
// `furnace init --force` does not duplicate the entry.
|
|
242
|
+
// The edit seeds from the raw document under the config lock, like
|
|
243
|
+
// `fireforge config`: a validated round-trip would drop keys written with
|
|
244
|
+
// `config --force`, and an unlocked one could lose a concurrent write.
|
|
242
245
|
try {
|
|
243
246
|
const existingAllowlist = forgeConfig.patchLint?.rawColorAllowlist ?? [];
|
|
244
247
|
if (!existingAllowlist.includes(tokensCssPath)) {
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
248
|
+
await withConfigFileLock(projectRoot, async () => {
|
|
249
|
+
const raw = await loadRawConfigDocument(projectRoot);
|
|
250
|
+
const current = validateConfig(raw).patchLint?.rawColorAllowlist ?? [];
|
|
251
|
+
if (current.includes(tokensCssPath))
|
|
252
|
+
return;
|
|
253
|
+
const updated = mutateConfig(raw, 'patchLint.rawColorAllowlist', [...current, tokensCssPath], true);
|
|
254
|
+
validateConfig(updated);
|
|
255
|
+
await writeConfigDocument(projectRoot, updated);
|
|
256
|
+
});
|
|
250
257
|
info(`Added ${tokensCssPath} to patchLint.rawColorAllowlist`);
|
|
251
258
|
}
|
|
252
259
|
}
|
|
@@ -6,7 +6,7 @@ import { getProjectPaths, loadConfig, loadState } from '../../core/config.js';
|
|
|
6
6
|
import { stdioIsInteractive } from '../../core/destructive.js';
|
|
7
7
|
import { getFurnacePaths, writeFurnaceConfig } from '../../core/furnace-config.js';
|
|
8
8
|
import { resolveFtlDir } from '../../core/furnace-constants.js';
|
|
9
|
-
import { completeJournalRollback, runFurnaceMutation } from '../../core/furnace-operation.js';
|
|
9
|
+
import { completeJournalRollback, runFurnaceMutation, waitLockMutationOptions, } from '../../core/furnace-operation.js';
|
|
10
10
|
import { assertFurnaceEngineReady } from '../../core/furnace-precondition.js';
|
|
11
11
|
import { CUSTOM_ELEMENT_TAG_PATTERN, CUSTOM_ELEMENT_TAG_RULES, } from '../../core/furnace-registration-validate.js';
|
|
12
12
|
import { createRollbackJournal, recordCreatedDir, snapshotFile, } from '../../core/furnace-rollback.js';
|
|
@@ -160,7 +160,7 @@ async function performOverrideMutations(args) {
|
|
|
160
160
|
subject: `component "${args.componentName}"`,
|
|
161
161
|
});
|
|
162
162
|
}
|
|
163
|
-
});
|
|
163
|
+
}, waitLockMutationOptions(args.waitLockSeconds));
|
|
164
164
|
}
|
|
165
165
|
/**
|
|
166
166
|
* Throws if `componentName` is already classified as something `override`
|
|
@@ -322,6 +322,7 @@ export async function furnaceOverrideCommand(projectRoot, name, options = {}) {
|
|
|
322
322
|
ftlDir,
|
|
323
323
|
firefoxVersion: forgeConfig.firefox.version,
|
|
324
324
|
...(state.baseCommit ? { baseCommit: state.baseCommit } : {}),
|
|
325
|
+
waitLockSeconds: options.waitLockSeconds,
|
|
325
326
|
});
|
|
326
327
|
// --- Success ---
|
|
327
328
|
note(`Files copied to components/overrides/${componentName}/:\n` +
|
|
@@ -421,6 +422,7 @@ export async function furnaceBatchOverrideCommand(projectRoot, names, options =
|
|
|
421
422
|
ftlDir,
|
|
422
423
|
firefoxVersion: forgeConfig.firefox.version,
|
|
423
424
|
...(state.baseCommit ? { baseCommit: state.baseCommit } : {}),
|
|
425
|
+
waitLockSeconds: options.waitLockSeconds,
|
|
424
426
|
});
|
|
425
427
|
succeeded.push(componentName);
|
|
426
428
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { applyAllComponents } from '../../core/furnace-apply.js';
|
|
4
4
|
import { updateFurnaceState } from '../../core/furnace-config.js';
|
|
5
|
-
import { runFurnaceMutation } from '../../core/furnace-operation.js';
|
|
5
|
+
import { runFurnaceMutation, waitLockMutationOptions, } from '../../core/furnace-operation.js';
|
|
6
6
|
import { assertFurnaceReady } from '../../core/furnace-precondition.js';
|
|
7
7
|
import { restoreRollbackJournal } from '../../core/furnace-rollback.js';
|
|
8
8
|
import { countEntriesWithBlockingStepErrors } from '../../core/furnace-step-errors.js';
|
|
@@ -224,7 +224,7 @@ export async function furnacePreviewCommand(projectRoot, options = {}) {
|
|
|
224
224
|
// entrypoint's global signal handlers consulting the lifecycle registry.
|
|
225
225
|
// The body's own try/catch + teardown path handles the normal exit case
|
|
226
226
|
// (mach storybook returns or throws).
|
|
227
|
-
|
|
227
|
+
const mutate = async (ctx) => {
|
|
228
228
|
// Register the stories cleanup as an extra teardown hook so the signal
|
|
229
229
|
// handler can wipe the staged stories directory in addition to the
|
|
230
230
|
// journal restore.
|
|
@@ -336,7 +336,8 @@ export async function furnacePreviewCommand(projectRoot, options = {}) {
|
|
|
336
336
|
// holds and downstream formatters always see a message/stack pair.
|
|
337
337
|
throw toError(primaryError);
|
|
338
338
|
}
|
|
339
|
-
}
|
|
339
|
+
};
|
|
340
|
+
await runFurnaceMutation(projectRoot, 'preview-teardown', mutate, waitLockMutationOptions(options.waitLockSeconds));
|
|
340
341
|
if (previewResult &&
|
|
341
342
|
previewResult.exitCode !== 0 &&
|
|
342
343
|
previewResult.exitCode !== 130 &&
|
|
@@ -6,7 +6,7 @@ import { getOverrideEngineTargetPath } from '../../core/furnace-apply-helpers.js
|
|
|
6
6
|
import { getFurnacePaths, loadFurnaceConfig, writeFurnaceConfig, } from '../../core/furnace-config.js';
|
|
7
7
|
import { resolveFtlDir } from '../../core/furnace-constants.js';
|
|
8
8
|
import { isComponentSourceFile } from '../../core/furnace-constants.js';
|
|
9
|
-
import { completeJournalRollback, runFurnaceMutation } from '../../core/furnace-operation.js';
|
|
9
|
+
import { completeJournalRollback, runFurnaceMutation, waitLockMutationOptions, } from '../../core/furnace-operation.js';
|
|
10
10
|
import { assertFurnaceEngineReady } from '../../core/furnace-precondition.js';
|
|
11
11
|
import { refreshOverrideFile } from '../../core/furnace-refresh.js';
|
|
12
12
|
import { createRollbackJournal, restoreRollbackJournal, snapshotDir, snapshotFile, } from '../../core/furnace-rollback.js';
|
|
@@ -165,7 +165,7 @@ async function refreshSingleOverride(projectRoot, name, options = {}) {
|
|
|
165
165
|
}
|
|
166
166
|
throw error;
|
|
167
167
|
}
|
|
168
|
-
}, { dryRun });
|
|
168
|
+
}, { dryRun, ...waitLockMutationOptions(options.waitLockSeconds) });
|
|
169
169
|
return { results, currentVersion };
|
|
170
170
|
}
|
|
171
171
|
/**
|
|
@@ -6,7 +6,7 @@ import { getProjectPaths, loadConfig } from '../../core/config.js';
|
|
|
6
6
|
import { stdioIsInteractive } from '../../core/destructive.js';
|
|
7
7
|
import { getFurnacePaths, loadFurnaceConfig, loadFurnaceState, updateFurnaceState, writeFurnaceConfig, } from '../../core/furnace-config.js';
|
|
8
8
|
import { resolveFtlDir, xpcshellTestParentDir } from '../../core/furnace-constants.js';
|
|
9
|
-
import { completeJournalRollback, runFurnaceMutation } from '../../core/furnace-operation.js';
|
|
9
|
+
import { completeJournalRollback, runFurnaceMutation, waitLockMutationOptions, } from '../../core/furnace-operation.js';
|
|
10
10
|
import { createRollbackJournal, snapshotDir, snapshotFile, } from '../../core/furnace-rollback.js';
|
|
11
11
|
import { isGitRepository } from '../../core/git.js';
|
|
12
12
|
import { deregisterTestManifest } from '../../core/moz-manifest-register.js';
|
|
@@ -343,7 +343,7 @@ export async function furnaceRemoveCommand(projectRoot, name, options = {}) {
|
|
|
343
343
|
// rollback pathway.
|
|
344
344
|
const paths = getProjectPaths(projectRoot);
|
|
345
345
|
await requireGitEngineForRemove(type, name, paths.engine);
|
|
346
|
-
|
|
346
|
+
const mutate = async (ctx) => {
|
|
347
347
|
const journal = createRollbackJournal();
|
|
348
348
|
ctx.registerJournal(journal);
|
|
349
349
|
try {
|
|
@@ -408,7 +408,8 @@ export async function furnaceRemoveCommand(projectRoot, name, options = {}) {
|
|
|
408
408
|
subject: `component "${name}"`,
|
|
409
409
|
});
|
|
410
410
|
}
|
|
411
|
-
}
|
|
411
|
+
};
|
|
412
|
+
await runFurnaceMutation(projectRoot, 'remove-rollback', mutate, waitLockMutationOptions(options.waitLockSeconds));
|
|
412
413
|
info(`Removed "${name}" from furnace.json`);
|
|
413
414
|
outro('Component removed');
|
|
414
415
|
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `furnace rename --dry-run`: the plan a rename would carry out, rendered
|
|
3
|
+
* from reads only. A rename edits three engine registration files besides
|
|
4
|
+
* moving the component, and before this none of those edits was visible
|
|
5
|
+
* until it had run.
|
|
6
|
+
*/
|
|
7
|
+
import type { FurnaceConfig } from '../../types/furnace.js';
|
|
8
|
+
/** Inputs for {@link renderRenamePlan}. */
|
|
9
|
+
export interface RenamePlanInput {
|
|
10
|
+
config: FurnaceConfig;
|
|
11
|
+
oldName: string;
|
|
12
|
+
newName: string;
|
|
13
|
+
/** Workspace directory of the component being renamed. */
|
|
14
|
+
oldDir: string;
|
|
15
|
+
/** On-disk directory label: `custom` or `overrides`. */
|
|
16
|
+
componentDirLabel: 'custom' | 'overrides';
|
|
17
|
+
engineDir: string;
|
|
18
|
+
/** Project marker a freshly added registration line would carry. */
|
|
19
|
+
markerComment: string | undefined;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Renders the rename plan: workspace file moves, the furnace.json re-key,
|
|
23
|
+
* and, for a custom component, every engine edit the real run would make
|
|
24
|
+
* (registrations only when the component is registered).
|
|
25
|
+
*
|
|
26
|
+
* @param input - See {@link RenamePlanInput}
|
|
27
|
+
* @returns The plan as display lines joined by newlines
|
|
28
|
+
*/
|
|
29
|
+
export declare function renderRenamePlan(input: RenamePlanInput): Promise<string>;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
+
/**
|
|
3
|
+
* `furnace rename --dry-run`: the plan a rename would carry out, rendered
|
|
4
|
+
* from reads only. A rename edits three engine registration files besides
|
|
5
|
+
* moving the component, and before this none of those edits was visible
|
|
6
|
+
* until it had run.
|
|
7
|
+
*/
|
|
8
|
+
import { readdir } from 'node:fs/promises';
|
|
9
|
+
import { join } from 'node:path';
|
|
10
|
+
import { isComponentSourceFile, JAR_MN, resolveFtlChromeSubPath, resolveFtlDir, resolveFtlLocaleJarMnPath, } from '../../core/furnace-constants.js';
|
|
11
|
+
import { hasLocaleFtlJarMnEntry } from '../../core/furnace-registration.js';
|
|
12
|
+
import { isTagAlreadyRegistered } from '../../core/furnace-registration-ast.js';
|
|
13
|
+
import { pathExists, readText } from '../../utils/fs.js';
|
|
14
|
+
import { renameComponentFileName, renameTagInDescription } from './rename-helpers.js';
|
|
15
|
+
/** Plan lines for the workspace move and the furnace.json re-key. */
|
|
16
|
+
async function workspaceLines(input) {
|
|
17
|
+
const { config, oldName, newName, oldDir, componentDirLabel } = input;
|
|
18
|
+
const lines = [
|
|
19
|
+
`Workspace: components/${componentDirLabel}/${oldName}/ → components/${componentDirLabel}/${newName}/`,
|
|
20
|
+
];
|
|
21
|
+
const entries = (await readdir(oldDir, { withFileTypes: true }))
|
|
22
|
+
.filter((entry) => entry.isFile())
|
|
23
|
+
.map((entry) => entry.name)
|
|
24
|
+
.sort();
|
|
25
|
+
for (const fileName of entries) {
|
|
26
|
+
const renamed = renameComponentFileName(fileName, oldName, newName);
|
|
27
|
+
const rewrite = isComponentSourceFile(fileName) ? ' (tag and class references rewritten)' : '';
|
|
28
|
+
lines.push(` ${fileName}${renamed === fileName ? '' : ` → ${renamed}`}${rewrite}`);
|
|
29
|
+
}
|
|
30
|
+
const entry = config.custom[oldName] ?? config.overrides[oldName];
|
|
31
|
+
lines.push(`furnace.json: "${oldName}" → "${newName}"`);
|
|
32
|
+
if (entry) {
|
|
33
|
+
const description = renameTagInDescription(entry.description, oldName, newName);
|
|
34
|
+
if (description !== entry.description) {
|
|
35
|
+
lines.push(` description: "${entry.description}" → "${description}"`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return lines;
|
|
39
|
+
}
|
|
40
|
+
/** Plan line for the customElements.js registration. */
|
|
41
|
+
async function customElementsLine(input) {
|
|
42
|
+
const { engineDir, oldName, newName, markerComment } = input;
|
|
43
|
+
const path = join(engineDir, 'toolkit/content/customElements.js');
|
|
44
|
+
if (!(await pathExists(path)))
|
|
45
|
+
return undefined;
|
|
46
|
+
const content = await readText(path);
|
|
47
|
+
const oldRegistered = isTagAlreadyRegistered(content, oldName);
|
|
48
|
+
if (isTagAlreadyRegistered(content, newName)) {
|
|
49
|
+
return `customElements.js: "${newName}" is already registered${oldRegistered ? `; remove the "${oldName}" entry` : ''}`;
|
|
50
|
+
}
|
|
51
|
+
if (oldRegistered) {
|
|
52
|
+
return `customElements.js: rewrite the "${oldName}" entry in place as "${newName}" (position and marker comments kept)`;
|
|
53
|
+
}
|
|
54
|
+
const marker = markerComment !== undefined ? ` marked // ${markerComment}:` : '';
|
|
55
|
+
return `customElements.js: add a "${newName}" entry${marker}`;
|
|
56
|
+
}
|
|
57
|
+
/** Plan line for the toolkit/content/jar.mn widget lines. */
|
|
58
|
+
async function jarLine(input) {
|
|
59
|
+
const { engineDir, oldName, newName, oldDir } = input;
|
|
60
|
+
const path = join(engineDir, JAR_MN);
|
|
61
|
+
if (!(await pathExists(path)))
|
|
62
|
+
return undefined;
|
|
63
|
+
const oldLines = (await readText(path))
|
|
64
|
+
.split('\n')
|
|
65
|
+
.filter((line) => line.includes(`(widgets/${oldName}/`)).length;
|
|
66
|
+
const newFiles = (await readdir(oldDir, { withFileTypes: true }))
|
|
67
|
+
.filter((entry) => entry.isFile() && /\.(?:mjs|css)$/.test(entry.name))
|
|
68
|
+
.map((entry) => renameComponentFileName(entry.name, oldName, newName))
|
|
69
|
+
.sort();
|
|
70
|
+
return (`${JAR_MN}: replace ${oldLines} "${oldName}" line(s) with ` +
|
|
71
|
+
(newFiles.length > 0 ? newFiles.join(', ') : 'none (no .mjs/.css files)'));
|
|
72
|
+
}
|
|
73
|
+
/** Plan lines for the deployed .ftl and its locale jar.mn line. */
|
|
74
|
+
async function localeLines(input, componentConfig) {
|
|
75
|
+
const { config, engineDir, oldName, newName } = input;
|
|
76
|
+
if (!componentConfig.localized)
|
|
77
|
+
return [];
|
|
78
|
+
const ftlDir = resolveFtlDir(config.ftlBasePath);
|
|
79
|
+
const lines = [];
|
|
80
|
+
if (await pathExists(join(engineDir, ftlDir, `${oldName}.ftl`))) {
|
|
81
|
+
lines.push(`${ftlDir}/${oldName}.ftl → ${newName}.ftl`);
|
|
82
|
+
}
|
|
83
|
+
const chromeSubPath = resolveFtlChromeSubPath(ftlDir);
|
|
84
|
+
const localeJarRel = resolveFtlLocaleJarMnPath(ftlDir);
|
|
85
|
+
if (chromeSubPath === undefined || localeJarRel === undefined)
|
|
86
|
+
return lines;
|
|
87
|
+
const present = await hasLocaleFtlJarMnEntry(engineDir, localeJarRel, oldName, chromeSubPath);
|
|
88
|
+
if (componentConfig.sharedFtl !== undefined) {
|
|
89
|
+
lines.push(`${localeJarRel}: no per-component line (sharedFtl: ${componentConfig.sharedFtl})` +
|
|
90
|
+
(present ? `; remove the stale "${oldName}.ftl" line` : ''));
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
lines.push(present
|
|
94
|
+
? `${localeJarRel}: re-point the "${oldName}.ftl" line to "${newName}.ftl"`
|
|
95
|
+
: `${localeJarRel}: no "${oldName}.ftl" line to re-point (left unchanged)`);
|
|
96
|
+
}
|
|
97
|
+
return lines;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Renders the rename plan: workspace file moves, the furnace.json re-key,
|
|
101
|
+
* and, for a custom component, every engine edit the real run would make
|
|
102
|
+
* (registrations only when the component is registered).
|
|
103
|
+
*
|
|
104
|
+
* @param input - See {@link RenamePlanInput}
|
|
105
|
+
* @returns The plan as display lines joined by newlines
|
|
106
|
+
*/
|
|
107
|
+
export async function renderRenamePlan(input) {
|
|
108
|
+
const lines = await workspaceLines(input);
|
|
109
|
+
const componentConfig = input.config.custom[input.oldName];
|
|
110
|
+
if (!componentConfig || !(await pathExists(input.engineDir))) {
|
|
111
|
+
return lines.join('\n');
|
|
112
|
+
}
|
|
113
|
+
lines.push('Engine:');
|
|
114
|
+
const engineLines = componentConfig.register
|
|
115
|
+
? [
|
|
116
|
+
await customElementsLine(input),
|
|
117
|
+
await jarLine(input),
|
|
118
|
+
...(await localeLines(input, componentConfig)),
|
|
119
|
+
].filter((line) => line !== undefined)
|
|
120
|
+
: ['registrations untouched (register: false)'];
|
|
121
|
+
if (await pathExists(join(input.engineDir, componentConfig.targetPath))) {
|
|
122
|
+
engineLines.push(`remove the stale deployed directory ${componentConfig.targetPath}/`);
|
|
123
|
+
}
|
|
124
|
+
lines.push(...engineLines.map((line) => ` ${line}`));
|
|
125
|
+
lines.push('Test scaffolds named after the old tag are renamed when present.');
|
|
126
|
+
return lines.join('\n');
|
|
127
|
+
}
|
|
@@ -3,6 +3,13 @@ import type { FurnaceConfig } from '../../types/furnace.js';
|
|
|
3
3
|
* Applies a component rename to scaffold-owned filenames only.
|
|
4
4
|
*/
|
|
5
5
|
export declare function renameComponentFileName(fileName: string, oldName: string, newName: string): string;
|
|
6
|
+
/**
|
|
7
|
+
* Rewrites whole-tag mentions of the old name in a component description,
|
|
8
|
+
* so a rename does not carry a description that still names the old tag.
|
|
9
|
+
* Boundary-aware like the source rewrite: `moz-panel` inside
|
|
10
|
+
* `moz-panel-group` is left alone.
|
|
11
|
+
*/
|
|
12
|
+
export declare function renameTagInDescription(description: string, oldName: string, newName: string): string;
|
|
6
13
|
/**
|
|
7
14
|
* Re-keys a custom component config entry and same-config compose references.
|
|
8
15
|
*/
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// SPDX-License-Identifier: EUPL-1.2
|
|
2
2
|
import { updateFurnaceState } from '../../core/furnace-config.js';
|
|
3
|
+
import { escapeRegex } from '../../utils/regex.js';
|
|
3
4
|
/**
|
|
4
5
|
* Applies a component rename to scaffold-owned filenames only.
|
|
5
6
|
*/
|
|
@@ -11,6 +12,15 @@ export function renameComponentFileName(fileName, oldName, newName) {
|
|
|
11
12
|
}
|
|
12
13
|
return fileName;
|
|
13
14
|
}
|
|
15
|
+
/**
|
|
16
|
+
* Rewrites whole-tag mentions of the old name in a component description,
|
|
17
|
+
* so a rename does not carry a description that still names the old tag.
|
|
18
|
+
* Boundary-aware like the source rewrite: `moz-panel` inside
|
|
19
|
+
* `moz-panel-group` is left alone.
|
|
20
|
+
*/
|
|
21
|
+
export function renameTagInDescription(description, oldName, newName) {
|
|
22
|
+
return description.replace(new RegExp(`(?<![\\w-])${escapeRegex(oldName)}(?![\\w-])`, 'g'), newName);
|
|
23
|
+
}
|
|
14
24
|
/**
|
|
15
25
|
* Re-keys a custom component config entry and same-config compose references.
|
|
16
26
|
*/
|
|
@@ -20,6 +30,7 @@ export function updateConfigForCustomRename(config, oldName, newName) {
|
|
|
20
30
|
return;
|
|
21
31
|
config.custom[newName] = {
|
|
22
32
|
...oldConfig,
|
|
33
|
+
description: renameTagInDescription(oldConfig.description, oldName, newName),
|
|
23
34
|
targetPath: oldConfig.targetPath.replace(new RegExp(`(^|/)${oldName}$`), `$1${newName}`),
|
|
24
35
|
};
|
|
25
36
|
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete -- idiomatic key removal from config record
|
|
@@ -37,7 +48,10 @@ export function updateConfigForOverrideRename(config, oldName, newName) {
|
|
|
37
48
|
const oldConfig = config.overrides[oldName];
|
|
38
49
|
if (!oldConfig)
|
|
39
50
|
return;
|
|
40
|
-
config.overrides[newName] = {
|
|
51
|
+
config.overrides[newName] = {
|
|
52
|
+
...oldConfig,
|
|
53
|
+
description: renameTagInDescription(oldConfig.description, oldName, newName),
|
|
54
|
+
};
|
|
41
55
|
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete -- idiomatic key removal from config record
|
|
42
56
|
delete config.overrides[oldName];
|
|
43
57
|
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Engine registration edits for `furnace rename`: the customElements.js
|
|
3
|
+
* entry (rewritten in place, keeping its marker comments), the
|
|
4
|
+
* toolkit/content/jar.mn widget lines, the deployed `.ftl`, and the locale
|
|
5
|
+
* jar.mn line (re-pointed only when one existed, never for `sharedFtl`).
|
|
6
|
+
*/
|
|
7
|
+
import { type RollbackJournal } from '../../core/furnace-rollback.js';
|
|
8
|
+
import type { CustomComponentConfig } from '../../types/furnace.js';
|
|
9
|
+
/**
|
|
10
|
+
* The project marker (`// <MARKER>:`) a registration line written by the
|
|
11
|
+
* rename carries, resolved exactly as `furnace apply` resolves it. An
|
|
12
|
+
* unreadable fireforge.json degrades to no marker rather than failing the
|
|
13
|
+
* rename.
|
|
14
|
+
*/
|
|
15
|
+
export declare function loadMarkerComment(projectRoot: string): Promise<string | undefined>;
|
|
16
|
+
/** Inputs for {@link updateEngineRegistrations}. */
|
|
17
|
+
export interface UpdateEngineRegistrationsOptions {
|
|
18
|
+
/** Absolute path to the engine checkout. */
|
|
19
|
+
engineDir: string;
|
|
20
|
+
/** Tag name being renamed away from. */
|
|
21
|
+
oldName: string;
|
|
22
|
+
/** Tag name being renamed to. */
|
|
23
|
+
newName: string;
|
|
24
|
+
/** Workspace directory holding the renamed component's files. */
|
|
25
|
+
newDir: string;
|
|
26
|
+
/** Engine-relative directory localized components deploy their `.ftl` into. */
|
|
27
|
+
ftlDir: string;
|
|
28
|
+
/** The renamed component's furnace.json entry (`localized`, `sharedFtl`). */
|
|
29
|
+
componentConfig: CustomComponentConfig;
|
|
30
|
+
/** Project marker for a registration line the rename has to add fresh. */
|
|
31
|
+
markerComment: string | undefined;
|
|
32
|
+
/** Rollback journal every write is recorded in. */
|
|
33
|
+
journal: RollbackJournal;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Re-points the engine-side registrations (customElements.js, jar.mn, and
|
|
37
|
+
* the localized `.ftl` entries) from the old tag name to the new one.
|
|
38
|
+
*
|
|
39
|
+
* @param options - See {@link UpdateEngineRegistrationsOptions}
|
|
40
|
+
*/
|
|
41
|
+
export declare function updateEngineRegistrations(options: UpdateEngineRegistrationsOptions): Promise<void>;
|