@hominis/fireforge 0.43.1 → 0.44.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 +153 -0
- package/README.md +3 -3
- package/dist/bin/fireforge.d.ts +4 -9
- package/dist/bin/fireforge.js +42 -40
- package/dist/build-info.json +4 -4
- package/dist/src/cli.js +74 -8
- package/dist/src/commands/bootstrap.js +17 -20
- package/dist/src/commands/build.js +25 -32
- package/dist/src/commands/config.js +34 -41
- package/dist/src/commands/discard.js +8 -9
- package/dist/src/commands/doctor-check-core.d.ts +13 -18
- package/dist/src/commands/doctor-check-core.js +8 -35
- package/dist/src/commands/doctor-external-toolchains.js +2 -2
- package/dist/src/commands/doctor-furnace-config-sync.d.ts +18 -0
- package/dist/src/commands/{doctor-furnace-manifest-sync.js → doctor-furnace-config-sync.js} +27 -26
- package/dist/src/commands/doctor-furnace-jar.d.ts +7 -9
- package/dist/src/commands/doctor-furnace-jar.js +7 -9
- package/dist/src/commands/doctor-furnace.js +21 -24
- package/dist/src/commands/doctor-orphaned-harness.d.ts +16 -20
- package/dist/src/commands/doctor-orphaned-harness.js +18 -44
- package/dist/src/commands/doctor-patch-manifest.d.ts +8 -0
- package/dist/src/commands/doctor-patch-manifest.js +155 -0
- package/dist/src/commands/doctor-post-rebase-audit.d.ts +2 -0
- package/dist/src/commands/{doctor/post-rebase-audit.js → doctor-post-rebase-audit.js} +3 -3
- package/dist/src/commands/doctor-working-tree.d.ts +10 -12
- package/dist/src/commands/doctor-working-tree.js +11 -18
- package/dist/src/commands/doctor.d.ts +1 -1
- package/dist/src/commands/doctor.js +64 -96
- package/dist/src/commands/download.js +32 -48
- package/dist/src/commands/export-all.js +29 -33
- package/dist/src/commands/export-flow.js +6 -6
- package/dist/src/commands/export-placement-conflicts.js +10 -9
- package/dist/src/commands/export-placement-gate.js +5 -5
- package/dist/src/commands/export-shared.d.ts +30 -33
- package/dist/src/commands/export-shared.js +45 -43
- package/dist/src/commands/export.js +21 -27
- package/dist/src/commands/furnace/apply.js +14 -23
- package/dist/src/commands/furnace/chrome-doc-remove.js +14 -21
- package/dist/src/commands/furnace/chrome-doc-templates.d.ts +23 -23
- package/dist/src/commands/furnace/chrome-doc-templates.js +23 -23
- package/dist/src/commands/furnace/chrome-doc-tests.js +26 -29
- package/dist/src/commands/furnace/chrome-doc.d.ts +16 -17
- package/dist/src/commands/furnace/chrome-doc.js +31 -41
- package/dist/src/commands/furnace/create-browser-test.d.ts +4 -4
- package/dist/src/commands/furnace/create-browser-test.js +8 -8
- package/dist/src/commands/furnace/create-mochikit.d.ts +6 -7
- package/dist/src/commands/furnace/create-mochikit.js +8 -9
- package/dist/src/commands/furnace/create-readback.d.ts +12 -13
- package/dist/src/commands/furnace/create-readback.js +12 -13
- package/dist/src/commands/furnace/create-templates.d.ts +22 -28
- package/dist/src/commands/furnace/create-templates.js +35 -30
- package/dist/src/commands/furnace/create-xpcshell.js +2 -2
- package/dist/src/commands/furnace/create.js +33 -23
- package/dist/src/commands/furnace/deploy.js +16 -24
- package/dist/src/commands/furnace/diff.js +15 -10
- package/dist/src/commands/furnace/init.js +33 -36
- package/dist/src/commands/furnace/override.js +23 -25
- package/dist/src/commands/furnace/preview.js +47 -67
- package/dist/src/commands/furnace/refresh.js +12 -16
- package/dist/src/commands/furnace/remove-mutations.d.ts +3 -6
- package/dist/src/commands/furnace/remove-mutations.js +14 -17
- package/dist/src/commands/furnace/remove-state.js +1 -1
- package/dist/src/commands/furnace/remove.js +33 -38
- package/dist/src/commands/furnace/rename-xpcshell.d.ts +8 -11
- package/dist/src/commands/furnace/rename-xpcshell.js +8 -11
- package/dist/src/commands/furnace/rename.js +59 -69
- package/dist/src/commands/furnace/scan.js +19 -33
- package/dist/src/commands/furnace/status.js +12 -9
- package/dist/src/commands/furnace/sync.js +9 -16
- package/dist/src/commands/furnace/validate.js +20 -20
- package/dist/src/commands/import.js +48 -37
- package/dist/src/commands/lint-per-patch.js +15 -10
- package/dist/src/commands/lint-per-run-checkjs.d.ts +13 -13
- package/dist/src/commands/lint-per-run-checkjs.js +13 -13
- package/dist/src/commands/lint-report.js +6 -7
- package/dist/src/commands/lint.d.ts +15 -16
- package/dist/src/commands/lint.js +86 -102
- package/dist/src/commands/package.js +6 -11
- package/dist/src/commands/patch/compact.js +1 -1
- package/dist/src/commands/patch/delete.js +24 -33
- package/dist/src/commands/patch/index.d.ts +5 -6
- package/dist/src/commands/patch/index.js +10 -12
- package/dist/src/commands/patch/lint-ignore.js +14 -13
- package/dist/src/commands/patch/move-files-create.d.ts +6 -6
- package/dist/src/commands/patch/move-files-create.js +8 -8
- package/dist/src/commands/patch/move-files-into.d.ts +6 -6
- package/dist/src/commands/patch/move-files-into.js +8 -8
- package/dist/src/commands/patch/patch-context.d.ts +2 -3
- package/dist/src/commands/patch/patch-context.js +2 -3
- package/dist/src/commands/patch/rename.d.ts +10 -11
- package/dist/src/commands/patch/rename.js +11 -12
- package/dist/src/commands/patch/reorder.js +8 -9
- package/dist/src/commands/patch/split-plan.js +1 -1
- package/dist/src/commands/patch/split.d.ts +8 -10
- package/dist/src/commands/patch/split.js +9 -11
- package/dist/src/commands/patch/staged-dependency-validate.js +8 -8
- package/dist/src/commands/patch/staged-dependency.js +7 -3
- package/dist/src/commands/patch/tier.d.ts +9 -9
- package/dist/src/commands/patch/tier.js +18 -15
- package/dist/src/commands/re-export-adjacent.js +9 -8
- package/dist/src/commands/re-export-bulk-scan.d.ts +9 -9
- package/dist/src/commands/re-export-bulk-scan.js +22 -21
- package/dist/src/commands/re-export-drift.js +10 -10
- package/dist/src/commands/re-export-files.d.ts +6 -7
- package/dist/src/commands/re-export-files.js +34 -44
- package/dist/src/commands/re-export-lint.d.ts +10 -13
- package/dist/src/commands/re-export-lint.js +16 -14
- package/dist/src/commands/re-export-options.d.ts +6 -6
- package/dist/src/commands/re-export-options.js +6 -6
- package/dist/src/commands/re-export-register.d.ts +4 -10
- package/dist/src/commands/re-export-register.js +5 -11
- package/dist/src/commands/re-export-scan.js +1 -1
- package/dist/src/commands/re-export-single.d.ts +3 -3
- package/dist/src/commands/re-export-single.js +33 -25
- package/dist/src/commands/re-export.js +13 -21
- package/dist/src/commands/rebase/abort.js +3 -3
- package/dist/src/commands/rebase/confirm.js +2 -1
- package/dist/src/commands/rebase/continue.d.ts +1 -1
- package/dist/src/commands/rebase/continue.js +14 -9
- package/dist/src/commands/rebase/index.js +11 -11
- package/dist/src/commands/rebase/patch-loop.d.ts +7 -1
- package/dist/src/commands/rebase/patch-loop.js +60 -39
- package/dist/src/commands/rebase/summary.js +1 -1
- package/dist/src/commands/register.js +5 -7
- package/dist/src/commands/reset.js +2 -1
- package/dist/src/commands/resolve.d.ts +16 -13
- package/dist/src/commands/resolve.js +30 -33
- package/dist/src/commands/run.js +33 -35
- package/dist/src/commands/setup-support.js +15 -19
- package/dist/src/commands/setup.js +13 -9
- package/dist/src/commands/status-check.d.ts +6 -6
- package/dist/src/commands/status-json.d.ts +6 -6
- package/dist/src/commands/status-json.js +5 -0
- package/dist/src/commands/status-output.d.ts +5 -5
- package/dist/src/commands/status-output.js +6 -6
- package/dist/src/commands/status-ownership.d.ts +16 -14
- package/dist/src/commands/status-ownership.js +16 -14
- package/dist/src/commands/status.js +42 -34
- package/dist/src/commands/test-build-phase.js +26 -13
- package/dist/src/commands/test-diagnose.js +44 -44
- package/dist/src/commands/test-register.js +1 -0
- package/dist/src/commands/test-run.d.ts +14 -16
- package/dist/src/commands/test-run.js +21 -13
- package/dist/src/commands/test-stale-gate.d.ts +15 -16
- package/dist/src/commands/test-stale-gate.js +15 -16
- package/dist/src/commands/test-verdict.d.ts +20 -3
- package/dist/src/commands/test-verdict.js +30 -0
- package/dist/src/commands/test.js +83 -76
- package/dist/src/commands/token-coverage.js +3 -4
- package/dist/src/commands/token.js +16 -18
- package/dist/src/commands/tree.js +47 -31
- package/dist/src/commands/typecheck.d.ts +10 -12
- package/dist/src/commands/typecheck.js +24 -27
- package/dist/src/commands/verify.js +13 -15
- package/dist/src/commands/watch.js +21 -23
- package/dist/src/commands/wire.js +52 -62
- package/dist/src/core/ast-utils.d.ts +8 -7
- package/dist/src/core/ast-utils.js +8 -7
- package/dist/src/core/branding.d.ts +9 -14
- package/dist/src/core/branding.js +7 -11
- package/dist/src/core/browser-wire.d.ts +1 -1
- package/dist/src/core/browser-wire.js +14 -19
- package/dist/src/core/build-audit-platform.js +25 -33
- package/dist/src/core/build-audit-registration.js +17 -25
- package/dist/src/core/build-audit-resolve.d.ts +15 -17
- package/dist/src/core/build-audit-resolve.js +39 -36
- package/dist/src/core/build-audit-transforms.js +18 -19
- package/dist/src/core/build-audit.js +28 -42
- package/dist/src/core/build-baseline-types.d.ts +29 -35
- package/dist/src/core/build-baseline.d.ts +5 -4
- package/dist/src/core/build-baseline.js +14 -14
- package/dist/src/core/build-overwrite-guard.d.ts +7 -14
- package/dist/src/core/build-overwrite-guard.js +17 -27
- package/dist/src/core/build-prepare.d.ts +2 -2
- package/dist/src/core/build-prepare.js +8 -9
- package/dist/src/core/config-mutate.js +20 -19
- package/dist/src/core/config-state.js +12 -4
- package/dist/src/core/config-validate.js +8 -5
- package/dist/src/core/config.d.ts +5 -8
- package/dist/src/core/config.js +7 -16
- package/dist/src/core/coverage-extend.d.ts +15 -13
- package/dist/src/core/coverage-extend.js +15 -13
- package/dist/src/core/destructive.d.ts +31 -9
- package/dist/src/core/destructive.js +29 -26
- package/dist/src/core/diff-hunks.js +10 -12
- package/dist/src/core/discard-baseline.d.ts +8 -8
- package/dist/src/core/discard-baseline.js +16 -15
- package/dist/src/core/display-state.d.ts +12 -14
- package/dist/src/core/display-state.js +12 -14
- package/dist/src/core/engine-changes.d.ts +2 -4
- package/dist/src/core/engine-changes.js +2 -4
- package/dist/src/core/engine-precondition.d.ts +28 -13
- package/dist/src/core/engine-precondition.js +25 -10
- package/dist/src/core/engine-session-lock.d.ts +47 -21
- package/dist/src/core/engine-session-lock.js +168 -33
- package/dist/src/core/export-moved-code-shape.d.ts +10 -10
- package/dist/src/core/export-moved-code-shape.js +10 -10
- package/dist/src/core/file-lock.d.ts +62 -5
- package/dist/src/core/file-lock.js +196 -59
- package/dist/src/core/firefox-cache.js +1 -3
- package/dist/src/core/firefox-extract.js +10 -14
- package/dist/src/core/firefox.d.ts +7 -5
- package/dist/src/core/firefox.js +4 -5
- package/dist/src/core/furnace-apply-dry-run.d.ts +2 -2
- package/dist/src/core/furnace-apply-dry-run.js +3 -2
- package/dist/src/core/furnace-apply-ftl.d.ts +7 -9
- package/dist/src/core/furnace-apply-ftl.js +16 -13
- package/dist/src/core/furnace-apply-helpers.d.ts +7 -7
- package/dist/src/core/furnace-apply-helpers.js +30 -21
- package/dist/src/core/furnace-apply-overwrite-warn.d.ts +8 -9
- package/dist/src/core/furnace-apply-overwrite-warn.js +8 -9
- package/dist/src/core/furnace-apply-undeploy-actions.d.ts +3 -4
- package/dist/src/core/furnace-apply-undeploy-actions.js +3 -4
- package/dist/src/core/furnace-apply.d.ts +5 -8
- package/dist/src/core/furnace-apply.js +19 -24
- package/dist/src/core/furnace-checksum-utils.d.ts +14 -0
- package/dist/src/core/furnace-checksum-utils.js +16 -0
- package/dist/src/core/furnace-config.d.ts +21 -30
- package/dist/src/core/furnace-config.js +32 -54
- package/dist/src/core/furnace-constants.d.ts +8 -0
- package/dist/src/core/furnace-constants.js +10 -2
- package/dist/src/core/furnace-css-fragments.d.ts +5 -5
- package/dist/src/core/furnace-css-fragments.js +5 -5
- package/dist/src/core/furnace-jsconfig.d.ts +11 -12
- package/dist/src/core/furnace-jsconfig.js +11 -12
- package/dist/src/core/furnace-marker.d.ts +7 -8
- package/dist/src/core/furnace-marker.js +7 -8
- package/dist/src/core/furnace-operation.d.ts +31 -0
- package/dist/src/core/furnace-operation.js +54 -17
- package/dist/src/core/furnace-precondition.d.ts +61 -0
- package/dist/src/core/furnace-precondition.js +67 -0
- package/dist/src/core/furnace-registration-remove.d.ts +5 -6
- package/dist/src/core/furnace-registration-remove.js +6 -7
- package/dist/src/core/furnace-registration-validate.d.ts +13 -0
- package/dist/src/core/furnace-registration-validate.js +20 -1
- package/dist/src/core/furnace-registration.d.ts +5 -6
- package/dist/src/core/furnace-registration.js +10 -12
- package/dist/src/core/furnace-rollback.js +7 -7
- package/dist/src/core/furnace-scanner.d.ts +1 -0
- package/dist/src/core/furnace-scanner.js +1 -2
- package/dist/src/core/furnace-stale-export.d.ts +10 -10
- package/dist/src/core/furnace-stale-export.js +10 -10
- package/dist/src/core/furnace-state-persist.d.ts +6 -8
- package/dist/src/core/furnace-state-persist.js +6 -8
- package/dist/src/core/furnace-validate-accessibility.d.ts +22 -0
- package/dist/src/core/furnace-validate-accessibility.js +310 -1
- package/dist/src/core/furnace-validate-compatibility.js +141 -1
- package/dist/src/core/furnace-validate-helpers.d.ts +5 -116
- package/dist/src/core/furnace-validate-helpers.js +0 -491
- package/dist/src/core/furnace-validate-registration.d.ts +7 -0
- package/dist/src/core/furnace-validate-registration.js +115 -41
- package/dist/src/core/furnace-validate.d.ts +16 -0
- package/dist/src/core/furnace-validate.js +188 -145
- package/dist/src/core/furnace-version-drift.d.ts +10 -11
- package/dist/src/core/furnace-version-drift.js +10 -11
- package/dist/src/core/git-base.d.ts +21 -9
- package/dist/src/core/git-base.js +24 -9
- package/dist/src/core/git-diff.d.ts +20 -9
- package/dist/src/core/git-diff.js +148 -63
- package/dist/src/core/git-file-ops.d.ts +19 -19
- package/dist/src/core/git-file-ops.js +19 -19
- package/dist/src/core/git-readonly-index.d.ts +53 -19
- package/dist/src/core/git-readonly-index.js +75 -31
- package/dist/src/core/git-status.d.ts +5 -6
- package/dist/src/core/git-status.js +5 -6
- package/dist/src/core/git.d.ts +9 -10
- package/dist/src/core/git.js +57 -71
- package/dist/src/core/license-headers.d.ts +17 -23
- package/dist/src/core/license-headers.js +17 -23
- package/dist/src/core/mach-build-artifacts.d.ts +9 -9
- package/dist/src/core/mach-build-artifacts.js +57 -19
- package/dist/src/core/mach-error-hints.js +42 -29
- package/dist/src/core/mach-known-noise-filter.d.ts +15 -16
- package/dist/src/core/mach-known-noise-filter.js +18 -20
- package/dist/src/core/mach-mozconfig.d.ts +14 -0
- package/dist/src/core/mach-mozconfig.js +30 -0
- package/dist/src/core/mach-resource-shim.d.ts +43 -58
- package/dist/src/core/mach-resource-shim.js +50 -67
- package/dist/src/core/mach.d.ts +37 -41
- package/dist/src/core/mach.js +50 -51
- package/dist/src/core/marionette-port.d.ts +36 -1
- package/dist/src/core/marionette-port.js +96 -31
- package/dist/src/core/marionette-preflight.d.ts +8 -12
- package/dist/src/core/marionette-preflight.js +86 -52
- package/dist/src/core/mochitest-server-port.d.ts +42 -0
- package/dist/src/core/mochitest-server-port.js +119 -0
- package/dist/src/core/module-resolution-preflight.d.ts +9 -11
- package/dist/src/core/module-resolution-preflight.js +9 -11
- package/dist/src/core/moz-manifest-helpers.d.ts +79 -0
- package/dist/src/core/moz-manifest-helpers.js +163 -0
- package/dist/src/core/{manifest-register.d.ts → moz-manifest-register.d.ts} +1 -1
- package/dist/src/core/{manifest-register.js → moz-manifest-register.js} +13 -28
- package/dist/src/core/{manifest-rules.d.ts → moz-manifest-rules.d.ts} +10 -1
- package/dist/src/core/{manifest-rules.js → moz-manifest-rules.js} +31 -24
- package/dist/src/core/{manifest-tokenizers.d.ts → moz-manifest-tokenizers.d.ts} +3 -5
- package/dist/src/core/{manifest-tokenizers.js → moz-manifest-tokenizers.js} +9 -12
- package/dist/src/core/ownership-table.d.ts +14 -16
- package/dist/src/core/ownership-table.js +14 -16
- package/dist/src/core/parser-fallback.d.ts +15 -1
- package/dist/src/core/parser-fallback.js +22 -3
- package/dist/src/core/patch-apply-fuzz.d.ts +10 -12
- package/dist/src/core/patch-apply-fuzz.js +15 -18
- package/dist/src/core/patch-apply.d.ts +13 -34
- package/dist/src/core/patch-apply.js +16 -76
- package/dist/src/core/patch-artifact-normalize.d.ts +13 -15
- package/dist/src/core/patch-artifact-normalize.js +13 -15
- package/dist/src/core/patch-export-metadata.d.ts +12 -2
- package/dist/src/core/patch-export-metadata.js +13 -4
- package/dist/src/core/patch-export-update.d.ts +13 -1
- package/dist/src/core/patch-export-update.js +25 -8
- package/dist/src/core/patch-export.d.ts +15 -8
- package/dist/src/core/patch-export.js +10 -11
- package/dist/src/core/patch-files.d.ts +5 -6
- package/dist/src/core/patch-files.js +5 -6
- package/dist/src/core/patch-identifier-suggest.d.ts +7 -12
- package/dist/src/core/patch-identifier-suggest.js +14 -19
- package/dist/src/core/patch-lint-binary.d.ts +51 -0
- package/dist/src/core/patch-lint-binary.js +39 -0
- package/dist/src/core/{lint-cache.d.ts → patch-lint-cache.d.ts} +5 -5
- package/dist/src/core/{lint-cache.js → patch-lint-cache.js} +21 -23
- package/dist/src/core/patch-lint-checkjs.d.ts +16 -16
- package/dist/src/core/patch-lint-checkjs.js +41 -20
- package/dist/src/core/patch-lint-chrome-jsdoc.d.ts +6 -9
- package/dist/src/core/patch-lint-chrome-jsdoc.js +10 -14
- package/dist/src/core/patch-lint-creators.d.ts +8 -8
- package/dist/src/core/patch-lint-creators.js +8 -8
- package/dist/src/core/patch-lint-cross.d.ts +17 -20
- package/dist/src/core/patch-lint-cross.js +16 -16
- package/dist/src/core/patch-lint-css.d.ts +3 -5
- package/dist/src/core/patch-lint-css.js +17 -22
- package/dist/src/core/patch-lint-diff-tag.d.ts +14 -16
- package/dist/src/core/patch-lint-diff-tag.js +14 -16
- package/dist/src/core/patch-lint-jsdoc.d.ts +7 -8
- package/dist/src/core/patch-lint-jsdoc.js +26 -19
- package/dist/src/core/patch-lint-mozbuild.js +20 -20
- package/dist/src/core/patch-lint-observer.d.ts +7 -7
- package/dist/src/core/patch-lint-observer.js +7 -7
- package/dist/src/core/patch-lint.d.ts +38 -29
- package/dist/src/core/patch-lint.js +89 -121
- package/dist/src/core/patch-lock.d.ts +1 -1
- package/dist/src/core/patch-lock.js +45 -9
- package/dist/src/core/patch-manifest-consistency.d.ts +57 -6
- package/dist/src/core/patch-manifest-consistency.js +111 -40
- package/dist/src/core/patch-manifest-files-affected.d.ts +43 -0
- package/dist/src/core/patch-manifest-files-affected.js +77 -0
- package/dist/src/core/patch-manifest-io.js +14 -18
- package/dist/src/core/patch-manifest-resolve.d.ts +9 -12
- package/dist/src/core/patch-manifest-resolve.js +9 -12
- package/dist/src/core/patch-manifest-validate.d.ts +6 -1
- package/dist/src/core/patch-manifest-validate.js +25 -13
- package/dist/src/core/patch-manifest.d.ts +2 -1
- package/dist/src/core/patch-manifest.js +2 -1
- package/dist/src/core/patch-parse.d.ts +24 -13
- package/dist/src/core/patch-parse.js +19 -14
- package/dist/src/core/patch-policy.d.ts +2 -2
- package/dist/src/core/patch-policy.js +2 -2
- package/dist/src/core/patch-registration-refs.d.ts +7 -8
- package/dist/src/core/patch-registration-refs.js +9 -9
- package/dist/src/core/process-cpu-time.d.ts +12 -0
- package/dist/src/core/process-cpu-time.js +52 -0
- package/dist/src/core/rebase-session.d.ts +38 -26
- package/dist/src/core/rebase-session.js +55 -28
- package/dist/src/core/register-browser-content.js +9 -74
- package/dist/src/core/{register-test-manifest.js → register-browser-test.js} +7 -42
- package/dist/src/core/register-module.js +10 -43
- package/dist/src/core/register-scaffold.d.ts +8 -8
- package/dist/src/core/register-scaffold.js +10 -10
- package/dist/src/core/register-shared-css.d.ts +9 -12
- package/dist/src/core/register-shared-css.js +17 -87
- package/dist/src/core/register-xpcshell-test.d.ts +6 -7
- package/dist/src/core/register-xpcshell-test.js +7 -8
- package/dist/src/core/shared-ftl.js +12 -4
- package/dist/src/core/state-file.d.ts +45 -0
- package/dist/src/core/state-file.js +34 -0
- package/dist/src/core/status-binary.d.ts +18 -11
- package/dist/src/core/status-binary.js +19 -12
- package/dist/src/core/status-classify.d.ts +30 -36
- package/dist/src/core/status-classify.js +21 -26
- package/dist/src/core/test-changed-prefs.d.ts +30 -0
- package/dist/src/core/test-changed-prefs.js +78 -0
- package/dist/src/core/test-harness-crash.d.ts +25 -63
- package/dist/src/core/test-harness-crash.js +121 -142
- package/dist/src/core/test-harness-signature.d.ts +18 -0
- package/dist/src/core/test-harness-signature.js +13 -0
- package/dist/src/core/test-path-scope.d.ts +12 -15
- package/dist/src/core/test-path-scope.js +15 -18
- package/dist/src/core/test-stale-check.d.ts +17 -17
- package/dist/src/core/test-stale-check.js +50 -43
- package/dist/src/core/test-stall-triage.d.ts +51 -0
- package/dist/src/core/test-stall-triage.js +126 -0
- package/dist/src/core/token-category.js +66 -14
- package/dist/src/core/token-coverage.js +9 -9
- package/dist/src/core/token-dark-mode.d.ts +9 -11
- package/dist/src/core/token-dark-mode.js +29 -13
- package/dist/src/core/token-docs.d.ts +2 -0
- package/dist/src/core/token-docs.js +3 -1
- package/dist/src/core/token-manager.d.ts +10 -2
- package/dist/src/core/token-manager.js +17 -8
- package/dist/src/core/token-scaffold.d.ts +7 -7
- package/dist/src/core/token-scaffold.js +7 -7
- package/dist/src/core/token-variant.d.ts +4 -4
- package/dist/src/core/token-variant.js +28 -6
- package/dist/src/core/toolchain-preflight.d.ts +20 -21
- package/dist/src/core/toolchain-preflight.js +28 -31
- package/dist/src/core/tree-guard.js +12 -2
- package/dist/src/core/tree-store.d.ts +41 -27
- package/dist/src/core/tree-store.js +68 -43
- package/dist/src/core/typecheck-shim.d.ts +23 -24
- package/dist/src/core/typecheck-shim.js +23 -24
- package/dist/src/core/typecheck.js +15 -9
- package/dist/src/core/wire-destroy.d.ts +3 -3
- package/dist/src/core/wire-destroy.js +7 -15
- package/dist/src/core/wire-dom-fragment.d.ts +9 -17
- package/dist/src/core/wire-dom-fragment.js +11 -44
- package/dist/src/core/wire-init.d.ts +2 -3
- package/dist/src/core/wire-init.js +8 -19
- package/dist/src/core/wire-subscript.d.ts +2 -3
- package/dist/src/core/wire-subscript.js +4 -13
- package/dist/src/core/wire-utils.d.ts +7 -8
- package/dist/src/core/wire-utils.js +7 -8
- package/dist/src/core/xpcshell-appdir.d.ts +38 -45
- package/dist/src/core/xpcshell-appdir.js +38 -45
- package/dist/src/errors/base.d.ts +37 -16
- package/dist/src/errors/base.js +37 -16
- package/dist/src/errors/build.d.ts +13 -1
- package/dist/src/errors/build.js +14 -2
- package/dist/src/errors/codes.d.ts +16 -0
- package/dist/src/errors/codes.js +16 -0
- package/dist/src/errors/furnace.d.ts +4 -4
- package/dist/src/errors/git.d.ts +6 -10
- package/dist/src/errors/git.js +6 -10
- package/dist/src/errors/patch.d.ts +7 -7
- package/dist/src/errors/patch.js +7 -7
- package/dist/src/errors/rebase.d.ts +4 -4
- package/dist/src/errors/rebase.js +4 -4
- package/dist/src/index.d.ts +7 -1
- package/dist/src/index.js +5 -0
- package/dist/src/types/commands/index.d.ts +2 -2
- package/dist/src/types/commands/options.d.ts +111 -70
- package/dist/src/types/commands/patches.d.ts +24 -34
- package/dist/src/types/commands/project.d.ts +5 -34
- package/dist/src/types/config.d.ts +25 -23
- package/dist/src/types/config.js +6 -1
- package/dist/src/types/furnace.d.ts +37 -13
- package/dist/src/types/furnace.js +19 -1
- package/dist/src/types/index.d.ts +3 -3
- package/dist/src/utils/build-info.d.ts +7 -8
- package/dist/src/utils/build-info.js +12 -11
- package/dist/src/utils/errors.d.ts +6 -8
- package/dist/src/utils/errors.js +6 -8
- package/dist/src/utils/logger.d.ts +27 -10
- package/dist/src/utils/logger.js +28 -16
- package/dist/src/utils/machine-output.d.ts +12 -0
- package/dist/src/utils/machine-output.js +33 -0
- package/dist/src/utils/options.d.ts +31 -14
- package/dist/src/utils/options.js +86 -30
- package/dist/src/utils/paths.d.ts +10 -8
- package/dist/src/utils/paths.js +10 -8
- package/dist/src/utils/platform.d.ts +0 -25
- package/dist/src/utils/platform.js +1 -42
- package/dist/src/utils/process-group.d.ts +9 -4
- package/dist/src/utils/process-group.js +19 -5
- package/dist/src/utils/process.d.ts +42 -7
- package/dist/src/utils/process.js +44 -17
- package/dist/src/utils/ps-duration.d.ts +31 -0
- package/dist/src/utils/ps-duration.js +70 -0
- package/dist/src/utils/regex.d.ts +9 -10
- package/dist/src/utils/regex.js +9 -10
- package/dist/src/utils/validation.d.ts +58 -28
- package/dist/src/utils/validation.js +60 -33
- package/package.json +3 -3
- package/dist/src/commands/doctor/post-rebase-audit.d.ts +0 -2
- package/dist/src/commands/doctor-furnace-manifest-sync.d.ts +0 -18
- package/dist/src/core/manifest-helpers.d.ts +0 -38
- package/dist/src/core/manifest-helpers.js +0 -120
- /package/dist/src/core/{lint-projection.d.ts → patch-lint-projection.d.ts} +0 -0
- /package/dist/src/core/{lint-projection.js → patch-lint-projection.js} +0 -0
- /package/dist/src/core/{register-test-manifest.d.ts → register-browser-test.d.ts} +0 -0
|
@@ -25,14 +25,25 @@
|
|
|
25
25
|
* 3. `<name>.ftl` — fallback when no chrome sub-path was resolvable.
|
|
26
26
|
*/
|
|
27
27
|
export function generateMjsContent(name, className, description, localized, header, ftlChromeSubPath, sharedFtl) {
|
|
28
|
+
// A `*/` in the operator-supplied description would close the JSDoc block
|
|
29
|
+
// early and leave the remainder as stray code. Escaped here rather than
|
|
30
|
+
// rejected at input, because the same text is also rendered by
|
|
31
|
+
// create-dry-run.ts, where no escaping is wanted.
|
|
32
|
+
const jsDocDescription = (description || name).replace(/\*\//g, '*\\/');
|
|
28
33
|
const ftlPath = sharedFtl !== undefined
|
|
29
34
|
? sharedFtl
|
|
30
35
|
: ftlChromeSubPath !== undefined
|
|
31
36
|
? `${ftlChromeSubPath}/${name}.ftl`
|
|
32
37
|
: `${name}.ftl`;
|
|
38
|
+
// Escape at the SINK, not at the validator. `ftlPath` reaches here from
|
|
39
|
+
// three sources — the `--shared-ftl` flag, the furnace.json `ftlBasePath`,
|
|
40
|
+
// and a derived `<name>.ftl` — and only the first passes through
|
|
41
|
+
// `validateSharedFtl`. `JSON.stringify` produces a correctly-escaped JS
|
|
42
|
+
// string literal for all of them, including the `"` and raw-newline cases
|
|
43
|
+
// that would otherwise break the generated module into a syntax error.
|
|
33
44
|
const ftlModulePreamble = localized
|
|
34
45
|
? `
|
|
35
|
-
window.MozXULElement?.insertFTLIfNeeded(
|
|
46
|
+
window.MozXULElement?.insertFTLIfNeeded(${JSON.stringify(ftlPath)});
|
|
36
47
|
`
|
|
37
48
|
: '';
|
|
38
49
|
const lifecycleHooks = localized
|
|
@@ -60,7 +71,7 @@ import { html } from "chrome://global/content/vendor/lit.all.mjs";
|
|
|
60
71
|
import { MozLitElement } from "chrome://global/content/lit-utils.mjs";
|
|
61
72
|
${ftlModulePreamble}
|
|
62
73
|
/**
|
|
63
|
-
* ${
|
|
74
|
+
* ${jsDocDescription}
|
|
64
75
|
*
|
|
65
76
|
* @tagname ${name}
|
|
66
77
|
*/
|
|
@@ -108,19 +119,18 @@ export function xpcshellTestFileName(name) {
|
|
|
108
119
|
* xpcshell cannot execute a component module that imports
|
|
109
120
|
* `chrome://global/content/vendor/lit.all.mjs` — the Lit bundle touches
|
|
110
121
|
* `window` at module-load time and the xpcshell harness has no `window`
|
|
111
|
-
* global.
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
* that couldn't fix a runtime-environment incompatibility.
|
|
122
|
+
* global. A scaffold that calls `ChromeUtils.importESModule` on the
|
|
123
|
+
* component's MJS therefore fails with `ReferenceError: window is not
|
|
124
|
+
* defined` for every Lit-based fork component, and FireForge's diagnostics
|
|
125
|
+
* misroute that to the "stale build artifacts" branch, sending operators on
|
|
126
|
+
* a rebuild loop that cannot fix a runtime-environment incompatibility.
|
|
117
127
|
*
|
|
118
|
-
*
|
|
128
|
+
* This template mirrors the chrome-doc packaging test instead: XCurProcD is
|
|
119
129
|
* probed at a pair of candidate layouts (dist/bin/browser and the macOS
|
|
120
|
-
* .app-bundle / ESR layout) to confirm the `.mjs` and `.css` files
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
*
|
|
130
|
+
* .app-bundle / ESR layout) to confirm the `.mjs` and `.css` files landed
|
|
131
|
+
* where jar.mn promised. That is the assertion xpcshell CAN make. Functional
|
|
132
|
+
* tests that need DOM/shadow-root/keyboard behaviour belong in a
|
|
133
|
+
* browser-chrome mochitest — scaffolded via
|
|
124
134
|
* `fireforge furnace create --test-style browser-chrome`.
|
|
125
135
|
*/
|
|
126
136
|
export function generateXpcshellTestContent(name, header) {
|
|
@@ -225,26 +235,21 @@ export function mochikitTestFileName(name) {
|
|
|
225
235
|
* MochiKit tests load the component module directly via the global chrome
|
|
226
236
|
* URI and assert that `customElements.get(<tag>)` returns a constructor.
|
|
227
237
|
* They run on forks whose top-level chrome document lacks a `tabbrowser`
|
|
228
|
-
*
|
|
229
|
-
* they do not traverse `URILoadingHelper.openLinkIn`.
|
|
238
|
+
* because they do not traverse `URILoadingHelper.openLinkIn`.
|
|
230
239
|
*
|
|
231
|
-
* The scaffold
|
|
232
|
-
* constructor is a function. Real UI assertions (render output, l10n
|
|
233
|
-
*
|
|
234
|
-
*
|
|
235
|
-
*
|
|
236
|
-
* rely on.
|
|
240
|
+
* The scaffold is a smoke test — the component is defined and the
|
|
241
|
+
* constructor is a function. Real UI assertions (render output, l10n wiring,
|
|
242
|
+
* keyboard interactions) are left out because they depend on the
|
|
243
|
+
* component's shape; operators can extend the test using the same SimpleTest
|
|
244
|
+
* APIs upstream toolkit widgets rely on.
|
|
237
245
|
*
|
|
238
246
|
* The template deliberately omits `SimpleTest.waitForExplicitFinish()`.
|
|
239
|
-
* `add_task` owns the test lifecycle: when every queued task resolves,
|
|
240
|
-
*
|
|
241
|
-
* `waitForExplicitFinish()` with `add_task`
|
|
242
|
-
* `SimpleTest.finish()`
|
|
243
|
-
*
|
|
244
|
-
*
|
|
245
|
-
* test. Leaving `waitForExplicitFinish()` out matches the convention
|
|
246
|
-
* upstream toolkit widget tests use (see `test_moz-button.html` and
|
|
247
|
-
* siblings under `toolkit/content/tests/widgets/`).
|
|
247
|
+
* `add_task` owns the test lifecycle: when every queued task resolves, the
|
|
248
|
+
* task harness calls `SimpleTest.finish()` itself. Combining
|
|
249
|
+
* `waitForExplicitFinish()` with `add_task` and no explicit
|
|
250
|
+
* `SimpleTest.finish()` in the task body makes the harness wait forever —
|
|
251
|
+
* an indefinite hang on `fireforge test --headless`. Omitting it matches the
|
|
252
|
+
* convention upstream toolkit widget tests use.
|
|
248
253
|
*/
|
|
249
254
|
export function generateMochikitTestContent(name) {
|
|
250
255
|
return `<!DOCTYPE html>
|
|
@@ -43,8 +43,8 @@ export async function scaffoldXpcshellTestFiles(componentName, license, forgeCon
|
|
|
43
43
|
const testFileName = xpcshellTestFileName(componentName);
|
|
44
44
|
const testFilePath = join(testDir, testFileName);
|
|
45
45
|
if (await pathExists(testFilePath)) {
|
|
46
|
-
// Never clobber an existing test implementation
|
|
47
|
-
//
|
|
46
|
+
// Never clobber an existing test implementation: the scaffold must not
|
|
47
|
+
// overwrite files owned by a different patch.
|
|
48
48
|
warn(`${testDirRel}/${testFileName} already exists — keeping the existing file.`);
|
|
49
49
|
}
|
|
50
50
|
else {
|
|
@@ -2,17 +2,17 @@
|
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { text } from '@clack/prompts';
|
|
4
4
|
import { getProjectPaths, loadConfig } from '../../core/config.js';
|
|
5
|
+
import { stdioIsInteractive } from '../../core/destructive.js';
|
|
5
6
|
import { createDefaultFurnaceConfig, furnaceConfigExists, getFurnacePaths, loadFurnaceConfig, writeFurnaceConfig, } from '../../core/furnace-config.js';
|
|
6
|
-
import { resolveFtlChromeSubPath, tagNameToClassName } from '../../core/furnace-constants.js';
|
|
7
|
-
import {
|
|
8
|
-
import { CUSTOM_ELEMENT_TAG_PATTERN, CUSTOM_ELEMENT_TAG_RULES, } from '../../core/furnace-registration-validate.js';
|
|
9
|
-
import { createRollbackJournal, recordCreatedDir,
|
|
7
|
+
import { resolveFtlChromeSubPath, tagNameToClassName, WIDGETS_DIR, } from '../../core/furnace-constants.js';
|
|
8
|
+
import { completeJournalRollback, runFurnaceMutation, } from '../../core/furnace-operation.js';
|
|
9
|
+
import { CUSTOM_ELEMENT_TAG_PATTERN, CUSTOM_ELEMENT_TAG_RULES, describeTagNameProblem, } from '../../core/furnace-registration-validate.js';
|
|
10
|
+
import { createRollbackJournal, recordCreatedDir, snapshotFile, } from '../../core/furnace-rollback.js';
|
|
10
11
|
import { isComponentInEngine, scanWidgetsDirectory } from '../../core/furnace-scanner.js';
|
|
11
12
|
import { DEFAULT_LICENSE, getLicenseHeader } from '../../core/license-headers.js';
|
|
12
13
|
import { validateSharedFtl } from '../../core/shared-ftl.js';
|
|
13
14
|
import { InvalidArgumentError } from '../../errors/base.js';
|
|
14
15
|
import { FurnaceError } from '../../errors/furnace.js';
|
|
15
|
-
import { toError } from '../../utils/errors.js';
|
|
16
16
|
import { ensureDir, pathExists, writeText } from '../../utils/fs.js';
|
|
17
17
|
import { cancel, intro, isCancel, note, outro } from '../../utils/logger.js';
|
|
18
18
|
import { resolveValidatedTestDir, scaffoldTestFiles } from './create-browser-test.js';
|
|
@@ -70,6 +70,8 @@ function validateTagName(name) {
|
|
|
70
70
|
* @param description - Human-readable component description
|
|
71
71
|
* @param localized - Whether to include a Fluent file
|
|
72
72
|
* @param license - Project license used for generated headers
|
|
73
|
+
* @param ftlChromeSubPath - chrome:// sub-path for the generated FTL reference, when localized
|
|
74
|
+
* @param sharedFtl - Explicit shared FTL path from `--shared-ftl`, when supplied
|
|
73
75
|
* @param journal - Optional rollback journal that snapshots files before writes
|
|
74
76
|
* @returns Relative filenames written for the component
|
|
75
77
|
*/
|
|
@@ -166,7 +168,7 @@ async function performCreateMutations(args) {
|
|
|
166
168
|
files = await writeComponentFiles(args.componentDir, args.componentName, args.className, args.description, args.localized, args.license, resolveFtlChromeSubPath(freshConfig.ftlBasePath), args.sharedFtl, journal);
|
|
167
169
|
const customEntry = {
|
|
168
170
|
description: args.description,
|
|
169
|
-
targetPath:
|
|
171
|
+
targetPath: `${WIDGETS_DIR}/${args.componentName}`,
|
|
170
172
|
register: args.register,
|
|
171
173
|
localized: args.localized,
|
|
172
174
|
};
|
|
@@ -199,15 +201,16 @@ async function performCreateMutations(args) {
|
|
|
199
201
|
}
|
|
200
202
|
}
|
|
201
203
|
catch (error) {
|
|
202
|
-
//
|
|
203
|
-
//
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
await
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
204
|
+
// `operationContext` is optional here (the dry-run and no-journal paths
|
|
205
|
+
// pass none), so the shared handler only applies when there is a
|
|
206
|
+
// lifecycle wrapper to tell.
|
|
207
|
+
if (args.operationContext) {
|
|
208
|
+
return await completeJournalRollback(args.operationContext, journal, error, {
|
|
209
|
+
projectRoot: args.projectRoot,
|
|
210
|
+
operation: 'create-rollback',
|
|
211
|
+
failureMessage: `Failed to create custom component "${args.componentName}"`,
|
|
212
|
+
subject: `component "${args.componentName}"`,
|
|
213
|
+
});
|
|
211
214
|
}
|
|
212
215
|
throw error;
|
|
213
216
|
}
|
|
@@ -237,7 +240,7 @@ async function resolveDescription(isInteractive, options) {
|
|
|
237
240
|
* @param options - CLI options for non-interactive mode
|
|
238
241
|
*/
|
|
239
242
|
export async function furnaceCreateCommand(projectRoot, name, options = {}) {
|
|
240
|
-
const isInteractive =
|
|
243
|
+
const isInteractive = stdioIsInteractive();
|
|
241
244
|
const isDryRun = options.dryRun ?? false;
|
|
242
245
|
intro(isDryRun ? 'Furnace Create (dry run)' : 'Furnace Create');
|
|
243
246
|
// --- Resolve component name ---
|
|
@@ -264,7 +267,9 @@ export async function furnaceCreateCommand(projectRoot, name, options = {}) {
|
|
|
264
267
|
const nameResult = await text({
|
|
265
268
|
message: 'Component tag name:',
|
|
266
269
|
placeholder: 'moz-my-widget',
|
|
267
|
-
|
|
270
|
+
// Message-returning form: the throwing `validateTagName` escaped
|
|
271
|
+
// clack's validation loop and killed the prompt on a bad name.
|
|
272
|
+
validate: (value) => describeTagNameProblem(value ?? ''),
|
|
268
273
|
});
|
|
269
274
|
if (isCancel(nameResult)) {
|
|
270
275
|
cancel('Create cancelled');
|
|
@@ -304,6 +309,11 @@ export async function furnaceCreateCommand(projectRoot, name, options = {}) {
|
|
|
304
309
|
// partial mutation behind.
|
|
305
310
|
const testStyle = resolveTestStyle(options);
|
|
306
311
|
const testDir = resolveValidatedTestDir(options.testDir, testStyle);
|
|
312
|
+
// Not routed through assertFurnaceEngineReady: this rung is CONDITIONAL on
|
|
313
|
+
// a test style being requested, and it names the component so the refusal
|
|
314
|
+
// identifies which create failed. Both are outside the shared helper's
|
|
315
|
+
// shape, and a scaffold without --with-tests must keep working with no
|
|
316
|
+
// engine present.
|
|
307
317
|
if (testStyle !== 'none' && !(await pathExists(paths.engine))) {
|
|
308
318
|
throw new FurnaceError('Engine directory not found. Run "fireforge download" first to use --with-tests, --xpcshell, or --test-style.', componentName);
|
|
309
319
|
}
|
|
@@ -314,13 +324,13 @@ export async function furnaceCreateCommand(projectRoot, name, options = {}) {
|
|
|
314
324
|
if (await pathExists(componentDir)) {
|
|
315
325
|
throw new FurnaceError(`Directory already exists: components/custom/${componentName}`, componentName);
|
|
316
326
|
}
|
|
317
|
-
//
|
|
327
|
+
// Normalize and validate --shared-ftl ahead of any writes. Shares the
|
|
318
328
|
// structural rules with furnace-config.ts so the command and the on-disk
|
|
319
|
-
// schema cannot diverge. Pass the resolved `localized` rather than a
|
|
320
|
-
//
|
|
321
|
-
//
|
|
322
|
-
//
|
|
323
|
-
//
|
|
329
|
+
// schema cannot diverge. Pass the resolved `localized` rather than a `true`
|
|
330
|
+
// literal so the validator's cross-field check stays anchored to the real
|
|
331
|
+
// feature selection — `resolveCreateFeatures` promotes localized upstream,
|
|
332
|
+
// and hard-coding `true` here would hide a regression if that promotion
|
|
333
|
+
// ever moved or dropped.
|
|
324
334
|
let sharedFtl;
|
|
325
335
|
if (options.sharedFtl !== undefined) {
|
|
326
336
|
const result = validateSharedFtl(options.sharedFtl, { localized });
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
-
import {
|
|
2
|
+
import { loadConfig } from '../../core/config.js';
|
|
3
3
|
import { applyAllComponents } from '../../core/furnace-apply.js';
|
|
4
4
|
import { logApplyResult } from '../../core/furnace-apply-output.js';
|
|
5
|
-
import {
|
|
5
|
+
import { getFurnacePaths, loadFurnaceConfig } from '../../core/furnace-config.js';
|
|
6
6
|
import { reportJsconfigPathsSync } from '../../core/furnace-jsconfig.js';
|
|
7
7
|
import { runFurnaceMutation } from '../../core/furnace-operation.js';
|
|
8
|
+
import { assertFurnaceReady } from '../../core/furnace-precondition.js';
|
|
8
9
|
import { getPersistableAppliedEntry, getStepFailureCount, persistSingleComponentState, shouldPersistSingleComponentState, } from '../../core/furnace-state-persist.js';
|
|
9
10
|
import { hasBlockingStepErrors } from '../../core/furnace-step-errors.js';
|
|
10
11
|
import { findOverrideBaseVersionDrift, formatOverrideBaseVersionDriftError, formatOverrideBaseVersionDriftWarning, } from '../../core/furnace-version-drift.js';
|
|
11
12
|
import { FurnaceError } from '../../errors/furnace.js';
|
|
12
|
-
import { pathExists } from '../../utils/fs.js';
|
|
13
13
|
import { info, intro, note, outro, spinner, warn } from '../../utils/logger.js';
|
|
14
14
|
import { runDeployValidation } from './validation-output.js';
|
|
15
15
|
/**
|
|
@@ -39,28 +39,29 @@ function getFailedComponentNames(result) {
|
|
|
39
39
|
return failed;
|
|
40
40
|
}
|
|
41
41
|
/**
|
|
42
|
-
* Applies a single named override or custom component in targeted deploy
|
|
42
|
+
* Applies a single named override or custom component in targeted deploy
|
|
43
|
+
* mode.
|
|
43
44
|
*
|
|
44
45
|
* Delegates to {@link applyAllComponents} with a `componentName` filter so
|
|
45
46
|
* targeted deploys run the exact same pipeline as deploy-all — including
|
|
46
47
|
* workspace-deletion detection, engine orphan undeploy, and jar.mn /
|
|
47
|
-
* customElements.js re-sync.
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
* line in the engine (field report D1).
|
|
48
|
+
* customElements.js re-sync. Calling the per-component apply helpers
|
|
49
|
+
* directly never prunes: renaming a helper file in the workspace then leaves
|
|
50
|
+
* the old deployed file and its stale jar.mn line in the engine.
|
|
51
51
|
*
|
|
52
52
|
* `persistState: false` is load-bearing: the batch persist path *replaces*
|
|
53
53
|
* `appliedChecksums` wholesale with only this run's entries, which for a
|
|
54
54
|
* named deploy would wipe every other component's state. Named deploy keeps
|
|
55
55
|
* its per-component state merge ({@link persistSingleComponentState}) and
|
|
56
|
-
* its atomicity gate ({@link
|
|
57
|
-
* site. Rollback on failure happens inside `applyAllComponents`; the
|
|
58
|
-
*
|
|
56
|
+
* its atomicity gate ({@link shouldPersistSingleComponentState}) at the call
|
|
57
|
+
* site. Rollback on failure happens inside `applyAllComponents`; the journal
|
|
58
|
+
* returned on success is ignored (the deploy keeps its files).
|
|
59
59
|
*
|
|
60
60
|
* @param name - Component name to apply
|
|
61
61
|
* @param config - Loaded Furnace configuration
|
|
62
62
|
* @param isDryRun - Whether file writes should be skipped
|
|
63
|
-
* @returns Apply result for the named component, or `stock` for stock-only
|
|
63
|
+
* @returns Apply result for the named component, or `stock` for stock-only
|
|
64
|
+
* entries
|
|
64
65
|
*/
|
|
65
66
|
async function applyNamedComponent(name, config, isDryRun, projectRoot, operationContext) {
|
|
66
67
|
if (!(name in config.overrides) && !(name in config.custom)) {
|
|
@@ -132,16 +133,7 @@ function enforceScopedOverrideVersionDriftPreflight(scopedDrift, force) {
|
|
|
132
133
|
export async function furnaceDeployCommand(projectRoot, name, options = {}) {
|
|
133
134
|
const isDryRun = options.dryRun ?? false;
|
|
134
135
|
intro(isDryRun ? 'Furnace Deploy (dry run)' : 'Furnace Deploy');
|
|
135
|
-
|
|
136
|
-
const paths = getProjectPaths(projectRoot);
|
|
137
|
-
if (!(await pathExists(paths.engine))) {
|
|
138
|
-
throw new FurnaceError('Engine directory not found. Run "fireforge download" first.');
|
|
139
|
-
}
|
|
140
|
-
// Load furnace config
|
|
141
|
-
if (!(await furnaceConfigExists(projectRoot))) {
|
|
142
|
-
throw new FurnaceError('No furnace.json found. Run "fireforge furnace create" or "fireforge furnace override" to get started.');
|
|
143
|
-
}
|
|
144
|
-
const config = await loadFurnaceConfig(projectRoot);
|
|
136
|
+
const { config } = await assertFurnaceReady(projectRoot);
|
|
145
137
|
const furnacePaths = getFurnacePaths(projectRoot);
|
|
146
138
|
const overrideCount = Object.keys(config.overrides).length;
|
|
147
139
|
const customCount = Object.keys(config.custom).length;
|
|
@@ -196,8 +188,8 @@ export async function furnaceDeployCommand(projectRoot, name, options = {}) {
|
|
|
196
188
|
applySpinner.stop(isDryRun ? 'Planned actions calculated' : 'Components applied');
|
|
197
189
|
logApplyResult(result, isDryRun);
|
|
198
190
|
// Keep the consumer jsconfig's chrome-module `paths` in step with the
|
|
199
|
-
// deployed module set
|
|
200
|
-
//
|
|
191
|
+
// deployed module set. Only after a clean apply — a rolled-back deploy
|
|
192
|
+
// must not advance the typecheck mapping either.
|
|
201
193
|
if (result.errors.length === 0 && getStepFailureCount(result) === 0) {
|
|
202
194
|
await reportJsconfigPathsSync(projectRoot, config, isDryRun);
|
|
203
195
|
}
|
|
@@ -11,6 +11,7 @@ import { FurnaceError } from '../../errors/furnace.js';
|
|
|
11
11
|
import { toError } from '../../utils/errors.js';
|
|
12
12
|
import { pathExists, readText } from '../../utils/fs.js';
|
|
13
13
|
import { formatErrorText, formatSuccessText, info, intro, outro } from '../../utils/logger.js';
|
|
14
|
+
import { normalizePathSlashes } from '../../utils/paths.js';
|
|
14
15
|
/**
|
|
15
16
|
* Renders a multi-hunk unified diff between the two strings and returns a
|
|
16
17
|
* flat list of display-ready lines. Each line has already had its marker
|
|
@@ -64,7 +65,11 @@ async function diffOverride(name, projectRoot, config) {
|
|
|
64
65
|
if (!isComponentSourceFile(entry.name))
|
|
65
66
|
continue;
|
|
66
67
|
// git show takes a repo-relative path. paths.engine IS the repo root.
|
|
67
|
-
|
|
68
|
+
// The slice leaves the host's separators behind, and `git show <ref>:<path>`
|
|
69
|
+
// only understands forward slashes — on Windows the unnormalized form makes
|
|
70
|
+
// every baseline read miss, so every overridden file is reported as a new
|
|
71
|
+
// file and `furnace diff` shows nothing.
|
|
72
|
+
const enginePath = normalizePathSlashes(getOverrideEngineTargetPath(paths.engine, overrideConfig, entry.name, ftlDir).slice(paths.engine.length + 1));
|
|
68
73
|
const modifiedPath = join(overrideDir, entry.name);
|
|
69
74
|
const baselineDisplayPath = enginePath;
|
|
70
75
|
let originalContent;
|
|
@@ -99,16 +104,16 @@ async function diffOverride(name, projectRoot, config) {
|
|
|
99
104
|
}
|
|
100
105
|
}
|
|
101
106
|
/**
|
|
102
|
-
* Diffs a custom component's workspace files against the engine-deployed
|
|
103
|
-
* Shows what would change (or has changed) on the next
|
|
107
|
+
* Diffs a custom component's workspace files against the engine-deployed
|
|
108
|
+
* copy. Shows what would change (or has changed) on the next
|
|
109
|
+
* `furnace apply`.
|
|
104
110
|
*
|
|
105
|
-
* `.ftl` files deploy to `engine/<ftlDir>/<name>.ftl` via
|
|
106
|
-
* — NOT to `customConfig.targetPath` — so the
|
|
107
|
-
* to branch on extension.
|
|
108
|
-
* localization file always
|
|
109
|
-
* file)" after a successful apply
|
|
110
|
-
*
|
|
111
|
-
* locale tree.
|
|
111
|
+
* `.ftl` files deploy to `engine/<ftlDir>/<name>.ftl` via
|
|
112
|
+
* `applyCustomFtlFile` — NOT to `customConfig.targetPath` — so the
|
|
113
|
+
* deployment-target lookup has to branch on extension. Without the branch, a
|
|
114
|
+
* component's localization file always reports "not yet deployed to engine
|
|
115
|
+
* (new file)" after a successful apply, because diff looks for it under the
|
|
116
|
+
* component's `targetPath` while apply wrote it into the locale tree.
|
|
112
117
|
*/
|
|
113
118
|
async function diffCustom(name, projectRoot, config) {
|
|
114
119
|
const customConfig = config.custom[name];
|
|
@@ -3,6 +3,7 @@ import { stat } from 'node:fs/promises';
|
|
|
3
3
|
import { basename, dirname, isAbsolute, join, normalize } from 'node:path';
|
|
4
4
|
import { text } from '@clack/prompts';
|
|
5
5
|
import { getProjectPaths, loadConfig, mutateConfig, writeConfig } from '../../core/config.js';
|
|
6
|
+
import { stdioIsInteractive } from '../../core/destructive.js';
|
|
6
7
|
import { createDefaultFurnaceConfig, furnaceConfigExists, writeFurnaceConfig, } from '../../core/furnace-config.js';
|
|
7
8
|
import { DEFAULT_LICENSE } from '../../core/license-headers.js';
|
|
8
9
|
import { registerSharedCSS } from '../../core/register-shared-css.js';
|
|
@@ -15,17 +16,15 @@ import { cancel, info, intro, isCancel, note, outro, success, warn } from '../..
|
|
|
15
16
|
/**
|
|
16
17
|
* File extensions that are definitely FTL resources (not locale
|
|
17
18
|
* directories). A value ending in one of these is almost certainly the
|
|
18
|
-
* result of the operator pointing at a single FTL file instead of the
|
|
19
|
-
*
|
|
19
|
+
* result of the operator pointing at a single FTL file instead of the locale
|
|
20
|
+
* directory that contains it.
|
|
20
21
|
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* Rejecting file-shaped values up-front keeps the operator on the
|
|
28
|
-
* correct path before any partial state is written.
|
|
22
|
+
* `furnace init --ftl-base-path browser/<name>.ftl` otherwise produces a
|
|
23
|
+
* misleading success path: the subsequent `furnace create --localized`
|
|
24
|
+
* scaffolds an `.mjs` referencing `insertFTLIfNeeded("<name>.ftl")` while
|
|
25
|
+
* furnace.json has no component entry, leaving the scaffold orphaned.
|
|
26
|
+
* Rejecting file-shaped values up-front keeps the operator on the correct
|
|
27
|
+
* path before any partial state is written.
|
|
29
28
|
*/
|
|
30
29
|
const FTL_FILE_EXTENSIONS = new Set(['.ftl', '.properties', '.dtd']);
|
|
31
30
|
function hasFtlFileExtension(value) {
|
|
@@ -112,13 +111,13 @@ export async function furnaceInitCommand(projectRoot, options = {}) {
|
|
|
112
111
|
}
|
|
113
112
|
const paths = getProjectPaths(projectRoot);
|
|
114
113
|
// Seed the default furnace config with a tokenPrefix derived from
|
|
115
|
-
// fireforge.json's binaryName so `token coverage` sees real tokens on
|
|
116
|
-
//
|
|
117
|
-
//
|
|
118
|
-
//
|
|
119
|
-
//
|
|
120
|
-
//
|
|
121
|
-
//
|
|
114
|
+
// fireforge.json's binaryName so `token coverage` sees real tokens on the
|
|
115
|
+
// very first run — without the prefix default, a fresh init → token add →
|
|
116
|
+
// coverage sequence reports `0 tokens / N unknown` because the scan has
|
|
117
|
+
// nothing to key off. Loading fireforge.json here is best-effort: a
|
|
118
|
+
// project without one (mid-setup) falls through to the prefix-less
|
|
119
|
+
// default, and `token coverage` emits its existing "no tokenPrefix"
|
|
120
|
+
// warning.
|
|
122
121
|
let derivedBinaryName;
|
|
123
122
|
try {
|
|
124
123
|
const fireForgeConfig = await loadConfig(projectRoot);
|
|
@@ -129,7 +128,7 @@ export async function furnaceInitCommand(projectRoot, options = {}) {
|
|
|
129
128
|
// rare but not forbidden. Skip the prefix default in that case.
|
|
130
129
|
}
|
|
131
130
|
const config = createDefaultFurnaceConfig(derivedBinaryName ? { binaryName: derivedBinaryName } : {});
|
|
132
|
-
const isInteractive =
|
|
131
|
+
const isInteractive = stdioIsInteractive();
|
|
133
132
|
const engineForValidation = (await pathExists(paths.engine)) ? paths.engine : undefined;
|
|
134
133
|
// Resolve componentPrefix
|
|
135
134
|
if (options.prefix !== undefined) {
|
|
@@ -231,12 +230,11 @@ async function scaffoldTokensCss(projectRoot) {
|
|
|
231
230
|
info(`Tokens CSS already present at engine/${tokensCssPath}; leaving it untouched.`);
|
|
232
231
|
}
|
|
233
232
|
// Registering the tokens file in `patchLint.rawColorAllowlist` is the
|
|
234
|
-
// complement to the scaffold itself: the file exists specifically to
|
|
235
|
-
//
|
|
236
|
-
//
|
|
237
|
-
//
|
|
238
|
-
//
|
|
239
|
-
// does not duplicate the entry.
|
|
233
|
+
// complement to the scaffold itself: the file exists specifically to carry
|
|
234
|
+
// raw color literals, and without the allowlist entry the first
|
|
235
|
+
// `fireforge lint` after a `token add` fails on raw-color-value issues for
|
|
236
|
+
// tokens the operator just created. The add is idempotent, so re-running
|
|
237
|
+
// `furnace init --force` does not duplicate the entry.
|
|
240
238
|
try {
|
|
241
239
|
const existingAllowlist = forgeConfig.patchLint?.rawColorAllowlist ?? [];
|
|
242
240
|
if (!existingAllowlist.includes(tokensCssPath)) {
|
|
@@ -252,18 +250,17 @@ async function scaffoldTokensCss(projectRoot) {
|
|
|
252
250
|
warn(`Could not register tokens CSS in patchLint.rawColorAllowlist: ${toError(error).message}. ` +
|
|
253
251
|
`Add "${tokensCssPath}" manually under patchLint.rawColorAllowlist in fireforge.json if lint flags its contents.`);
|
|
254
252
|
}
|
|
255
|
-
//
|
|
256
|
-
//
|
|
257
|
-
//
|
|
258
|
-
//
|
|
259
|
-
//
|
|
260
|
-
//
|
|
261
|
-
//
|
|
262
|
-
//
|
|
263
|
-
// shared
|
|
264
|
-
//
|
|
265
|
-
//
|
|
266
|
-
// `furnace init --force` against a registered tree is a no-op.
|
|
253
|
+
// Register the tokens CSS in browser/themes/shared/jar.inc.mn so the file
|
|
254
|
+
// is owned end-to-end by tooling. Scaffolding and allowlisting it without
|
|
255
|
+
// registering leaves the very next `fireforge status` correctly flagging
|
|
256
|
+
// it as unmanaged + unregistered while `furnace deploy --dry-run` reports
|
|
257
|
+
// nothing to deploy — a documented init command turning a clean project
|
|
258
|
+
// unclean. The CSS lives at the canonical
|
|
259
|
+
// `browser/themes/shared/<binaryName>-tokens.css` path the shared-CSS rule
|
|
260
|
+
// already targets, so it gets the same
|
|
261
|
+
// `skin/classic/browser/<name>.css (../shared/<name>.css)` entry as any
|
|
262
|
+
// other shared CSS. Idempotent — `furnace init --force` against a
|
|
263
|
+
// registered tree is a no-op.
|
|
267
264
|
try {
|
|
268
265
|
const fileBase = `${forgeConfig.binaryName}-tokens.css`;
|
|
269
266
|
const result = await registerSharedCSS(paths.engine, fileBase, undefined, false);
|
|
@@ -3,11 +3,13 @@ import { readdir } from 'node:fs/promises';
|
|
|
3
3
|
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
|
+
import { stdioIsInteractive } from '../../core/destructive.js';
|
|
6
7
|
import { createDefaultFurnaceConfig, furnaceConfigExists, getFurnacePaths, loadFurnaceConfig, writeFurnaceConfig, } from '../../core/furnace-config.js';
|
|
7
8
|
import { resolveFtlDir } from '../../core/furnace-constants.js';
|
|
8
|
-
import {
|
|
9
|
+
import { completeJournalRollback, runFurnaceMutation } from '../../core/furnace-operation.js';
|
|
10
|
+
import { assertFurnaceEngineReady } from '../../core/furnace-precondition.js';
|
|
9
11
|
import { CUSTOM_ELEMENT_TAG_PATTERN, CUSTOM_ELEMENT_TAG_RULES, } from '../../core/furnace-registration-validate.js';
|
|
10
|
-
import { createRollbackJournal, recordCreatedDir,
|
|
12
|
+
import { createRollbackJournal, recordCreatedDir, snapshotFile, } from '../../core/furnace-rollback.js';
|
|
11
13
|
import { getComponentDetails, scanWidgetsDirectory } from '../../core/furnace-scanner.js';
|
|
12
14
|
import { InvalidArgumentError } from '../../errors/base.js';
|
|
13
15
|
import { FurnaceError } from '../../errors/furnace.js';
|
|
@@ -22,9 +24,14 @@ async function loadAuthoringFurnaceConfig(projectRoot) {
|
|
|
22
24
|
}
|
|
23
25
|
/**
|
|
24
26
|
* Copies the source files needed for a new override into the workspace.
|
|
27
|
+
* @param engineDir - Absolute path to the engine checkout
|
|
25
28
|
* @param srcDir - Original component directory in the engine checkout
|
|
26
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
|
|
27
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
|
|
28
35
|
* @returns Filenames copied into the override directory
|
|
29
36
|
*/
|
|
30
37
|
async function copyOverrideFiles(engineDir, srcDir, destDir, componentName, hasFTL, overrideType, ftlDir, journal) {
|
|
@@ -81,10 +88,10 @@ async function copyOverrideFiles(engineDir, srcDir, destDir, componentName, hasF
|
|
|
81
88
|
/**
|
|
82
89
|
* Writes override metadata to disk and updates furnace.json with the new
|
|
83
90
|
* override entry. Re-reads the current on-disk furnace.json inside the
|
|
84
|
-
* operation lock and splices the new entry onto the fresh state so two
|
|
85
|
-
* concurrent `furnace override` commands cannot race their read-modify
|
|
86
|
-
*
|
|
87
|
-
*
|
|
91
|
+
* operation lock and splices the new entry onto the fresh state, so two
|
|
92
|
+
* concurrent `furnace override` commands cannot race their read-modify-write
|
|
93
|
+
* cycles into a single surviving entry — otherwise both report success and
|
|
94
|
+
* furnace.json keeps only the second writer's.
|
|
88
95
|
*/
|
|
89
96
|
async function saveOverrideConfig(projectRoot, destDir, componentName, overrideType, description, details, firefoxVersion, journal, baseCommit) {
|
|
90
97
|
const overrideJson = {
|
|
@@ -137,17 +144,12 @@ async function performOverrideMutations(args) {
|
|
|
137
144
|
return filesCopied;
|
|
138
145
|
}
|
|
139
146
|
catch (error) {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
}
|
|
146
|
-
catch (rollbackError) {
|
|
147
|
-
await recordFurnaceRollbackFailure(args.projectRoot, 'override-rollback', `component "${args.componentName}": ${toError(rollbackError).message}`);
|
|
148
|
-
throw rollbackError;
|
|
149
|
-
}
|
|
150
|
-
throw error;
|
|
147
|
+
return await completeJournalRollback(ctx, journal, error, {
|
|
148
|
+
projectRoot: args.projectRoot,
|
|
149
|
+
operation: 'override-rollback',
|
|
150
|
+
failureMessage: `Failed to override component "${args.componentName}"`,
|
|
151
|
+
subject: `component "${args.componentName}"`,
|
|
152
|
+
});
|
|
151
153
|
}
|
|
152
154
|
});
|
|
153
155
|
}
|
|
@@ -190,7 +192,7 @@ function promoteStockToOverrideIfNeeded(config, componentName) {
|
|
|
190
192
|
* @param options - CLI options for non-interactive mode
|
|
191
193
|
*/
|
|
192
194
|
export async function furnaceOverrideCommand(projectRoot, name, options = {}) {
|
|
193
|
-
const isInteractive =
|
|
195
|
+
const isInteractive = stdioIsInteractive();
|
|
194
196
|
intro('Furnace Override');
|
|
195
197
|
// --- Validate config-independent inputs BEFORE auto-creating furnace.json
|
|
196
198
|
// so a failed authoring command never strands a fresh config in the
|
|
@@ -205,9 +207,7 @@ export async function furnaceOverrideCommand(projectRoot, name, options = {}) {
|
|
|
205
207
|
'Usage: fireforge furnace override <name> -t <type> -d "description"', 'name');
|
|
206
208
|
}
|
|
207
209
|
// Verify engine/ exists (config-independent precondition)
|
|
208
|
-
|
|
209
|
-
throw new FurnaceError('Engine directory not found. Run "fireforge download" first.');
|
|
210
|
-
}
|
|
210
|
+
await assertFurnaceEngineReady(projectRoot);
|
|
211
211
|
// Load the current config without auto-creating a new furnace.json. A user
|
|
212
212
|
// cancelling out of the interactive prompts should not leave a fresh config
|
|
213
213
|
// behind in an otherwise untouched project.
|
|
@@ -334,14 +334,12 @@ export async function furnaceOverrideCommand(projectRoot, name, options = {}) {
|
|
|
334
334
|
*/
|
|
335
335
|
export async function furnaceBatchOverrideCommand(projectRoot, names, options = {}) {
|
|
336
336
|
intro(`Furnace Override (batch: ${names.length} components)`);
|
|
337
|
-
const isInteractive =
|
|
337
|
+
const isInteractive = stdioIsInteractive();
|
|
338
338
|
if (!options.type && !isInteractive) {
|
|
339
339
|
throw new InvalidArgumentError('Override type is required for batch override in non-interactive mode. Use -t css-only or -t full.', 'type');
|
|
340
340
|
}
|
|
341
341
|
const paths = getProjectPaths(projectRoot);
|
|
342
|
-
|
|
343
|
-
throw new FurnaceError('Engine directory not found. Run "fireforge download" first.');
|
|
344
|
-
}
|
|
342
|
+
await assertFurnaceEngineReady(projectRoot);
|
|
345
343
|
// Validate all names upfront before any mutations
|
|
346
344
|
for (const name of names) {
|
|
347
345
|
if (!CUSTOM_ELEMENT_TAG_PATTERN.test(name)) {
|