@hominis/fireforge 0.45.0 → 0.46.1
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 +409 -446
- package/dist/bin/fireforge.d.ts +1 -1
- package/dist/bin/fireforge.js +21 -15
- package/dist/build-info.json +4 -4
- package/dist/src/cli-usage-error.d.ts +46 -0
- package/dist/src/cli-usage-error.js +81 -0
- package/dist/src/cli.d.ts +7 -2
- package/dist/src/cli.js +47 -47
- package/dist/src/commands/bootstrap-checks.js +2 -1
- package/dist/src/commands/bootstrap.js +3 -4
- package/dist/src/commands/build.js +27 -17
- package/dist/src/commands/config.js +9 -9
- package/dist/src/commands/destructive-decision.d.ts +19 -0
- package/dist/src/commands/destructive-decision.js +31 -0
- package/dist/src/commands/discard.js +5 -5
- package/dist/src/commands/doctor-check-core.d.ts +4 -10
- package/dist/src/commands/doctor-check-core.js +0 -8
- package/dist/src/commands/doctor-external-toolchains.js +2 -2
- package/dist/src/commands/doctor-furnace-config-sync.d.ts +2 -2
- package/dist/src/commands/doctor-furnace-config-sync.js +20 -20
- package/dist/src/commands/doctor-furnace-jar.d.ts +1 -1
- package/dist/src/commands/doctor-furnace-jar.js +1 -1
- package/dist/src/commands/doctor-furnace.js +22 -22
- package/dist/src/commands/doctor-orphaned-harness.d.ts +10 -17
- package/dist/src/commands/doctor-orphaned-harness.js +14 -23
- package/dist/src/commands/doctor-patch-manifest.d.ts +2 -1
- package/dist/src/commands/doctor-patch-manifest.js +7 -6
- package/dist/src/commands/doctor-post-rebase-audit.js +3 -3
- package/dist/src/commands/doctor-source-pin.d.ts +12 -12
- package/dist/src/commands/doctor-source-pin.js +14 -14
- package/dist/src/commands/doctor-working-tree.d.ts +3 -3
- package/dist/src/commands/doctor-working-tree.js +3 -3
- package/dist/src/commands/doctor.d.ts +3 -1
- package/dist/src/commands/doctor.js +15 -16
- package/dist/src/commands/download.js +50 -37
- package/dist/src/commands/export-all.js +29 -12
- package/dist/src/commands/export-flow.d.ts +5 -5
- package/dist/src/commands/export-flow.js +29 -59
- package/dist/src/commands/export-placement-conflicts.d.ts +3 -3
- package/dist/src/commands/export-placement-conflicts.js +12 -12
- package/dist/src/commands/export-placement-gate.d.ts +2 -2
- package/dist/src/commands/export-placement-gate.js +7 -13
- package/dist/src/commands/export-placement-policy.d.ts +1 -1
- package/dist/src/commands/export-placement-policy.js +4 -6
- package/dist/src/commands/export-shared.d.ts +51 -32
- package/dist/src/commands/export-shared.js +17 -32
- package/dist/src/commands/export.js +14 -5
- package/dist/src/commands/furnace/apply.js +16 -16
- package/dist/src/commands/furnace/authoring-config.d.ts +13 -0
- package/dist/src/commands/furnace/authoring-config.js +19 -0
- package/dist/src/commands/furnace/chrome-doc-remove.d.ts +1 -1
- package/dist/src/commands/furnace/chrome-doc-remove.js +2 -2
- package/dist/src/commands/furnace/chrome-doc-templates.d.ts +14 -14
- package/dist/src/commands/furnace/chrome-doc-templates.js +17 -17
- package/dist/src/commands/furnace/chrome-doc-tests.d.ts +2 -2
- package/dist/src/commands/furnace/chrome-doc-tests.js +4 -4
- package/dist/src/commands/furnace/chrome-doc.d.ts +8 -8
- package/dist/src/commands/furnace/chrome-doc.js +18 -18
- package/dist/src/commands/furnace/create-browser-test.d.ts +1 -1
- package/dist/src/commands/furnace/create-browser-test.js +7 -12
- package/dist/src/commands/furnace/create-dry-run.d.ts +4 -4
- package/dist/src/commands/furnace/create-dry-run.js +6 -9
- package/dist/src/commands/furnace/create-features.d.ts +2 -2
- package/dist/src/commands/furnace/create-features.js +2 -2
- package/dist/src/commands/furnace/create-mochikit.d.ts +4 -4
- package/dist/src/commands/furnace/create-mochikit.js +7 -7
- package/dist/src/commands/furnace/create-templates.d.ts +31 -15
- package/dist/src/commands/furnace/create-templates.js +20 -19
- package/dist/src/commands/furnace/create-xpcshell.d.ts +5 -5
- package/dist/src/commands/furnace/create-xpcshell.js +8 -8
- package/dist/src/commands/furnace/create.d.ts +1 -1
- package/dist/src/commands/furnace/create.js +35 -29
- package/dist/src/commands/furnace/deploy.js +15 -6
- package/dist/src/commands/furnace/diff.js +7 -7
- package/dist/src/commands/furnace/index.js +1 -1
- package/dist/src/commands/furnace/init.js +17 -16
- package/dist/src/commands/furnace/list.js +2 -2
- package/dist/src/commands/furnace/override.d.ts +1 -1
- package/dist/src/commands/furnace/override.js +43 -34
- package/dist/src/commands/furnace/preview.js +17 -17
- package/dist/src/commands/furnace/refresh.js +15 -7
- package/dist/src/commands/furnace/remove-mutations.d.ts +9 -10
- package/dist/src/commands/furnace/remove-mutations.js +19 -19
- package/dist/src/commands/furnace/remove-state.d.ts +1 -1
- package/dist/src/commands/furnace/remove-state.js +1 -1
- package/dist/src/commands/furnace/remove.js +4 -8
- package/dist/src/commands/furnace/rename-browser-test.js +10 -15
- package/dist/src/commands/furnace/rename-xpcshell.d.ts +2 -2
- package/dist/src/commands/furnace/rename-xpcshell.js +3 -3
- package/dist/src/commands/furnace/rename.js +36 -36
- package/dist/src/commands/furnace/scan.js +3 -3
- package/dist/src/commands/furnace/status.js +19 -16
- package/dist/src/commands/furnace/sync.js +6 -6
- package/dist/src/commands/furnace/test-file-name.d.ts +28 -0
- package/dist/src/commands/furnace/test-file-name.js +39 -0
- package/dist/src/commands/furnace/validate.js +11 -12
- package/dist/src/commands/furnace/validation-output.d.ts +21 -9
- package/dist/src/commands/furnace/validation-output.js +3 -8
- package/dist/src/commands/import.js +22 -29
- package/dist/src/commands/lint-per-patch.d.ts +2 -2
- package/dist/src/commands/lint-per-patch.js +27 -12
- package/dist/src/commands/lint-per-run-checkjs.d.ts +14 -15
- package/dist/src/commands/lint-per-run-checkjs.js +14 -15
- package/dist/src/commands/lint-report.d.ts +3 -3
- package/dist/src/commands/lint-report.js +4 -4
- package/dist/src/commands/lint.d.ts +5 -4
- package/dist/src/commands/lint.js +36 -36
- package/dist/src/commands/manifest.d.ts +4 -4
- package/dist/src/commands/manifest.js +1 -1
- package/dist/src/commands/package.js +4 -6
- package/dist/src/commands/patch/compact.d.ts +2 -2
- package/dist/src/commands/patch/compact.js +19 -20
- package/dist/src/commands/patch/delete.d.ts +1 -1
- package/dist/src/commands/patch/delete.js +23 -33
- package/dist/src/commands/patch/entry-projection.d.ts +13 -0
- package/dist/src/commands/patch/entry-projection.js +24 -0
- package/dist/src/commands/patch/lint-ignore.d.ts +3 -12
- package/dist/src/commands/patch/lint-ignore.js +33 -44
- package/dist/src/commands/patch/move-files-create.d.ts +2 -2
- package/dist/src/commands/patch/move-files-create.js +29 -15
- package/dist/src/commands/patch/move-files-into.d.ts +2 -2
- package/dist/src/commands/patch/move-files-into.js +41 -37
- package/dist/src/commands/patch/move-files.js +5 -14
- package/dist/src/commands/patch/patch-context.d.ts +1 -1
- package/dist/src/commands/patch/rename.d.ts +4 -4
- package/dist/src/commands/patch/rename.js +35 -49
- package/dist/src/commands/patch/reorder.js +35 -48
- package/dist/src/commands/patch/split-plan.d.ts +7 -8
- package/dist/src/commands/patch/split-plan.js +10 -13
- package/dist/src/commands/patch/split.d.ts +2 -2
- package/dist/src/commands/patch/split.js +50 -48
- package/dist/src/commands/patch/staged-dependency-validate.d.ts +1 -1
- package/dist/src/commands/patch/staged-dependency-validate.js +3 -3
- package/dist/src/commands/patch/staged-dependency.d.ts +1 -1
- package/dist/src/commands/patch/staged-dependency.js +22 -28
- package/dist/src/commands/patch/tier.d.ts +2 -2
- package/dist/src/commands/patch/tier.js +20 -30
- package/dist/src/commands/patch-rename-map.d.ts +19 -0
- package/dist/src/commands/patch-rename-map.js +36 -0
- package/dist/src/commands/pending-resolution.d.ts +15 -0
- package/dist/src/commands/pending-resolution.js +25 -0
- package/dist/src/commands/re-export-adjacent.d.ts +25 -3
- package/dist/src/commands/re-export-adjacent.js +40 -24
- package/dist/src/commands/re-export-bulk-scan.d.ts +3 -3
- package/dist/src/commands/re-export-bulk-scan.js +23 -27
- package/dist/src/commands/re-export-drift.d.ts +10 -10
- package/dist/src/commands/re-export-drift.js +33 -33
- package/dist/src/commands/re-export-files.d.ts +2 -3
- package/dist/src/commands/re-export-files.js +52 -44
- package/dist/src/commands/re-export-lint.d.ts +29 -30
- package/dist/src/commands/re-export-lint.js +36 -29
- package/dist/src/commands/re-export-options.d.ts +1 -1
- package/dist/src/commands/re-export-options.js +1 -1
- package/dist/src/commands/re-export-register.d.ts +1 -1
- package/dist/src/commands/re-export-register.js +1 -1
- package/dist/src/commands/re-export-scan.d.ts +1 -1
- package/dist/src/commands/re-export-scan.js +12 -9
- package/dist/src/commands/re-export-single.d.ts +23 -4
- package/dist/src/commands/re-export-single.js +39 -31
- package/dist/src/commands/re-export.js +35 -17
- package/dist/src/commands/rebase/abort.js +9 -14
- package/dist/src/commands/rebase/continue.js +20 -19
- package/dist/src/commands/rebase/index.d.ts +1 -1
- package/dist/src/commands/rebase/index.js +5 -5
- package/dist/src/commands/rebase/patch-loop.d.ts +2 -2
- package/dist/src/commands/rebase/patch-loop.js +20 -24
- package/dist/src/commands/register.js +5 -5
- package/dist/src/commands/reset.js +1 -1
- package/dist/src/commands/resolve.d.ts +2 -2
- package/dist/src/commands/resolve.js +21 -13
- package/dist/src/commands/run.d.ts +0 -13
- package/dist/src/commands/run.js +38 -51
- package/dist/src/commands/setup-support.d.ts +16 -4
- package/dist/src/commands/setup-support.js +20 -20
- package/dist/src/commands/setup.js +4 -10
- package/dist/src/commands/source.js +9 -2
- package/dist/src/commands/status-check.d.ts +3 -3
- package/dist/src/commands/status-check.js +6 -6
- package/dist/src/commands/status-json.d.ts +14 -13
- package/dist/src/commands/status-json.js +9 -8
- package/dist/src/commands/status-output.d.ts +3 -3
- package/dist/src/commands/status-output.js +5 -5
- package/dist/src/commands/status-ownership.d.ts +3 -3
- package/dist/src/commands/status-ownership.js +3 -3
- package/dist/src/commands/status.js +25 -26
- package/dist/src/commands/test-build-phase.d.ts +3 -3
- package/dist/src/commands/test-build-phase.js +48 -24
- package/dist/src/commands/test-diagnose.d.ts +1 -1
- package/dist/src/commands/test-diagnose.js +20 -20
- package/dist/src/commands/test-modes.d.ts +4 -4
- package/dist/src/commands/test-modes.js +4 -5
- package/dist/src/commands/test-register.js +5 -3
- package/dist/src/commands/test-run.d.ts +11 -11
- package/dist/src/commands/test-run.js +40 -33
- package/dist/src/commands/test-stale-gate.d.ts +12 -12
- package/dist/src/commands/test-stale-gate.js +17 -17
- package/dist/src/commands/test-verdict.d.ts +19 -5
- package/dist/src/commands/test-verdict.js +26 -11
- package/dist/src/commands/test.d.ts +3 -3
- package/dist/src/commands/test.js +73 -36
- package/dist/src/commands/token-coverage.js +3 -3
- package/dist/src/commands/token-list.d.ts +26 -0
- package/dist/src/commands/token-list.js +153 -0
- package/dist/src/commands/token.js +26 -10
- package/dist/src/commands/tree.js +26 -21
- package/dist/src/commands/typecheck.d.ts +6 -6
- package/dist/src/commands/typecheck.js +16 -16
- package/dist/src/commands/verify.d.ts +3 -3
- package/dist/src/commands/verify.js +10 -10
- package/dist/src/commands/watch.js +11 -11
- package/dist/src/commands/wire.js +17 -16
- package/dist/src/core/ast-utils.d.ts +7 -7
- package/dist/src/core/ast-utils.js +8 -8
- package/dist/src/core/branding.d.ts +5 -12
- package/dist/src/core/branding.js +6 -5
- package/dist/src/core/browser-wire.d.ts +1 -1
- package/dist/src/core/browser-wire.js +10 -7
- package/dist/src/core/build-audit-platform.d.ts +32 -3
- package/dist/src/core/build-audit-platform.js +153 -13
- package/dist/src/core/build-audit-registration.d.ts +5 -5
- package/dist/src/core/build-audit-registration.js +10 -9
- package/dist/src/core/build-audit-resolve.d.ts +5 -5
- package/dist/src/core/build-audit-resolve.js +6 -6
- package/dist/src/core/build-audit-skip.d.ts +57 -0
- package/dist/src/core/build-audit-skip.js +112 -0
- package/dist/src/core/build-audit-transforms.d.ts +2 -2
- package/dist/src/core/build-audit-transforms.js +3 -3
- package/dist/src/core/build-audit.d.ts +21 -8
- package/dist/src/core/build-audit.js +142 -40
- package/dist/src/core/build-baseline-types.d.ts +19 -18
- package/dist/src/core/build-baseline-types.js +1 -1
- package/dist/src/core/build-baseline.d.ts +48 -31
- package/dist/src/core/build-baseline.js +20 -43
- package/dist/src/core/build-jar-escalation.d.ts +8 -8
- package/dist/src/core/build-jar-escalation.js +18 -17
- package/dist/src/core/build-overwrite-guard.d.ts +4 -4
- package/dist/src/core/build-overwrite-guard.js +14 -14
- package/dist/src/core/build-prepare.d.ts +4 -12
- package/dist/src/core/build-prepare.js +22 -26
- package/dist/src/core/config-mutate.js +4 -4
- package/dist/src/core/config-paths.d.ts +2 -6
- package/dist/src/core/config-paths.js +4 -2
- package/dist/src/core/config-state.d.ts +0 -6
- package/dist/src/core/config-state.js +3 -21
- package/dist/src/core/config-validate-build-audit.d.ts +8 -0
- package/dist/src/core/config-validate-build-audit.js +80 -0
- package/dist/src/core/config-validate-file-size.d.ts +1 -1
- package/dist/src/core/config-validate-file-size.js +3 -3
- package/dist/src/core/config-validate-patch-policy.d.ts +2 -2
- package/dist/src/core/config-validate-patch-policy.js +3 -3
- package/dist/src/core/config-validate-test-toolchains.d.ts +2 -2
- package/dist/src/core/config-validate-test-toolchains.js +4 -5
- package/dist/src/core/config-validate.js +22 -12
- package/dist/src/core/config.d.ts +12 -12
- package/dist/src/core/config.js +21 -25
- package/dist/src/core/coverage-extend.d.ts +16 -16
- package/dist/src/core/coverage-extend.js +20 -20
- package/dist/src/core/destructive.d.ts +14 -14
- package/dist/src/core/destructive.js +9 -9
- package/dist/src/core/diff-hunks.d.ts +2 -2
- package/dist/src/core/diff-hunks.js +7 -7
- package/dist/src/core/discard-baseline.d.ts +10 -10
- package/dist/src/core/discard-baseline.js +22 -23
- package/dist/src/core/display-state.d.ts +11 -11
- package/dist/src/core/display-state.js +12 -12
- package/dist/src/core/engine-changes.d.ts +2 -2
- package/dist/src/core/engine-changes.js +2 -2
- package/dist/src/core/engine-precondition.d.ts +5 -13
- package/dist/src/core/engine-precondition.js +5 -10
- package/dist/src/core/engine-session-lock.d.ts +18 -18
- package/dist/src/core/engine-session-lock.js +50 -54
- package/dist/src/core/export-moved-code-shape.d.ts +7 -7
- package/dist/src/core/export-moved-code-shape.js +10 -10
- package/dist/src/core/file-lock-owner.d.ts +103 -0
- package/dist/src/core/file-lock-owner.js +259 -0
- package/dist/src/core/file-lock.d.ts +14 -19
- package/dist/src/core/file-lock.js +90 -128
- package/dist/src/core/firefox-cache.d.ts +13 -1
- package/dist/src/core/firefox-cache.js +61 -36
- package/dist/src/core/firefox-download.d.ts +15 -0
- package/dist/src/core/firefox-download.js +38 -22
- package/dist/src/core/firefox-extract.d.ts +8 -7
- package/dist/src/core/firefox-extract.js +45 -27
- package/dist/src/core/firefox.d.ts +34 -36
- package/dist/src/core/firefox.js +13 -44
- package/dist/src/core/furnace-apply-dry-run.d.ts +1 -6
- package/dist/src/core/furnace-apply-dry-run.js +2 -8
- package/dist/src/core/furnace-apply-ftl.d.ts +5 -5
- package/dist/src/core/furnace-apply-ftl.js +8 -8
- package/dist/src/core/furnace-apply-helpers.d.ts +9 -20
- package/dist/src/core/furnace-apply-helpers.js +28 -39
- package/dist/src/core/furnace-apply-output.js +1 -1
- package/dist/src/core/furnace-apply-overwrite-warn.d.ts +9 -9
- package/dist/src/core/furnace-apply-overwrite-warn.js +13 -11
- package/dist/src/core/furnace-apply-undeploy-actions.d.ts +1 -1
- package/dist/src/core/furnace-apply-undeploy-actions.js +1 -1
- package/dist/src/core/furnace-apply.d.ts +4 -4
- package/dist/src/core/furnace-apply.js +50 -29
- package/dist/src/core/furnace-checksum-utils.d.ts +5 -5
- package/dist/src/core/furnace-checksum-utils.js +5 -5
- package/dist/src/core/furnace-config-custom.d.ts +1 -1
- package/dist/src/core/furnace-config-custom.js +2 -2
- package/dist/src/core/furnace-config-order.js +1 -1
- package/dist/src/core/furnace-config-tokens.d.ts +3 -3
- package/dist/src/core/furnace-config-tokens.js +3 -3
- package/dist/src/core/furnace-config-validate.js +2 -2
- package/dist/src/core/furnace-config.d.ts +5 -5
- package/dist/src/core/furnace-config.js +40 -53
- package/dist/src/core/furnace-constants.d.ts +6 -6
- package/dist/src/core/furnace-constants.js +9 -8
- package/dist/src/core/furnace-css-fragments.d.ts +6 -6
- package/dist/src/core/furnace-css-fragments.js +11 -11
- package/dist/src/core/furnace-dir-entry.d.ts +20 -0
- package/dist/src/core/furnace-dir-entry.js +21 -0
- package/dist/src/core/furnace-jsconfig.d.ts +7 -7
- package/dist/src/core/furnace-jsconfig.js +22 -20
- package/dist/src/core/furnace-operation.d.ts +22 -19
- package/dist/src/core/furnace-operation.js +38 -34
- package/dist/src/core/furnace-precondition.d.ts +10 -10
- package/dist/src/core/furnace-precondition.js +8 -8
- package/dist/src/core/furnace-refresh.d.ts +18 -6
- package/dist/src/core/furnace-refresh.js +5 -8
- package/dist/src/core/furnace-registration-ast.d.ts +2 -3
- package/dist/src/core/furnace-registration-ast.js +9 -12
- package/dist/src/core/furnace-registration-remove.d.ts +4 -4
- package/dist/src/core/furnace-registration-remove.js +6 -6
- package/dist/src/core/furnace-registration-validate.d.ts +2 -2
- package/dist/src/core/furnace-registration-validate.js +2 -2
- package/dist/src/core/furnace-registration.d.ts +7 -6
- package/dist/src/core/furnace-registration.js +29 -36
- package/dist/src/core/furnace-rollback.d.ts +1 -1
- package/dist/src/core/furnace-rollback.js +5 -5
- package/dist/src/core/furnace-scanner.js +3 -6
- package/dist/src/core/furnace-stale-export.d.ts +17 -16
- package/dist/src/core/furnace-stale-export.js +16 -15
- package/dist/src/core/furnace-staleness.d.ts +2 -2
- package/dist/src/core/furnace-staleness.js +2 -2
- package/dist/src/core/furnace-state-persist.d.ts +12 -12
- package/dist/src/core/furnace-state-persist.js +10 -10
- package/dist/src/core/furnace-step-errors.d.ts +6 -6
- package/dist/src/core/furnace-step-errors.js +6 -6
- package/dist/src/core/furnace-validate-accessibility.js +14 -14
- package/dist/src/core/furnace-validate-compatibility.js +9 -9
- package/dist/src/core/furnace-validate-registration.d.ts +2 -2
- package/dist/src/core/furnace-validate-registration.js +18 -20
- package/dist/src/core/furnace-validate-structure.d.ts +1 -1
- package/dist/src/core/furnace-validate-structure.js +4 -4
- package/dist/src/core/furnace-validate.js +9 -9
- package/dist/src/core/furnace-version-drift.d.ts +5 -5
- package/dist/src/core/furnace-version-drift.js +5 -5
- package/dist/src/core/git-base.d.ts +6 -4
- package/dist/src/core/git-base.js +29 -7
- package/dist/src/core/git-diff-new-file.d.ts +40 -0
- package/dist/src/core/git-diff-new-file.js +119 -0
- package/dist/src/core/git-diff.d.ts +13 -13
- package/dist/src/core/git-diff.js +121 -189
- package/dist/src/core/git-file-ops.d.ts +6 -13
- package/dist/src/core/git-file-ops.js +11 -35
- package/dist/src/core/git-readonly-index.d.ts +12 -14
- package/dist/src/core/git-readonly-index.js +12 -16
- package/dist/src/core/git-status.d.ts +9 -2
- package/dist/src/core/git-status.js +23 -11
- package/dist/src/core/git.d.ts +3 -9
- package/dist/src/core/git.js +28 -57
- package/dist/src/core/harness-orphans.d.ts +17 -17
- package/dist/src/core/harness-orphans.js +28 -27
- package/dist/src/core/history-log.d.ts +19 -0
- package/dist/src/core/history-log.js +29 -0
- package/dist/src/core/license-headers.d.ts +19 -18
- package/dist/src/core/license-headers.js +29 -28
- package/dist/src/core/mach-build-artifacts.d.ts +21 -21
- package/dist/src/core/mach-build-artifacts.js +23 -23
- package/dist/src/core/mach-error-hints.d.ts +5 -10
- package/dist/src/core/mach-error-hints.js +14 -14
- package/dist/src/core/mach-known-noise-filter.d.ts +42 -38
- package/dist/src/core/mach-known-noise-filter.js +57 -56
- package/dist/src/core/mach-mozconfig.d.ts +6 -6
- package/dist/src/core/mach-mozconfig.js +17 -16
- package/dist/src/core/mach-python.d.ts +3 -0
- package/dist/src/core/mach-python.js +13 -7
- package/dist/src/core/mach-resource-shim.d.ts +24 -12
- package/dist/src/core/mach-resource-shim.js +124 -21
- package/dist/src/core/mach.d.ts +59 -73
- package/dist/src/core/mach.js +47 -115
- package/dist/src/core/marionette-port.d.ts +15 -30
- package/dist/src/core/marionette-port.js +46 -89
- package/dist/src/core/marionette-preflight.d.ts +6 -6
- package/dist/src/core/marionette-preflight.js +32 -50
- package/dist/src/core/markdown-table.d.ts +9 -9
- package/dist/src/core/markdown-table.js +14 -14
- package/dist/src/core/mochitest-server-port.d.ts +8 -8
- package/dist/src/core/mochitest-server-port.js +17 -17
- package/dist/src/core/module-resolution-preflight.d.ts +8 -8
- package/dist/src/core/module-resolution-preflight.js +11 -11
- package/dist/src/core/moz-manifest-helpers.d.ts +7 -7
- package/dist/src/core/moz-manifest-helpers.js +7 -7
- package/dist/src/core/moz-manifest-register.d.ts +1 -1
- package/dist/src/core/moz-manifest-register.js +2 -2
- package/dist/src/core/moz-manifest-rules.js +46 -42
- package/dist/src/core/moz-manifest-tokenizers.js +1 -1
- package/dist/src/core/ownership-table.d.ts +5 -5
- package/dist/src/core/ownership-table.js +7 -7
- package/dist/src/core/parser-fallback.d.ts +3 -3
- package/dist/src/core/parser-fallback.js +3 -3
- package/dist/src/core/patch-apply-fuzz.d.ts +5 -5
- package/dist/src/core/patch-apply-fuzz.js +13 -13
- package/dist/src/core/patch-apply.d.ts +13 -14
- package/dist/src/core/patch-apply.js +36 -42
- package/dist/src/core/patch-export-coverage.d.ts +0 -9
- package/dist/src/core/patch-export-coverage.js +1 -30
- package/dist/src/core/patch-export-update.d.ts +21 -4
- package/dist/src/core/patch-export-update.js +7 -6
- package/dist/src/core/patch-export.d.ts +20 -30
- package/dist/src/core/patch-export.js +55 -77
- package/dist/src/core/patch-files.d.ts +0 -4
- package/dist/src/core/patch-files.js +0 -11
- package/dist/src/core/patch-identifier-suggest.d.ts +1 -1
- package/dist/src/core/patch-identifier-suggest.js +4 -4
- package/dist/src/core/patch-lint-binary.d.ts +12 -18
- package/dist/src/core/patch-lint-cache.d.ts +18 -2
- package/dist/src/core/patch-lint-cache.js +16 -19
- package/dist/src/core/patch-lint-checkjs.d.ts +55 -38
- package/dist/src/core/patch-lint-checkjs.js +78 -64
- package/dist/src/core/patch-lint-chrome-jsdoc.d.ts +8 -9
- package/dist/src/core/patch-lint-chrome-jsdoc.js +10 -11
- package/dist/src/core/patch-lint-creators.d.ts +5 -9
- package/dist/src/core/patch-lint-creators.js +3 -3
- package/dist/src/core/patch-lint-cross.d.ts +27 -19
- package/dist/src/core/patch-lint-cross.js +67 -110
- package/dist/src/core/patch-lint-css.d.ts +1 -1
- package/dist/src/core/patch-lint-css.js +15 -11
- package/dist/src/core/patch-lint-diff-tag.d.ts +5 -5
- package/dist/src/core/patch-lint-diff-tag.js +5 -5
- package/dist/src/core/patch-lint-diff.d.ts +4 -4
- package/dist/src/core/patch-lint-diff.js +4 -4
- package/dist/src/core/patch-lint-file-size.d.ts +3 -3
- package/dist/src/core/patch-lint-file-size.js +6 -6
- package/dist/src/core/patch-lint-forward-registration.d.ts +58 -0
- package/dist/src/core/patch-lint-forward-registration.js +210 -0
- package/dist/src/core/patch-lint-jsdoc.d.ts +2 -2
- package/dist/src/core/patch-lint-jsdoc.js +46 -46
- package/dist/src/core/patch-lint-module-registration.d.ts +3 -9
- package/dist/src/core/patch-lint-module-registration.js +1 -1
- package/dist/src/core/patch-lint-mozbuild.d.ts +1 -1
- package/dist/src/core/patch-lint-mozbuild.js +10 -10
- package/dist/src/core/patch-lint-observer.d.ts +3 -3
- package/dist/src/core/patch-lint-observer.js +7 -7
- package/dist/src/core/patch-lint-ownership.d.ts +6 -6
- package/dist/src/core/patch-lint-ownership.js +6 -6
- package/dist/src/core/patch-lint-prettier.d.ts +6 -6
- package/dist/src/core/patch-lint-prettier.js +7 -7
- package/dist/src/core/patch-lint-queue-types.d.ts +60 -0
- package/dist/src/core/patch-lint-queue-types.js +12 -0
- package/dist/src/core/patch-lint-staged-registration.d.ts +61 -0
- package/dist/src/core/patch-lint-staged-registration.js +90 -0
- package/dist/src/core/patch-lint-unmanaged-companion.d.ts +23 -23
- package/dist/src/core/patch-lint-unmanaged-companion.js +26 -26
- package/dist/src/core/patch-lint.d.ts +41 -35
- package/dist/src/core/patch-lint.js +52 -49
- package/dist/src/core/patch-lock.d.ts +1 -1
- package/dist/src/core/patch-lock.js +11 -11
- package/dist/src/core/patch-manifest-consistency.d.ts +7 -7
- package/dist/src/core/patch-manifest-consistency.js +16 -17
- package/dist/src/core/patch-manifest-files-affected.d.ts +1 -1
- package/dist/src/core/patch-manifest-files-affected.js +3 -3
- package/dist/src/core/patch-manifest-io.d.ts +14 -14
- package/dist/src/core/patch-manifest-io.js +35 -34
- package/dist/src/core/patch-manifest-query.d.ts +1 -1
- package/dist/src/core/patch-manifest-query.js +4 -4
- package/dist/src/core/patch-manifest-resolve.d.ts +5 -5
- package/dist/src/core/patch-manifest-resolve.js +7 -7
- package/dist/src/core/patch-manifest-validate.js +3 -3
- package/dist/src/core/patch-manifest.d.ts +2 -2
- package/dist/src/core/patch-manifest.js +2 -2
- package/dist/src/core/patch-parse.d.ts +32 -21
- package/dist/src/core/patch-parse.js +40 -15
- package/dist/src/core/patch-policy.js +15 -27
- package/dist/src/core/patch-registration-refs.d.ts +4 -4
- package/dist/src/core/patch-registration-refs.js +7 -7
- package/dist/src/core/patch-source-metadata.d.ts +1 -3
- package/dist/src/core/patch-source-metadata.js +0 -4
- package/dist/src/core/patch-transform.d.ts +8 -16
- package/dist/src/core/patch-transform.js +13 -23
- package/dist/src/core/process-cpu-time.d.ts +1 -1
- package/dist/src/core/process-cpu-time.js +6 -6
- package/dist/src/core/rebase-session.d.ts +9 -15
- package/dist/src/core/rebase-session.js +13 -25
- package/dist/src/core/register-browser-content.js +3 -2
- package/dist/src/core/register-browser-test.js +2 -1
- package/dist/src/core/register-module.js +2 -1
- package/dist/src/core/register-result.d.ts +1 -1
- package/dist/src/core/register-result.js +1 -1
- package/dist/src/core/register-scaffold.d.ts +2 -2
- package/dist/src/core/register-scaffold.js +8 -7
- package/dist/src/core/register-shared-css.d.ts +3 -3
- package/dist/src/core/register-shared-css.js +6 -5
- package/dist/src/core/register-xpcshell-test.d.ts +2 -2
- package/dist/src/core/register-xpcshell-test.js +2 -2
- package/dist/src/core/run-log-redact.d.ts +38 -0
- package/dist/src/core/run-log-redact.js +69 -0
- package/dist/src/core/run-log.d.ts +21 -10
- package/dist/src/core/run-log.js +76 -27
- package/dist/src/core/shared-ftl.d.ts +2 -2
- package/dist/src/core/shared-ftl.js +6 -6
- package/dist/src/core/signal-critical.d.ts +2 -2
- package/dist/src/core/signal-critical.js +4 -6
- package/dist/src/core/smoke-patterns.d.ts +5 -6
- package/dist/src/core/smoke-patterns.js +15 -20
- package/dist/src/core/state-file.d.ts +15 -4
- package/dist/src/core/state-file.js +14 -1
- package/dist/src/core/status-binary.d.ts +8 -8
- package/dist/src/core/status-binary.js +12 -12
- package/dist/src/core/status-classify.d.ts +17 -17
- package/dist/src/core/status-classify.js +13 -12
- package/dist/src/core/test-changed-prefs.d.ts +12 -12
- package/dist/src/core/test-changed-prefs.js +40 -25
- package/dist/src/core/test-harness-crash.d.ts +39 -39
- package/dist/src/core/test-harness-crash.js +69 -69
- package/dist/src/core/test-harness-output.d.ts +7 -7
- package/dist/src/core/test-harness-output.js +7 -7
- package/dist/src/core/test-harness-verdict-notes.d.ts +13 -14
- package/dist/src/core/test-harness-verdict-notes.js +4 -4
- package/dist/src/core/test-path-scope.d.ts +8 -8
- package/dist/src/core/test-path-scope.js +11 -11
- package/dist/src/core/test-stale-check.d.ts +22 -23
- package/dist/src/core/test-stale-check.js +31 -30
- package/dist/src/core/test-stale-symlink.d.ts +1 -1
- package/dist/src/core/test-stale-symlink.js +1 -1
- package/dist/src/core/test-stall-triage.d.ts +9 -9
- package/dist/src/core/test-stall-triage.js +22 -22
- package/dist/src/core/test-xpcshell-retry.d.ts +26 -7
- package/dist/src/core/test-xpcshell-retry.js +14 -11
- package/dist/src/core/token-category.d.ts +35 -2
- package/dist/src/core/token-category.js +67 -58
- package/dist/src/core/token-coverage.js +4 -5
- package/dist/src/core/token-dark-mode.d.ts +9 -9
- package/dist/src/core/token-dark-mode.js +13 -25
- package/dist/src/core/token-docs.d.ts +1 -1
- package/dist/src/core/token-inventory.d.ts +56 -0
- package/dist/src/core/token-inventory.js +109 -0
- package/dist/src/core/token-manager.d.ts +4 -4
- package/dist/src/core/token-manager.js +22 -22
- package/dist/src/core/token-scaffold.d.ts +4 -4
- package/dist/src/core/token-scaffold.js +4 -4
- package/dist/src/core/token-variant.d.ts +14 -14
- package/dist/src/core/token-variant.js +52 -53
- package/dist/src/core/toolchain-preflight.d.ts +15 -15
- package/dist/src/core/toolchain-preflight.js +23 -23
- package/dist/src/core/tree-cow.d.ts +3 -5
- package/dist/src/core/tree-cow.js +8 -8
- package/dist/src/core/tree-guard.d.ts +3 -3
- package/dist/src/core/tree-guard.js +23 -23
- package/dist/src/core/tree-store.d.ts +15 -15
- package/dist/src/core/tree-store.js +39 -38
- package/dist/src/core/typecheck-shim.d.ts +16 -15
- package/dist/src/core/typecheck-shim.js +26 -25
- package/dist/src/core/typecheck.d.ts +12 -12
- package/dist/src/core/typecheck.js +33 -33
- package/dist/src/core/wire-destroy.d.ts +2 -2
- package/dist/src/core/wire-destroy.js +5 -5
- package/dist/src/core/wire-dom-fragment.d.ts +3 -3
- package/dist/src/core/wire-dom-fragment.js +12 -23
- package/dist/src/core/wire-init.d.ts +2 -2
- package/dist/src/core/wire-init.js +7 -7
- package/dist/src/core/wire-subscript.d.ts +1 -1
- package/dist/src/core/wire-subscript.js +3 -3
- package/dist/src/core/wire-utils.d.ts +9 -9
- package/dist/src/core/wire-utils.js +16 -28
- package/dist/src/core/xpcshell-appdir.d.ts +20 -20
- package/dist/src/core/xpcshell-appdir.js +28 -30
- package/dist/src/core/xpcshell-profile-dir.d.ts +3 -3
- package/dist/src/core/xpcshell-profile-dir.js +7 -7
- package/dist/src/errors/base.d.ts +69 -16
- package/dist/src/errors/base.js +95 -26
- package/dist/src/errors/build.d.ts +6 -6
- package/dist/src/errors/build.js +26 -34
- package/dist/src/errors/codes.d.ts +10 -10
- package/dist/src/errors/codes.js +10 -10
- package/dist/src/errors/config.d.ts +0 -14
- package/dist/src/errors/config.js +13 -34
- package/dist/src/errors/download.d.ts +13 -0
- package/dist/src/errors/download.js +53 -24
- package/dist/src/errors/furnace.d.ts +2 -2
- package/dist/src/errors/furnace.js +8 -9
- package/dist/src/errors/git.d.ts +9 -9
- package/dist/src/errors/git.js +21 -31
- package/dist/src/errors/patch.d.ts +3 -3
- package/dist/src/errors/patch.js +11 -13
- package/dist/src/errors/rebase.d.ts +1 -1
- package/dist/src/errors/rebase.js +8 -8
- package/dist/src/errors/run.d.ts +1 -1
- package/dist/src/errors/run.js +1 -1
- package/dist/src/index.d.ts +4 -4
- package/dist/src/index.js +4 -4
- package/dist/src/types/commands/options.d.ts +155 -200
- package/dist/src/types/commands/patches.d.ts +19 -19
- package/dist/src/types/commands/project.d.ts +3 -3
- package/dist/src/types/config.d.ts +52 -19
- package/dist/src/types/furnace.d.ts +17 -17
- package/dist/src/types/index.d.ts +0 -1
- package/dist/src/types/json.d.ts +3 -3
- package/dist/src/types/json.js +2 -2
- package/dist/src/types/typecheck.d.ts +3 -3
- package/dist/src/utils/assert.d.ts +4 -16
- package/dist/src/utils/assert.js +7 -24
- package/dist/src/utils/build-info.d.ts +6 -6
- package/dist/src/utils/build-info.js +6 -6
- package/dist/src/utils/child-env.d.ts +7 -6
- package/dist/src/utils/child-env.js +5 -5
- package/dist/src/utils/concurrency.d.ts +2 -2
- package/dist/src/utils/concurrency.js +2 -2
- package/dist/src/utils/elapsed.js +10 -1
- package/dist/src/utils/errors.d.ts +8 -8
- package/dist/src/utils/errors.js +8 -8
- package/dist/src/utils/fs.d.ts +1 -1
- package/dist/src/utils/fs.js +15 -20
- package/dist/src/utils/hash.d.ts +12 -0
- package/dist/src/utils/hash.js +16 -0
- package/dist/src/utils/line-dispatch.d.ts +15 -0
- package/dist/src/utils/line-dispatch.js +48 -0
- package/dist/src/utils/logger.d.ts +4 -4
- package/dist/src/utils/logger.js +11 -11
- package/dist/src/utils/machine-output.js +2 -2
- package/dist/src/utils/options.d.ts +14 -20
- package/dist/src/utils/options.js +26 -27
- package/dist/src/utils/package-root.js +5 -14
- package/dist/src/utils/paths.d.ts +4 -4
- package/dist/src/utils/paths.js +4 -4
- package/dist/src/utils/platform.d.ts +0 -4
- package/dist/src/utils/process-group.d.ts +10 -9
- package/dist/src/utils/process-group.js +37 -36
- package/dist/src/utils/process.d.ts +70 -55
- package/dist/src/utils/process.js +129 -179
- package/dist/src/utils/ps-duration.d.ts +4 -4
- package/dist/src/utils/ps-duration.js +9 -9
- package/dist/src/utils/regex.d.ts +4 -4
- package/dist/src/utils/regex.js +7 -7
- package/dist/src/utils/sleep.d.ts +26 -0
- package/dist/src/utils/sleep.js +31 -0
- package/dist/src/utils/stdio-drain.d.ts +7 -7
- package/dist/src/utils/stdio-drain.js +8 -8
- package/dist/src/utils/validation.d.ts +12 -49
- package/dist/src/utils/validation.js +26 -36
- package/docs/README.md +2 -2
- package/docs/configuration.md +163 -69
- package/docs/exit-codes.md +66 -49
- package/docs/furnace.md +20 -19
- package/docs/lifecycle-invariants.md +414 -247
- package/docs/machine-output.md +58 -34
- package/docs/patch-workflow.md +48 -44
- package/docs/run-logs.md +72 -28
- package/docs/testing.md +105 -98
- package/docs/verification-trees.md +23 -22
- package/package.json +7 -6
- package/dist/src/commands/rebase.d.ts +0 -4
- package/dist/src/commands/rebase.js +0 -5
- package/dist/src/core/patch-artifact-normalize.d.ts +0 -21
- package/dist/src/core/patch-artifact-normalize.js +0 -24
- package/dist/src/core/patch-lint-reexports.d.ts +0 -7
- package/dist/src/core/patch-lint-reexports.js +0 -8
- package/dist/src/core/wire-targets.d.ts +0 -7
- package/dist/src/core/wire-targets.js +0 -8
|
@@ -13,6 +13,7 @@ import { FurnaceError } from '../../errors/furnace.js';
|
|
|
13
13
|
import { getNodeErrorCode, toError } from '../../utils/errors.js';
|
|
14
14
|
import { ensureDir, pathExists, writeText } from '../../utils/fs.js';
|
|
15
15
|
import { cancel, info, intro, isCancel, note, outro, success, warn } from '../../utils/logger.js';
|
|
16
|
+
import { normalizePathSlashes } from '../../utils/paths.js';
|
|
16
17
|
/**
|
|
17
18
|
* File extensions that are definitely FTL resources (not locale
|
|
18
19
|
* directories). A value ending in one of these is almost certainly the
|
|
@@ -38,16 +39,16 @@ function hasFtlFileExtension(value) {
|
|
|
38
39
|
/**
|
|
39
40
|
* Validates an FTL base path before writing it to furnace.json.
|
|
40
41
|
* Rejects:
|
|
41
|
-
* - empty values and null bytes
|
|
42
|
-
* - absolute paths (POSIX or Windows-drive) that escape the engine
|
|
43
|
-
* - `..` segments that escape the engine
|
|
42
|
+
* - empty values and null bytes
|
|
43
|
+
* - absolute paths (POSIX or Windows-drive) that escape the engine
|
|
44
|
+
* - `..` segments that escape the engine
|
|
44
45
|
* - file-shaped values ending in `.ftl` / `.properties` / `.dtd`
|
|
45
|
-
* (these are locale resources, not directories
|
|
46
|
-
* almost certainly meant to name the parent directory)
|
|
46
|
+
* (these are locale resources, not directories, so the operator
|
|
47
|
+
* almost certainly meant to name the parent directory)
|
|
47
48
|
*
|
|
48
49
|
* When {@link engineDir} is provided and exists on disk, the resolved
|
|
49
|
-
* `engine/${value}` path is probed
|
|
50
|
-
* directory, the same file-shape error fires
|
|
50
|
+
* `engine/${value}` path is probed. If it exists but is not a
|
|
51
|
+
* directory, the same file-shape error fires. If it does not exist yet,
|
|
51
52
|
* a non-blocking warning is logged (a fresh project that has not
|
|
52
53
|
* `fireforge download`-ed yet is the legitimate pre-existence case).
|
|
53
54
|
*/
|
|
@@ -64,7 +65,7 @@ async function validateFtlBasePath(value, engineDir) {
|
|
|
64
65
|
// Normalize with the POSIX rules regardless of host: `normalize` on Windows
|
|
65
66
|
// emits backslashes, so a `../`-prefix test against the platform `normalize`
|
|
66
67
|
// silently passes every traversal attempt there.
|
|
67
|
-
const normalized = posix.normalize(value
|
|
68
|
+
const normalized = posix.normalize(normalizePathSlashes(value));
|
|
68
69
|
if (normalized === '..' || normalized.startsWith('../')) {
|
|
69
70
|
throw new FurnaceError(`ftlBasePath "${value}" must not escape the engine checkout via parent-directory segments.`);
|
|
70
71
|
}
|
|
@@ -86,16 +87,16 @@ async function validateFtlBasePath(value, engineDir) {
|
|
|
86
87
|
}
|
|
87
88
|
catch (error) {
|
|
88
89
|
// FurnaceError (from the `isDirectory()` branch above) is a real
|
|
89
|
-
// shape failure
|
|
90
|
+
// shape failure, so re-throw and let the operator see it.
|
|
90
91
|
if (error instanceof FurnaceError)
|
|
91
92
|
throw error;
|
|
92
93
|
// ENOENT is expected on a fresh project before `fireforge
|
|
93
|
-
// download` has populated engine
|
|
94
|
+
// download` has populated engine/. Only warn.
|
|
94
95
|
const code = getNodeErrorCode(error);
|
|
95
96
|
if (code === 'ENOENT') {
|
|
96
97
|
warn(`ftlBasePath "${value}" does not yet exist at ${resolved}. This is fine if you have not run "fireforge download" yet; rerun "fireforge furnace init --force" after the engine is extracted to re-validate.`);
|
|
97
98
|
}
|
|
98
|
-
// Any other stat error is also
|
|
99
|
+
// Any other stat error is also ignored here as best-effort: a
|
|
99
100
|
// permission issue or malformed engine checkout will surface on
|
|
100
101
|
// the next command that actually reads the FTL tree.
|
|
101
102
|
}
|
|
@@ -115,7 +116,7 @@ export async function furnaceInitCommand(projectRoot, options = {}) {
|
|
|
115
116
|
const paths = getProjectPaths(projectRoot);
|
|
116
117
|
// Seed the default furnace config with a tokenPrefix derived from
|
|
117
118
|
// fireforge.json's binaryName so `token coverage` sees real tokens on the
|
|
118
|
-
// very first run
|
|
119
|
+
// very first run. Without the prefix default, a fresh init → token add →
|
|
119
120
|
// coverage sequence reports `0 tokens / N unknown` because the scan has
|
|
120
121
|
// nothing to key off. Loading fireforge.json here is best-effort: a
|
|
121
122
|
// project without one (mid-setup) falls through to the prefix-less
|
|
@@ -196,8 +197,8 @@ export async function furnaceInitCommand(projectRoot, options = {}) {
|
|
|
196
197
|
* Scaffolds the default tokens CSS file under the engine and registers
|
|
197
198
|
* its path in `fireforge.json`'s `patchLint.rawColorAllowlist`. Both
|
|
198
199
|
* operations are skipped silently when the engine directory does not
|
|
199
|
-
* yet exist (a fresh project that hasn't `fireforge download`ed yet)
|
|
200
|
-
*
|
|
200
|
+
* yet exist (a fresh project that hasn't `fireforge download`ed yet).
|
|
201
|
+
* The scaffold is re-driven on the next `furnace init --force`.
|
|
201
202
|
*
|
|
202
203
|
* Returns the scaffolded path when the file was actually created, so
|
|
203
204
|
* the init command can surface it in the summary note.
|
|
@@ -257,12 +258,12 @@ async function scaffoldTokensCss(projectRoot) {
|
|
|
257
258
|
// is owned end-to-end by tooling. Scaffolding and allowlisting it without
|
|
258
259
|
// registering leaves the very next `fireforge status` correctly flagging
|
|
259
260
|
// it as unmanaged + unregistered while `furnace deploy --dry-run` reports
|
|
260
|
-
// nothing to deploy
|
|
261
|
+
// nothing to deploy, a documented init command turning a clean project
|
|
261
262
|
// unclean. The CSS lives at the canonical
|
|
262
263
|
// `browser/themes/shared/<binaryName>-tokens.css` path the shared-CSS rule
|
|
263
264
|
// already targets, so it gets the same
|
|
264
265
|
// `skin/classic/browser/<name>.css (../shared/<name>.css)` entry as any
|
|
265
|
-
// other shared CSS.
|
|
266
|
+
// other shared CSS. It is idempotent: `furnace init --force` against a
|
|
266
267
|
// registered tree is a no-op.
|
|
267
268
|
try {
|
|
268
269
|
const fileBase = `${forgeConfig.binaryName}-tokens.css`;
|
|
@@ -22,8 +22,8 @@ async function getHealthIndicator(componentDir, type, name, appliedChecksums) {
|
|
|
22
22
|
}
|
|
23
23
|
catch {
|
|
24
24
|
// A race with `furnace remove`, filesystem permission change, or a
|
|
25
|
-
// transient IO failure must not crash the entire `list -v` output
|
|
26
|
-
// render a degraded state
|
|
25
|
+
// transient IO failure must not crash the entire `list -v` output, so
|
|
26
|
+
// render a degraded state and the rest of the table still shows.
|
|
27
27
|
return formatErrorText('unavailable');
|
|
28
28
|
}
|
|
29
29
|
}
|
|
@@ -8,7 +8,7 @@ import type { FurnaceOverrideOptions } from '../../types/commands/index.js';
|
|
|
8
8
|
export declare function furnaceOverrideCommand(projectRoot: string, name?: string, options?: FurnaceOverrideOptions): Promise<void>;
|
|
9
9
|
/**
|
|
10
10
|
* Creates multiple overrides in a single invocation. Each component is validated
|
|
11
|
-
* and created sequentially
|
|
11
|
+
* and created sequentially. Failures on one component do not block the rest.
|
|
12
12
|
* @param projectRoot - Root directory of the project
|
|
13
13
|
* @param names - Component tag names to override
|
|
14
14
|
* @param options - CLI options applied to all overrides
|
|
@@ -4,7 +4,7 @@ import { dirname, join } from 'node:path';
|
|
|
4
4
|
import { select, text } from '@clack/prompts';
|
|
5
5
|
import { getProjectPaths, loadConfig, loadState } from '../../core/config.js';
|
|
6
6
|
import { stdioIsInteractive } from '../../core/destructive.js';
|
|
7
|
-
import {
|
|
7
|
+
import { getFurnacePaths, writeFurnaceConfig } from '../../core/furnace-config.js';
|
|
8
8
|
import { resolveFtlDir } from '../../core/furnace-constants.js';
|
|
9
9
|
import { completeJournalRollback, runFurnaceMutation } from '../../core/furnace-operation.js';
|
|
10
10
|
import { assertFurnaceEngineReady } from '../../core/furnace-precondition.js';
|
|
@@ -16,25 +16,14 @@ import { FurnaceError } from '../../errors/furnace.js';
|
|
|
16
16
|
import { toError } from '../../utils/errors.js';
|
|
17
17
|
import { copyFile, ensureDir, pathExists, writeJson } from '../../utils/fs.js';
|
|
18
18
|
import { cancel, info, intro, isCancel, note, outro, warn } from '../../utils/logger.js';
|
|
19
|
-
|
|
20
|
-
if (await furnaceConfigExists(projectRoot)) {
|
|
21
|
-
return loadFurnaceConfig(projectRoot);
|
|
22
|
-
}
|
|
23
|
-
return createDefaultFurnaceConfig();
|
|
24
|
-
}
|
|
19
|
+
import { loadAuthoringFurnaceConfig } from './authoring-config.js';
|
|
25
20
|
/**
|
|
26
21
|
* Copies the source files needed for a new override into the workspace.
|
|
27
|
-
* @param
|
|
28
|
-
* @param srcDir - Original component directory in the engine checkout
|
|
29
|
-
* @param destDir - Destination override directory in the workspace
|
|
30
|
-
* @param componentName - Custom element tag name being overridden
|
|
31
|
-
* @param hasFTL - Whether the component ships a localized `.ftl` file
|
|
32
|
-
* @param overrideType - Requested override mode
|
|
33
|
-
* @param ftlDir - Engine-relative directory the shared `.ftl` deploys into
|
|
34
|
-
* @param journal - Rollback journal every write is recorded in
|
|
22
|
+
* @param options - See {@link CopyOverrideFilesOptions}
|
|
35
23
|
* @returns Filenames copied into the override directory
|
|
36
24
|
*/
|
|
37
|
-
async function copyOverrideFiles(
|
|
25
|
+
async function copyOverrideFiles(options) {
|
|
26
|
+
const { engineDir, srcDir, destDir, componentName, hasFTL, overrideType, ftlDir, journal } = options;
|
|
38
27
|
await ensureDir(destDir);
|
|
39
28
|
const entries = await readdir(srcDir, { withFileTypes: true });
|
|
40
29
|
const copiedFiles = [];
|
|
@@ -90,10 +79,11 @@ async function copyOverrideFiles(engineDir, srcDir, destDir, componentName, hasF
|
|
|
90
79
|
* override entry. Re-reads the current on-disk furnace.json inside the
|
|
91
80
|
* operation lock and splices the new entry onto the fresh state, so two
|
|
92
81
|
* concurrent `furnace override` commands cannot race their read-modify-write
|
|
93
|
-
* cycles into a single surviving entry
|
|
82
|
+
* cycles into a single surviving entry. Otherwise both report success and
|
|
94
83
|
* furnace.json keeps only the second writer's.
|
|
95
84
|
*/
|
|
96
|
-
async function saveOverrideConfig(
|
|
85
|
+
async function saveOverrideConfig(options) {
|
|
86
|
+
const { projectRoot, destDir, componentName, overrideType, description, details, firefoxVersion, journal, baseCommit, } = options;
|
|
97
87
|
const overrideJson = {
|
|
98
88
|
type: overrideType,
|
|
99
89
|
description,
|
|
@@ -106,8 +96,8 @@ async function saveOverrideConfig(projectRoot, destDir, componentName, overrideT
|
|
|
106
96
|
await writeJson(overrideJsonPath, overrideJson);
|
|
107
97
|
// Re-read the current furnace.json inside the lock. The outer caller
|
|
108
98
|
// loaded a snapshot before entering `runFurnaceMutation`, but another
|
|
109
|
-
// furnace mutation (override / init / sync) may have landed in between
|
|
110
|
-
//
|
|
99
|
+
// furnace mutation (override / init / sync) may have landed in between,
|
|
100
|
+
// and writing back the stale snapshot would drop that concurrent write.
|
|
111
101
|
const freshConfig = await loadAuthoringFurnaceConfig(projectRoot);
|
|
112
102
|
freshConfig.overrides[componentName] = {
|
|
113
103
|
type: overrideType,
|
|
@@ -138,9 +128,28 @@ async function performOverrideMutations(args) {
|
|
|
138
128
|
ctx.registerJournal(journal);
|
|
139
129
|
recordCreatedDir(journal, args.destDir);
|
|
140
130
|
try {
|
|
141
|
-
const filesCopied = await copyOverrideFiles(
|
|
131
|
+
const filesCopied = await copyOverrideFiles({
|
|
132
|
+
engineDir: args.engineDir,
|
|
133
|
+
srcDir: args.srcDir,
|
|
134
|
+
destDir: args.destDir,
|
|
135
|
+
componentName: args.componentName,
|
|
136
|
+
hasFTL: args.details.hasFTL,
|
|
137
|
+
overrideType: args.overrideType,
|
|
138
|
+
ftlDir: args.ftlDir,
|
|
139
|
+
journal,
|
|
140
|
+
});
|
|
142
141
|
await snapshotFile(journal, args.furnacePaths.furnaceConfig);
|
|
143
|
-
await saveOverrideConfig(
|
|
142
|
+
await saveOverrideConfig({
|
|
143
|
+
projectRoot: args.projectRoot,
|
|
144
|
+
destDir: args.destDir,
|
|
145
|
+
componentName: args.componentName,
|
|
146
|
+
overrideType: args.overrideType,
|
|
147
|
+
description: args.description,
|
|
148
|
+
details: args.details,
|
|
149
|
+
firefoxVersion: args.firefoxVersion,
|
|
150
|
+
journal,
|
|
151
|
+
baseCommit: args.baseCommit,
|
|
152
|
+
});
|
|
144
153
|
return filesCopied;
|
|
145
154
|
}
|
|
146
155
|
catch (error) {
|
|
@@ -155,11 +164,11 @@ async function performOverrideMutations(args) {
|
|
|
155
164
|
}
|
|
156
165
|
/**
|
|
157
166
|
* Throws if `componentName` is already classified as something `override`
|
|
158
|
-
* cannot coexist with. A stock-bucket entry is
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
*
|
|
162
|
-
* transition in-memory
|
|
167
|
+
* cannot coexist with. A stock-bucket entry is not a hard conflict:
|
|
168
|
+
* `override` exists to fork a component out of the stock bucket into the
|
|
169
|
+
* overrides bucket, and requiring manual `furnace.json` surgery first was
|
|
170
|
+
* a footgun. `promoteStockToOverrideIfNeeded` handles the
|
|
171
|
+
* transition in-memory. This guard only rejects the other two cases where
|
|
163
172
|
* a rename actually contradicts existing state.
|
|
164
173
|
*/
|
|
165
174
|
function assertNoComponentCollision(config, componentName) {
|
|
@@ -176,7 +185,7 @@ function assertNoComponentCollision(config, componentName) {
|
|
|
176
185
|
* the subsequent `writeFurnaceConfig` inside the mutation phase persists
|
|
177
186
|
* the stock → override promotion atomically alongside the new override
|
|
178
187
|
* entry. Returns true when a promotion happened so the caller can emit a
|
|
179
|
-
* one-line note
|
|
188
|
+
* one-line note. Returns false when the component was not stock.
|
|
180
189
|
*/
|
|
181
190
|
function promoteStockToOverrideIfNeeded(config, componentName) {
|
|
182
191
|
const index = config.stock.indexOf(componentName);
|
|
@@ -194,9 +203,9 @@ function promoteStockToOverrideIfNeeded(config, componentName) {
|
|
|
194
203
|
export async function furnaceOverrideCommand(projectRoot, name, options = {}) {
|
|
195
204
|
const isInteractive = stdioIsInteractive();
|
|
196
205
|
intro('Furnace Override');
|
|
197
|
-
// --- Validate config-independent inputs
|
|
206
|
+
// --- Validate config-independent inputs before auto-creating furnace.json
|
|
198
207
|
// so a failed authoring command never strands a fresh config in the
|
|
199
|
-
// project root. CLI-supplied name is checked here
|
|
208
|
+
// project root. CLI-supplied name is checked here. The engine directory
|
|
200
209
|
// and component-resolution checks below also have no config dependency.
|
|
201
210
|
const paths = getProjectPaths(projectRoot);
|
|
202
211
|
if (name !== undefined && !CUSTOM_ELEMENT_TAG_PATTERN.test(name)) {
|
|
@@ -217,7 +226,7 @@ export async function furnaceOverrideCommand(projectRoot, name, options = {}) {
|
|
|
217
226
|
// --- Resolve component name ---
|
|
218
227
|
let componentName = name;
|
|
219
228
|
if (!componentName) {
|
|
220
|
-
// Interactive prompt path
|
|
229
|
+
// Interactive prompt path. Non-interactive missing-name was rejected above.
|
|
221
230
|
const allComponents = await scanWidgetsDirectory(paths.engine, ftlDir);
|
|
222
231
|
const available = allComponents.filter((c) => !(c.tagName in config.overrides));
|
|
223
232
|
if (available.length === 0) {
|
|
@@ -327,7 +336,7 @@ export async function furnaceOverrideCommand(projectRoot, name, options = {}) {
|
|
|
327
336
|
}
|
|
328
337
|
/**
|
|
329
338
|
* Creates multiple overrides in a single invocation. Each component is validated
|
|
330
|
-
* and created sequentially
|
|
339
|
+
* and created sequentially. Failures on one component do not block the rest.
|
|
331
340
|
* @param projectRoot - Root directory of the project
|
|
332
341
|
* @param names - Component tag names to override
|
|
333
342
|
* @param options - CLI options applied to all overrides
|
|
@@ -353,8 +362,8 @@ export async function furnaceBatchOverrideCommand(projectRoot, names, options =
|
|
|
353
362
|
const state = await loadState(projectRoot);
|
|
354
363
|
// Check for duplicates and pre-existing classifications across every
|
|
355
364
|
// bucket in furnace.json. A stock-bucket entry is promoted in-memory
|
|
356
|
-
// here (see `promoteStockToOverrideIfNeeded`) rather than rejected
|
|
357
|
-
// the operator's intent is to fork that specific stock component. The
|
|
365
|
+
// here (see `promoteStockToOverrideIfNeeded`) rather than rejected,
|
|
366
|
+
// since the operator's intent is to fork that specific stock component. The
|
|
358
367
|
// collision guard still rejects name conflicts that would double-
|
|
359
368
|
// classify a tag in a way `writeFurnaceConfig` cannot safely produce
|
|
360
369
|
// (two overrides, or an override + custom).
|
|
@@ -13,8 +13,8 @@ import { toError } from '../../utils/errors.js';
|
|
|
13
13
|
import { pathExists } from '../../utils/fs.js';
|
|
14
14
|
import { info, intro, outro, spinner, warn } from '../../utils/logger.js';
|
|
15
15
|
/**
|
|
16
|
-
* Runs the two teardown steps
|
|
17
|
-
* restore
|
|
16
|
+
* Runs the two teardown steps (`cleanStories` and the rollback-journal
|
|
17
|
+
* restore) independently, collecting whatever errors either step throws.
|
|
18
18
|
* Both steps must run regardless of the other's outcome, because each
|
|
19
19
|
* operates on a different part of engine state and skipping one leaves
|
|
20
20
|
* the engine in a worse position than a single-step failure.
|
|
@@ -72,10 +72,10 @@ function reportPreviewStagingFailures(stageResult) {
|
|
|
72
72
|
}
|
|
73
73
|
/**
|
|
74
74
|
* Filenames emitted by the Firefox build backend (not by Storybook's npm
|
|
75
|
-
* package set)
|
|
75
|
+
* package set). Their absence means `mach build` has not produced its
|
|
76
76
|
* post-configure artifacts, which is a different failure mode from a missing
|
|
77
77
|
* Storybook workspace dependency tree. A
|
|
78
|
-
* `FileNotFoundError: [...] chrome-map.json`
|
|
78
|
+
* `FileNotFoundError: [...] chrome-map.json` after a successful Storybook
|
|
79
79
|
* `npm install` is the case a dep-focused heuristic misdiagnoses, sending
|
|
80
80
|
* the operator back to `--install`. The pattern list is narrow on purpose so
|
|
81
81
|
* the backend-rebuild hint only fires when it is confident.
|
|
@@ -101,7 +101,7 @@ export function buildStorybookFailureMessage(output, installRequested) {
|
|
|
101
101
|
? 'Try running "python3 ./mach storybook upgrade" manually in the engine directory.'
|
|
102
102
|
: 'Run "fireforge furnace preview --install" to bootstrap Storybook dependencies, or run "python3 ./mach storybook upgrade" manually in engine/.';
|
|
103
103
|
const hasFileNotFoundSignal = /(ENOENT|No such file or directory|FileNotFoundError)/i.test(output);
|
|
104
|
-
// Check backend-artifact signal first
|
|
104
|
+
// Check the backend-artifact signal first: a missing chrome-map.json looks
|
|
105
105
|
// like any other "No such file" error to a naïve regex, but the fix is
|
|
106
106
|
// to rerun `fireforge build`, not to reinstall Storybook dependencies.
|
|
107
107
|
if (hasFileNotFoundSignal && BACKEND_ARTIFACT_PATTERNS.some((p) => p.test(output))) {
|
|
@@ -122,7 +122,7 @@ export function buildStorybookFailureMessage(output, installRequested) {
|
|
|
122
122
|
* Preflights the Firefox build + toolchain prerequisites `mach storybook`
|
|
123
123
|
* quietly assumes. Without it, preview stages components and launches a
|
|
124
124
|
* ~1000-package `mach storybook upgrade` npm install before the backend
|
|
125
|
-
* surfaces a "missing chrome-map.json" / Cargo-config failure
|
|
125
|
+
* surfaces a "missing chrome-map.json" / Cargo-config failure. This refuses
|
|
126
126
|
* fast and leaves the workspace untouched.
|
|
127
127
|
*
|
|
128
128
|
* @param engineDir - Resolved engine directory
|
|
@@ -143,7 +143,7 @@ async function assertPreviewPrerequisites(engineDir) {
|
|
|
143
143
|
// follow the remediation instruction ("run bootstrap then rerun preview")
|
|
144
144
|
// hit the same refusal on the retry, because `fireforge bootstrap` alone
|
|
145
145
|
// produces only `.in`. Either name is sufficient to prove the Rust
|
|
146
|
-
// toolchain is registered
|
|
146
|
+
// toolchain is registered. The stronger `hasBuildArtifacts` check above
|
|
147
147
|
// already guards against a completely un-configured tree.
|
|
148
148
|
const cargoConfigPath = join(engineDir, '.cargo', 'config.toml');
|
|
149
149
|
const cargoConfigInPath = join(engineDir, '.cargo', 'config.toml.in');
|
|
@@ -158,10 +158,10 @@ async function assertPreviewPrerequisites(engineDir) {
|
|
|
158
158
|
/**
|
|
159
159
|
* Emits a framing banner when the Storybook workspace has not yet had its npm
|
|
160
160
|
* dependencies installed. `mach storybook` drives the install internally and
|
|
161
|
-
* prints ELSPROBLEMS / UNMET DEPENDENCY lines verbatim
|
|
161
|
+
* prints ELSPROBLEMS / UNMET DEPENDENCY lines verbatim. Without this banner
|
|
162
162
|
* operators reliably read the npm output as a failure.
|
|
163
163
|
*
|
|
164
|
-
* Skipped when `--install` was explicitly requested
|
|
164
|
+
* Skipped when `--install` was explicitly requested, since that path runs
|
|
165
165
|
* `mach storybook upgrade` before the preview launches, so the npm output
|
|
166
166
|
* for the subsequent `mach storybook` invocation is a no-op.
|
|
167
167
|
*/
|
|
@@ -177,9 +177,9 @@ async function announceStorybookFirstRunIfNeeded(engineDir, installRequested) {
|
|
|
177
177
|
/**
|
|
178
178
|
* Surfaces an explicit success banner after a clean mach-storybook
|
|
179
179
|
* exit so the operator's scrollback visually terminates the npm noise
|
|
180
|
-
* from the first-run install. Only fires on expected exit codes
|
|
181
|
-
*
|
|
182
|
-
*
|
|
180
|
+
* from the first-run install. Only fires on expected exit codes. Non-zero
|
|
181
|
+
* cases fall through to the existing `buildStorybookFailureMessage`
|
|
182
|
+
* classification.
|
|
183
183
|
*/
|
|
184
184
|
function announceStorybookCleanExitIfApplicable(exitCode) {
|
|
185
185
|
if (exitCode === 0 || exitCode === 130 || exitCode === 143) {
|
|
@@ -212,9 +212,9 @@ export async function furnacePreviewCommand(projectRoot, options = {}) {
|
|
|
212
212
|
await assertPreviewPrerequisites(paths.engine);
|
|
213
213
|
let previewResult;
|
|
214
214
|
// True once we are about to (or have) written to engine/.../stories/furnace.
|
|
215
|
-
//
|
|
216
|
-
//
|
|
217
|
-
// full-directory wipe, so it is correct to run against partial state
|
|
215
|
+
// Set before `syncStories` is awaited so a mid-sync failure still
|
|
216
|
+
// triggers `cleanStories` during teardown. `cleanStories` is a
|
|
217
|
+
// full-directory wipe, so it is correct to run against partial state,
|
|
218
218
|
// including state with zero files, where it is a cheap no-op.
|
|
219
219
|
let storiesCleanupRequired = false;
|
|
220
220
|
let previewJournal;
|
|
@@ -264,7 +264,7 @@ export async function furnacePreviewCommand(projectRoot, options = {}) {
|
|
|
264
264
|
stageSpinner.stop(`Staged ${stageResult.applied.length} component${stageResult.applied.length === 1 ? '' : 's'} for preview`);
|
|
265
265
|
}
|
|
266
266
|
// Sync story files. Set the cleanup flag before the await so a partial
|
|
267
|
-
// write failure still triggers the teardown wipe
|
|
267
|
+
// write failure still triggers the teardown wipe. `syncStories` writes
|
|
268
268
|
// files incrementally with no internal cleanup of its own.
|
|
269
269
|
const syncSpinner = spinner('Syncing component stories...');
|
|
270
270
|
storiesCleanupRequired = true;
|
|
@@ -299,7 +299,7 @@ export async function furnacePreviewCommand(projectRoot, options = {}) {
|
|
|
299
299
|
// cleanStories must not prevent the journal restore, and vice versa.
|
|
300
300
|
// Running teardown in a `finally` that calls
|
|
301
301
|
// `restoreRollbackJournalOrThrow` throws synchronously, bypassing the
|
|
302
|
-
// primary error and skipping downstream handling
|
|
302
|
+
// primary error and skipping downstream handling, so the engine is left
|
|
303
303
|
// with staged files and the user gets a teardown message with no
|
|
304
304
|
// guidance. Both failures are collected instead and, if anything went
|
|
305
305
|
// wrong, a `pendingRepair` marker is persisted for `fireforge doctor` to
|
|
@@ -90,8 +90,8 @@ async function refreshSingleOverride(projectRoot, name, options = {}) {
|
|
|
90
90
|
}
|
|
91
91
|
return { results: [], currentVersion };
|
|
92
92
|
}
|
|
93
|
-
// Prefer the per-override baseCommit (survives download --force)
|
|
94
|
-
// to the project-wide value for overrides created before this field existed.
|
|
93
|
+
// Prefer the per-override baseCommit (survives download --force). Fall
|
|
94
|
+
// back to the project-wide value for overrides created before this field existed.
|
|
95
95
|
const baseCommit = overrideConfig.baseCommit ?? state.baseCommit;
|
|
96
96
|
if (!baseCommit) {
|
|
97
97
|
throw new FurnaceError('Cannot refresh: baseCommit not found. Re-run "fireforge download" to establish a baseline, ' +
|
|
@@ -126,7 +126,15 @@ async function refreshSingleOverride(projectRoot, name, options = {}) {
|
|
|
126
126
|
for (const entry of overrideFiles) {
|
|
127
127
|
const overridePath = join(overrideDir, entry.name);
|
|
128
128
|
const engineRelPath = getOverrideEngineTargetPath(paths.engine, overrideConfig, entry.name, ftlDir).slice(paths.engine.length + 1);
|
|
129
|
-
const result = await refreshOverrideFile(
|
|
129
|
+
const result = await refreshOverrideFile({
|
|
130
|
+
engineDir: paths.engine,
|
|
131
|
+
overridePath,
|
|
132
|
+
engineRelPath,
|
|
133
|
+
baseCommit,
|
|
134
|
+
fileName: entry.name,
|
|
135
|
+
dryRun,
|
|
136
|
+
strategy,
|
|
137
|
+
});
|
|
130
138
|
fileResults.push(result);
|
|
131
139
|
}
|
|
132
140
|
// Update baseVersion and baseCommit on clean merge (not dry-run, no conflicts)
|
|
@@ -145,7 +153,7 @@ async function refreshSingleOverride(projectRoot, name, options = {}) {
|
|
|
145
153
|
return fileResults;
|
|
146
154
|
}
|
|
147
155
|
catch (error) {
|
|
148
|
-
// A dry run wrote nothing, so there is no journal to restore
|
|
156
|
+
// A dry run wrote nothing, so there is no journal to restore. It
|
|
149
157
|
// rethrows without touching the lifecycle wrapper.
|
|
150
158
|
if (!dryRun) {
|
|
151
159
|
return await completeJournalRollback(ctx, journal, error, {
|
|
@@ -163,7 +171,7 @@ async function refreshSingleOverride(projectRoot, name, options = {}) {
|
|
|
163
171
|
/**
|
|
164
172
|
* Refreshes every override sequentially, tallying merged/conflict/
|
|
165
173
|
* unchanged file counts. Per-override errors are expected (warned and
|
|
166
|
-
* recorded as failures) and do not abort the batch
|
|
174
|
+
* recorded as failures) and do not abort the batch. Only an error that
|
|
167
175
|
* escapes this function entirely warrants the caller's journal rollback.
|
|
168
176
|
*/
|
|
169
177
|
async function runBatchRefresh(projectRoot, overrideNames, options) {
|
|
@@ -224,7 +232,7 @@ export async function furnaceRefreshCommand(projectRoot, name, options = {}) {
|
|
|
224
232
|
if (name && refreshAll) {
|
|
225
233
|
throw new FurnaceError('Cannot specify both a component name and --all. Use one or the other.');
|
|
226
234
|
}
|
|
227
|
-
// Verify engine exists
|
|
235
|
+
// Verify engine exists: refresh reads engine files for three-way merge
|
|
228
236
|
// and --reset-base reads engine HEAD. Without this check, the user gets
|
|
229
237
|
// an obscure git error instead of a clear precondition message.
|
|
230
238
|
await assertFurnaceEngineReady(projectRoot);
|
|
@@ -257,7 +265,7 @@ export async function furnaceRefreshCommand(projectRoot, name, options = {}) {
|
|
|
257
265
|
}
|
|
258
266
|
// Snapshot furnace.json before the batch loop so an unexpected failure
|
|
259
267
|
// (process crash, unhandled error) can be recovered from. Per-component
|
|
260
|
-
// errors caught below are expected and do not trigger a restore
|
|
268
|
+
// errors caught below are expected and do not trigger a restore. Only
|
|
261
269
|
// an error that escapes the loop entirely warrants rolling back.
|
|
262
270
|
const batchJournal = dryRun ? undefined : createRollbackJournal();
|
|
263
271
|
if (batchJournal) {
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import { getFurnacePaths } from '../../core/furnace-config.js';
|
|
1
|
+
import type { FurnacePaths } from '../../core/furnace-config.js';
|
|
3
2
|
import type { RollbackJournal } from '../../core/furnace-rollback.js';
|
|
4
|
-
import type { FurnaceState } from '../../types/furnace.js';
|
|
3
|
+
import type { FurnaceConfig, FurnaceState } from '../../types/furnace.js';
|
|
5
4
|
/**
|
|
6
|
-
* Engine-side and workspace-side removal for an
|
|
5
|
+
* Engine-side and workspace-side removal for an override component.
|
|
7
6
|
*
|
|
8
7
|
* Runs inside the caller's rollback journal rather than opening its own, so
|
|
9
8
|
* a failure anywhere in the remove still restores the whole operation as a
|
|
@@ -14,15 +13,15 @@ export declare function performOverrideRemovalMutations(args: {
|
|
|
14
13
|
paths: {
|
|
15
14
|
engine: string;
|
|
16
15
|
};
|
|
17
|
-
furnacePaths:
|
|
18
|
-
freshConfig:
|
|
16
|
+
furnacePaths: FurnacePaths;
|
|
17
|
+
freshConfig: FurnaceConfig;
|
|
19
18
|
freshState: FurnaceState;
|
|
20
19
|
ftlDir: string;
|
|
21
20
|
journal: RollbackJournal;
|
|
22
21
|
}): Promise<void>;
|
|
23
22
|
/**
|
|
24
|
-
* Engine-side and workspace-side removal for a
|
|
25
|
-
* Sibling of {@link performOverrideRemovalMutations}
|
|
23
|
+
* Engine-side and workspace-side removal for a custom component.
|
|
24
|
+
* Sibling of {@link performOverrideRemovalMutations}. See its note.
|
|
26
25
|
*/
|
|
27
26
|
export declare function performCustomRemovalMutations(args: {
|
|
28
27
|
projectRoot: string;
|
|
@@ -30,8 +29,8 @@ export declare function performCustomRemovalMutations(args: {
|
|
|
30
29
|
paths: {
|
|
31
30
|
engine: string;
|
|
32
31
|
};
|
|
33
|
-
furnacePaths:
|
|
34
|
-
freshConfig:
|
|
32
|
+
furnacePaths: FurnacePaths;
|
|
33
|
+
freshConfig: FurnaceConfig;
|
|
35
34
|
ftlDir: string;
|
|
36
35
|
journal: RollbackJournal;
|
|
37
36
|
}): Promise<void>;
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* `furnaceRemoveCommand` at the per-function cap. Extracting them inside the
|
|
8
8
|
* same file would trade a function-length problem for a file-length one.
|
|
9
9
|
*
|
|
10
|
-
* Both run inside the
|
|
10
|
+
* Both run inside the caller's rollback journal rather than opening their
|
|
11
11
|
* own, so a failure anywhere in the remove still restores the whole
|
|
12
12
|
* operation as a single unit.
|
|
13
13
|
*/
|
|
@@ -16,7 +16,6 @@ import { join } from 'node:path';
|
|
|
16
16
|
import { removeCustomFtlJarMnEntry } from '../../core/furnace-apply-ftl.js';
|
|
17
17
|
import { getOverrideEngineTargetPath, isOverrideCopyCandidate, restoreOverrideFileToBaseline, } from '../../core/furnace-apply-helpers.js';
|
|
18
18
|
import { extractComponentChecksums } from '../../core/furnace-checksum-utils.js';
|
|
19
|
-
import { getFurnacePaths } from '../../core/furnace-config.js';
|
|
20
19
|
import { removeCustomElementRegistration, removeJarMnEntries, } from '../../core/furnace-registration.js';
|
|
21
20
|
import { snapshotDir, snapshotFile } from '../../core/furnace-rollback.js';
|
|
22
21
|
import { isGitRepository } from '../../core/git.js';
|
|
@@ -28,12 +27,12 @@ import { removeDeployedCustomFiles } from './remove-state.js';
|
|
|
28
27
|
/**
|
|
29
28
|
* Restores every override-deployed file in `engine/` to its pristine HEAD
|
|
30
29
|
* state, inverting what `applyOverrideComponent` would have written. Files that
|
|
31
|
-
* existed in HEAD are restored via `git restore
|
|
30
|
+
* existed in HEAD are restored via `git restore`. Files the override
|
|
32
31
|
* introduced (not in HEAD) are deleted outright.
|
|
33
32
|
*
|
|
34
|
-
* The restore set is the
|
|
35
|
-
* workspace directory and (b) filenames recorded in `previousChecksumKeys
|
|
36
|
-
*
|
|
33
|
+
* The restore set is the union of (a) files currently in the override
|
|
34
|
+
* workspace directory and (b) filenames recorded in `previousChecksumKeys`,
|
|
35
|
+
* i.e. files we know we deployed last time, even if the developer has
|
|
37
36
|
* since deleted them from the workspace. Without (b), a workspace deletion
|
|
38
37
|
* leaves an orphaned engine copy that `furnace remove` would never see.
|
|
39
38
|
*
|
|
@@ -44,14 +43,15 @@ import { removeDeployedCustomFiles } from './remove-state.js';
|
|
|
44
43
|
async function restoreOverrideEngineFiles(engineDir, overrideDir, overrideConfig, previousChecksumKeys, ftlDir, journal) {
|
|
45
44
|
// Engine-as-git is a hard precondition for restoration: git HEAD is the only
|
|
46
45
|
// honest oracle for "what was there before the override". If the engine is
|
|
47
|
-
// not a git repo we refuse rather than silently leaving files behind
|
|
48
|
-
// previous warn
|
|
46
|
+
// not a git repo we refuse rather than silently leaving files behind. The
|
|
47
|
+
// previous behaviour was to warn and continue, which is what this fix
|
|
48
|
+
// removes.
|
|
49
49
|
if (!(await isGitRepository(engineDir))) {
|
|
50
50
|
throw new FurnaceError('Cannot restore override files: engine is not a git repository. Run "fireforge download" to initialise it.');
|
|
51
51
|
}
|
|
52
52
|
// Build the union of "files we still see on disk" and "files state.json
|
|
53
53
|
// claims we deployed". The state set is the only authority for files that
|
|
54
|
-
// were deployed and later deleted from the workspace
|
|
54
|
+
// were deployed and later deleted from the workspace. The workspace set is
|
|
55
55
|
// the only authority for files added since last apply that have not yet
|
|
56
56
|
// been recorded in state. We need both.
|
|
57
57
|
const fileSet = new Set();
|
|
@@ -81,7 +81,7 @@ async function restoreOverrideEngineFiles(engineDir, overrideDir, overrideConfig
|
|
|
81
81
|
return { restored, removed };
|
|
82
82
|
}
|
|
83
83
|
/**
|
|
84
|
-
* Engine-side and workspace-side removal for an
|
|
84
|
+
* Engine-side and workspace-side removal for an override component.
|
|
85
85
|
*
|
|
86
86
|
* Runs inside the caller's rollback journal rather than opening its own, so
|
|
87
87
|
* a failure anywhere in the remove still restores the whole operation as a
|
|
@@ -91,10 +91,10 @@ export async function performOverrideRemovalMutations(args) {
|
|
|
91
91
|
const { name, paths, furnacePaths, freshConfig, freshState, ftlDir, journal } = args;
|
|
92
92
|
const overrideConfig = freshConfig.overrides[name];
|
|
93
93
|
const dir = join(furnacePaths.overridesDir, name);
|
|
94
|
-
// Restore deployed engine files
|
|
94
|
+
// Restore deployed engine files before removing the workspace
|
|
95
95
|
// directory. The restore set is the union of (a) files currently in
|
|
96
|
-
// the workspace and (b) files state.json says we deployed last time
|
|
97
|
-
//
|
|
96
|
+
// the workspace and (b) files state.json says we deployed last time.
|
|
97
|
+
// Without (b), source-side deletions would orphan engine copies
|
|
98
98
|
// that this command can never see again.
|
|
99
99
|
if (overrideConfig?.basePath) {
|
|
100
100
|
const previousKeys = Object.keys(extractComponentChecksums(freshState.appliedChecksums, 'override', name));
|
|
@@ -113,8 +113,8 @@ export async function performOverrideRemovalMutations(args) {
|
|
|
113
113
|
}
|
|
114
114
|
}
|
|
115
115
|
/**
|
|
116
|
-
* Engine-side and workspace-side removal for a
|
|
117
|
-
* Sibling of {@link performOverrideRemovalMutations}
|
|
116
|
+
* Engine-side and workspace-side removal for a custom component.
|
|
117
|
+
* Sibling of {@link performOverrideRemovalMutations}. See its note.
|
|
118
118
|
*/
|
|
119
119
|
export async function performCustomRemovalMutations(args) {
|
|
120
120
|
const { projectRoot, name, paths, furnacePaths, freshConfig, ftlDir, journal } = args;
|
|
@@ -141,12 +141,12 @@ export async function performCustomRemovalMutations(args) {
|
|
|
141
141
|
await removeDir(dir);
|
|
142
142
|
info(`Deleted components/custom/${name}/`);
|
|
143
143
|
}
|
|
144
|
-
// Clean up deployed files in engine (per-file
|
|
144
|
+
// Clean up deployed files in engine (per-file, see helper doc).
|
|
145
145
|
if (customConfig?.targetPath) {
|
|
146
146
|
await removeDeployedCustomFiles(projectRoot, paths.engine, name, customConfig.targetPath, journal);
|
|
147
147
|
}
|
|
148
148
|
// Localized components deploy a .ftl outside targetPath into the
|
|
149
|
-
// shared Fluent tree
|
|
149
|
+
// shared Fluent tree. Apply writes it, so remove must delete it too
|
|
150
150
|
// or the locale payload is orphaned.
|
|
151
151
|
if (customConfig?.localized) {
|
|
152
152
|
const ftlRel = join(ftlDir, `${name}.ftl`);
|
|
@@ -155,12 +155,12 @@ export async function performCustomRemovalMutations(args) {
|
|
|
155
155
|
await snapshotFile(journal, ftlPath);
|
|
156
156
|
await removeFile(ftlPath);
|
|
157
157
|
// `ftlRel` is a native join, so on Windows an interpolated
|
|
158
|
-
// `engine/${ftlRel}` renders as `engine/toolkit\locales
|
|
158
|
+
// `engine/${ftlRel}` renders as `engine/toolkit\locales\...`, one
|
|
159
159
|
// message with both separators. Print the engine-relative form.
|
|
160
160
|
info(`Deleted localized file engine/${normalizePathSlashes(ftlRel)}`);
|
|
161
161
|
}
|
|
162
162
|
// Drop the locale jar.mn chrome registration that `applyCustomFtlFile`
|
|
163
|
-
// wrote during deploy
|
|
163
|
+
// wrote during deploy. Otherwise the engine is left with a
|
|
164
164
|
// `locale/.../${name}.ftl` entry pointing at a file just deleted, which
|
|
165
165
|
// breaks the next package-manifest validation.
|
|
166
166
|
await removeCustomFtlJarMnEntry(paths.engine, `${name}.ftl`, ftlDir, customConfig, journal);
|
|
@@ -10,7 +10,7 @@ export declare function dropChecksumsByPrefix(state: FurnaceState, prefix: strin
|
|
|
10
10
|
* Per-file, never a recursive `removeDir` of the whole directory: nothing
|
|
11
11
|
* stops two components from sharing a targetPath (or a hand-edited config
|
|
12
12
|
* from pointing at an upstream-shared directory), and the recursive delete
|
|
13
|
-
* permanently destroyed the co-located files on success
|
|
13
|
+
* permanently destroyed the co-located files on success. The rollback
|
|
14
14
|
* journal only protects the failure path. Deployed files come from the
|
|
15
15
|
* component's state checksums, falling back to the conventional
|
|
16
16
|
* `<name>.{mjs,css,ftl}` set when state carries no record (cleared by a
|
|
@@ -24,7 +24,7 @@ export function dropChecksumsByPrefix(state, prefix) {
|
|
|
24
24
|
* Per-file, never a recursive `removeDir` of the whole directory: nothing
|
|
25
25
|
* stops two components from sharing a targetPath (or a hand-edited config
|
|
26
26
|
* from pointing at an upstream-shared directory), and the recursive delete
|
|
27
|
-
* permanently destroyed the co-located files on success
|
|
27
|
+
* permanently destroyed the co-located files on success. The rollback
|
|
28
28
|
* journal only protects the failure path. Deployed files come from the
|
|
29
29
|
* component's state checksums, falling back to the conventional
|
|
30
30
|
* `<name>.{mjs,css,ftl}` set when state carries no record (cleared by a
|