@hominis/fireforge 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/LICENSE.md +294 -0
- package/README.md +435 -0
- package/dist/bin/fireforge.d.ts +10 -0
- package/dist/bin/fireforge.js +29 -0
- package/dist/src/cli.d.ts +33 -0
- package/dist/src/cli.js +180 -0
- package/dist/src/commands/bootstrap.d.ts +9 -0
- package/dist/src/commands/bootstrap.js +73 -0
- package/dist/src/commands/build.d.ts +11 -0
- package/dist/src/commands/build.js +102 -0
- package/dist/src/commands/config.d.ts +13 -0
- package/dist/src/commands/config.js +135 -0
- package/dist/src/commands/discard.d.ts +12 -0
- package/dist/src/commands/discard.js +84 -0
- package/dist/src/commands/doctor.d.ts +18 -0
- package/dist/src/commands/doctor.js +356 -0
- package/dist/src/commands/download.d.ts +11 -0
- package/dist/src/commands/download.js +127 -0
- package/dist/src/commands/export-all.d.ts +11 -0
- package/dist/src/commands/export-all.js +122 -0
- package/dist/src/commands/export-shared.d.ts +48 -0
- package/dist/src/commands/export-shared.js +208 -0
- package/dist/src/commands/export.d.ts +13 -0
- package/dist/src/commands/export.js +178 -0
- package/dist/src/commands/furnace/apply.d.ts +7 -0
- package/dist/src/commands/furnace/apply.js +80 -0
- package/dist/src/commands/furnace/create.d.ts +8 -0
- package/dist/src/commands/furnace/create.js +377 -0
- package/dist/src/commands/furnace/deploy.d.ts +8 -0
- package/dist/src/commands/furnace/deploy.js +338 -0
- package/dist/src/commands/furnace/diff.d.ts +7 -0
- package/dist/src/commands/furnace/diff.js +119 -0
- package/dist/src/commands/furnace/index.d.ts +16 -0
- package/dist/src/commands/furnace/index.js +121 -0
- package/dist/src/commands/furnace/list.d.ts +5 -0
- package/dist/src/commands/furnace/list.js +65 -0
- package/dist/src/commands/furnace/override.d.ts +8 -0
- package/dist/src/commands/furnace/override.js +188 -0
- package/dist/src/commands/furnace/preview.d.ts +7 -0
- package/dist/src/commands/furnace/preview.js +96 -0
- package/dist/src/commands/furnace/remove.d.ts +8 -0
- package/dist/src/commands/furnace/remove.js +159 -0
- package/dist/src/commands/furnace/scan.d.ts +5 -0
- package/dist/src/commands/furnace/scan.js +112 -0
- package/dist/src/commands/furnace/status.d.ts +7 -0
- package/dist/src/commands/furnace/status.js +137 -0
- package/dist/src/commands/furnace/validate.d.ts +6 -0
- package/dist/src/commands/furnace/validate.js +91 -0
- package/dist/src/commands/furnace/validation-output.d.ts +7 -0
- package/dist/src/commands/furnace/validation-output.js +22 -0
- package/dist/src/commands/import.d.ts +11 -0
- package/dist/src/commands/import.js +241 -0
- package/dist/src/commands/lint.d.ts +10 -0
- package/dist/src/commands/lint.js +118 -0
- package/dist/src/commands/package.d.ts +11 -0
- package/dist/src/commands/package.js +80 -0
- package/dist/src/commands/re-export.d.ts +12 -0
- package/dist/src/commands/re-export.js +242 -0
- package/dist/src/commands/rebase/abort.d.ts +7 -0
- package/dist/src/commands/rebase/abort.js +49 -0
- package/dist/src/commands/rebase/confirm.d.ts +18 -0
- package/dist/src/commands/rebase/confirm.js +33 -0
- package/dist/src/commands/rebase/continue.d.ts +7 -0
- package/dist/src/commands/rebase/continue.js +81 -0
- package/dist/src/commands/rebase/index.d.ts +22 -0
- package/dist/src/commands/rebase/index.js +127 -0
- package/dist/src/commands/rebase/patch-loop.d.ts +9 -0
- package/dist/src/commands/rebase/patch-loop.js +135 -0
- package/dist/src/commands/rebase/summary.d.ts +12 -0
- package/dist/src/commands/rebase/summary.js +43 -0
- package/dist/src/commands/rebase.d.ts +4 -0
- package/dist/src/commands/rebase.js +6 -0
- package/dist/src/commands/register.d.ts +13 -0
- package/dist/src/commands/register.js +67 -0
- package/dist/src/commands/reset.d.ts +11 -0
- package/dist/src/commands/reset.js +83 -0
- package/dist/src/commands/resolve.d.ts +9 -0
- package/dist/src/commands/resolve.js +124 -0
- package/dist/src/commands/run.d.ts +9 -0
- package/dist/src/commands/run.js +91 -0
- package/dist/src/commands/setup-support.d.ts +23 -0
- package/dist/src/commands/setup-support.js +310 -0
- package/dist/src/commands/setup.d.ts +11 -0
- package/dist/src/commands/setup.js +94 -0
- package/dist/src/commands/status.d.ts +11 -0
- package/dist/src/commands/status.js +268 -0
- package/dist/src/commands/test.d.ts +12 -0
- package/dist/src/commands/test.js +182 -0
- package/dist/src/commands/token-coverage.d.ts +5 -0
- package/dist/src/commands/token-coverage.js +57 -0
- package/dist/src/commands/token.d.ts +14 -0
- package/dist/src/commands/token.js +121 -0
- package/dist/src/commands/watch.d.ts +9 -0
- package/dist/src/commands/watch.js +112 -0
- package/dist/src/commands/wire.d.ts +13 -0
- package/dist/src/commands/wire.js +149 -0
- package/dist/src/core/ast-utils.d.ts +47 -0
- package/dist/src/core/ast-utils.js +57 -0
- package/dist/src/core/brand-validation.d.ts +7 -0
- package/dist/src/core/brand-validation.js +15 -0
- package/dist/src/core/branding.d.ts +49 -0
- package/dist/src/core/branding.js +229 -0
- package/dist/src/core/browser-wire.d.ts +40 -0
- package/dist/src/core/browser-wire.js +66 -0
- package/dist/src/core/build-prepare.d.ts +25 -0
- package/dist/src/core/build-prepare.js +93 -0
- package/dist/src/core/config-mutate.d.ts +15 -0
- package/dist/src/core/config-mutate.js +51 -0
- package/dist/src/core/config-paths.d.ts +28 -0
- package/dist/src/core/config-paths.js +65 -0
- package/dist/src/core/config-state.d.ts +28 -0
- package/dist/src/core/config-state.js +152 -0
- package/dist/src/core/config-validate.d.ts +11 -0
- package/dist/src/core/config-validate.js +141 -0
- package/dist/src/core/config.d.ts +39 -0
- package/dist/src/core/config.js +70 -0
- package/dist/src/core/file-lock.d.ts +11 -0
- package/dist/src/core/file-lock.js +80 -0
- package/dist/src/core/firefox-archive.d.ts +40 -0
- package/dist/src/core/firefox-archive.js +63 -0
- package/dist/src/core/firefox-cache.d.ts +23 -0
- package/dist/src/core/firefox-cache.js +134 -0
- package/dist/src/core/firefox-download.d.ts +21 -0
- package/dist/src/core/firefox-download.js +129 -0
- package/dist/src/core/firefox-extract.d.ts +21 -0
- package/dist/src/core/firefox-extract.js +53 -0
- package/dist/src/core/firefox.d.ts +34 -0
- package/dist/src/core/firefox.js +78 -0
- package/dist/src/core/furnace-apply-helpers.d.ts +21 -0
- package/dist/src/core/furnace-apply-helpers.js +244 -0
- package/dist/src/core/furnace-apply.d.ts +16 -0
- package/dist/src/core/furnace-apply.js +147 -0
- package/dist/src/core/furnace-config.d.ts +94 -0
- package/dist/src/core/furnace-config.js +372 -0
- package/dist/src/core/furnace-constants.d.ts +4 -0
- package/dist/src/core/furnace-constants.js +6 -0
- package/dist/src/core/furnace-registration-ast.d.ts +24 -0
- package/dist/src/core/furnace-registration-ast.js +218 -0
- package/dist/src/core/furnace-registration-remove.d.ts +14 -0
- package/dist/src/core/furnace-registration-remove.js +89 -0
- package/dist/src/core/furnace-registration-validate.d.ts +20 -0
- package/dist/src/core/furnace-registration-validate.js +40 -0
- package/dist/src/core/furnace-registration.d.ts +29 -0
- package/dist/src/core/furnace-registration.js +96 -0
- package/dist/src/core/furnace-rollback.d.ts +20 -0
- package/dist/src/core/furnace-rollback.js +66 -0
- package/dist/src/core/furnace-scanner.d.ts +40 -0
- package/dist/src/core/furnace-scanner.js +143 -0
- package/dist/src/core/furnace-stories.d.ts +37 -0
- package/dist/src/core/furnace-stories.js +185 -0
- package/dist/src/core/furnace-validate-accessibility.d.ts +6 -0
- package/dist/src/core/furnace-validate-accessibility.js +32 -0
- package/dist/src/core/furnace-validate-checks.d.ts +4 -0
- package/dist/src/core/furnace-validate-checks.js +7 -0
- package/dist/src/core/furnace-validate-compatibility.d.ts +6 -0
- package/dist/src/core/furnace-validate-compatibility.js +57 -0
- package/dist/src/core/furnace-validate-helpers.d.ts +28 -0
- package/dist/src/core/furnace-validate-helpers.js +129 -0
- package/dist/src/core/furnace-validate-registration.d.ts +37 -0
- package/dist/src/core/furnace-validate-registration.js +220 -0
- package/dist/src/core/furnace-validate-structure.d.ts +6 -0
- package/dist/src/core/furnace-validate-structure.js +66 -0
- package/dist/src/core/furnace-validate.d.ts +16 -0
- package/dist/src/core/furnace-validate.js +103 -0
- package/dist/src/core/git-base.d.ts +47 -0
- package/dist/src/core/git-base.js +50 -0
- package/dist/src/core/git-diff.d.ts +63 -0
- package/dist/src/core/git-diff.js +246 -0
- package/dist/src/core/git-file-ops.d.ts +65 -0
- package/dist/src/core/git-file-ops.js +141 -0
- package/dist/src/core/git-status.d.ts +65 -0
- package/dist/src/core/git-status.js +163 -0
- package/dist/src/core/git.d.ts +113 -0
- package/dist/src/core/git.js +363 -0
- package/dist/src/core/license-headers.d.ts +36 -0
- package/dist/src/core/license-headers.js +83 -0
- package/dist/src/core/mach-build-artifacts.d.ts +29 -0
- package/dist/src/core/mach-build-artifacts.js +117 -0
- package/dist/src/core/mach-mozconfig.d.ts +17 -0
- package/dist/src/core/mach-mozconfig.js +50 -0
- package/dist/src/core/mach-python.d.ts +16 -0
- package/dist/src/core/mach-python.js +126 -0
- package/dist/src/core/mach.d.ts +106 -0
- package/dist/src/core/mach.js +166 -0
- package/dist/src/core/manifest-helpers.d.ts +25 -0
- package/dist/src/core/manifest-helpers.js +96 -0
- package/dist/src/core/manifest-register.d.ts +30 -0
- package/dist/src/core/manifest-register.js +65 -0
- package/dist/src/core/manifest-rules.d.ts +39 -0
- package/dist/src/core/manifest-rules.js +151 -0
- package/dist/src/core/manifest-tokenizers.d.ts +34 -0
- package/dist/src/core/manifest-tokenizers.js +84 -0
- package/dist/src/core/parser-fallback.d.ts +36 -0
- package/dist/src/core/parser-fallback.js +43 -0
- package/dist/src/core/patch-apply-fuzz.d.ts +29 -0
- package/dist/src/core/patch-apply-fuzz.js +70 -0
- package/dist/src/core/patch-apply.d.ts +46 -0
- package/dist/src/core/patch-apply.js +235 -0
- package/dist/src/core/patch-export.d.ts +99 -0
- package/dist/src/core/patch-export.js +314 -0
- package/dist/src/core/patch-files.d.ts +11 -0
- package/dist/src/core/patch-files.js +51 -0
- package/dist/src/core/patch-lint.d.ts +72 -0
- package/dist/src/core/patch-lint.js +403 -0
- package/dist/src/core/patch-lock.d.ts +8 -0
- package/dist/src/core/patch-lock.js +29 -0
- package/dist/src/core/patch-manifest-consistency.d.ts +24 -0
- package/dist/src/core/patch-manifest-consistency.js +135 -0
- package/dist/src/core/patch-manifest-io.d.ts +36 -0
- package/dist/src/core/patch-manifest-io.js +77 -0
- package/dist/src/core/patch-manifest-query.d.ts +48 -0
- package/dist/src/core/patch-manifest-query.js +124 -0
- package/dist/src/core/patch-manifest-validate.d.ts +22 -0
- package/dist/src/core/patch-manifest-validate.js +72 -0
- package/dist/src/core/patch-manifest.d.ts +11 -0
- package/dist/src/core/patch-manifest.js +12 -0
- package/dist/src/core/patch-parse.d.ts +43 -0
- package/dist/src/core/patch-parse.js +143 -0
- package/dist/src/core/patch-transform.d.ts +21 -0
- package/dist/src/core/patch-transform.js +138 -0
- package/dist/src/core/rebase-session.d.ts +47 -0
- package/dist/src/core/rebase-session.js +65 -0
- package/dist/src/core/register-browser-content.d.ts +11 -0
- package/dist/src/core/register-browser-content.js +116 -0
- package/dist/src/core/register-module.d.ts +11 -0
- package/dist/src/core/register-module.js +76 -0
- package/dist/src/core/register-shared-css.d.ts +11 -0
- package/dist/src/core/register-shared-css.js +117 -0
- package/dist/src/core/register-test-manifest.d.ts +18 -0
- package/dist/src/core/register-test-manifest.js +99 -0
- package/dist/src/core/state-file.d.ts +4 -0
- package/dist/src/core/state-file.js +25 -0
- package/dist/src/core/token-coverage.d.ts +12 -0
- package/dist/src/core/token-coverage.js +74 -0
- package/dist/src/core/token-manager.d.ts +55 -0
- package/dist/src/core/token-manager.js +387 -0
- package/dist/src/core/wire-destroy.d.ts +21 -0
- package/dist/src/core/wire-destroy.js +103 -0
- package/dist/src/core/wire-dom-fragment.d.ts +23 -0
- package/dist/src/core/wire-dom-fragment.js +129 -0
- package/dist/src/core/wire-init.d.ts +23 -0
- package/dist/src/core/wire-init.js +201 -0
- package/dist/src/core/wire-subscript.d.ts +20 -0
- package/dist/src/core/wire-subscript.js +134 -0
- package/dist/src/core/wire-targets.d.ts +7 -0
- package/dist/src/core/wire-targets.js +9 -0
- package/dist/src/core/wire-utils.d.ts +88 -0
- package/dist/src/core/wire-utils.js +279 -0
- package/dist/src/errors/base.d.ts +60 -0
- package/dist/src/errors/base.js +87 -0
- package/dist/src/errors/build.d.ts +52 -0
- package/dist/src/errors/build.js +114 -0
- package/dist/src/errors/codes.d.ts +29 -0
- package/dist/src/errors/codes.js +30 -0
- package/dist/src/errors/config.d.ts +31 -0
- package/dist/src/errors/config.js +61 -0
- package/dist/src/errors/download.d.ts +42 -0
- package/dist/src/errors/download.js +95 -0
- package/dist/src/errors/furnace.d.ts +10 -0
- package/dist/src/errors/furnace.js +22 -0
- package/dist/src/errors/git.d.ts +41 -0
- package/dist/src/errors/git.js +99 -0
- package/dist/src/errors/patch.d.ts +10 -0
- package/dist/src/errors/patch.js +26 -0
- package/dist/src/errors/rebase.d.ts +20 -0
- package/dist/src/errors/rebase.js +30 -0
- package/dist/src/index.d.ts +21 -0
- package/dist/src/index.js +21 -0
- package/dist/src/types/cli.d.ts +14 -0
- package/dist/src/types/cli.js +2 -0
- package/dist/src/types/commands/index.d.ts +6 -0
- package/dist/src/types/commands/index.js +6 -0
- package/dist/src/types/commands/options.d.ts +239 -0
- package/dist/src/types/commands/options.js +6 -0
- package/dist/src/types/commands/patches.d.ts +89 -0
- package/dist/src/types/commands/patches.js +6 -0
- package/dist/src/types/commands/project.d.ts +71 -0
- package/dist/src/types/commands/project.js +6 -0
- package/dist/src/types/config.d.ts +101 -0
- package/dist/src/types/config.js +2 -0
- package/dist/src/types/furnace.d.ts +158 -0
- package/dist/src/types/furnace.js +2 -0
- package/dist/src/types/index.d.ts +6 -0
- package/dist/src/types/index.js +6 -0
- package/dist/src/utils/errors.d.ts +2 -0
- package/dist/src/utils/errors.js +15 -0
- package/dist/src/utils/fs.d.ts +72 -0
- package/dist/src/utils/fs.js +179 -0
- package/dist/src/utils/logger.d.ts +58 -0
- package/dist/src/utils/logger.js +120 -0
- package/dist/src/utils/options.d.ts +8 -0
- package/dist/src/utils/options.js +16 -0
- package/dist/src/utils/package-root.d.ts +10 -0
- package/dist/src/utils/package-root.js +53 -0
- package/dist/src/utils/parse.d.ts +110 -0
- package/dist/src/utils/parse.js +200 -0
- package/dist/src/utils/paths.d.ts +10 -0
- package/dist/src/utils/paths.js +43 -0
- package/dist/src/utils/platform.d.ts +38 -0
- package/dist/src/utils/platform.js +56 -0
- package/dist/src/utils/process.d.ts +80 -0
- package/dist/src/utils/process.js +188 -0
- package/dist/src/utils/regex.d.ts +24 -0
- package/dist/src/utils/regex.js +40 -0
- package/dist/src/utils/validation.d.ts +133 -0
- package/dist/src/utils/validation.js +250 -0
- package/package.json +106 -0
- package/templates/configs/common.mozconfig +24 -0
- package/templates/configs/darwin.mozconfig +10 -0
- package/templates/configs/linux.mozconfig +12 -0
- package/templates/configs/win32.mozconfig +14 -0
- package/templates/licenses/0BSD.md +14 -0
- package/templates/licenses/EUPL-1.2.md +294 -0
- package/templates/licenses/GPL-2.0-or-later.md +339 -0
- package/templates/licenses/MPL-2.0.md +383 -0
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { FireForgeError } from '../errors/base.js';
|
|
4
|
+
import { ExitCode } from '../errors/codes.js';
|
|
5
|
+
import { copyDir, pathExists, readText, writeText } from '../utils/fs.js';
|
|
6
|
+
import { warn } from '../utils/logger.js';
|
|
7
|
+
/**
|
|
8
|
+
* Error thrown when branding operations fail.
|
|
9
|
+
*/
|
|
10
|
+
export class BrandingError extends FireForgeError {
|
|
11
|
+
code = ExitCode.PATCH_ERROR;
|
|
12
|
+
get userMessage() {
|
|
13
|
+
return `Branding Error: ${this.message}\n\nBranding is required to set MOZ_APP_VENDOR, MOZ_MACBUNDLE_ID, and other Firefox identity values.`;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Sets up the custom branding directory for the browser.
|
|
18
|
+
*
|
|
19
|
+
* This creates a branding directory based on Firefox's unofficial branding,
|
|
20
|
+
* with customized values for:
|
|
21
|
+
* - configure.sh: MOZ_APP_DISPLAYNAME, MOZ_MACBUNDLE_ID
|
|
22
|
+
* - brand.properties: brandShorterName, brandShortName, brandFullName
|
|
23
|
+
* - brand.ftl: -brand-shorter-name, -brand-short-name, etc.
|
|
24
|
+
*
|
|
25
|
+
* @param engineDir - Path to the engine directory
|
|
26
|
+
* @param config - Branding configuration
|
|
27
|
+
*/
|
|
28
|
+
export async function setupBranding(engineDir, config) {
|
|
29
|
+
const brandingDir = join(engineDir, 'browser', 'branding', config.binaryName);
|
|
30
|
+
const unofficialDir = join(engineDir, 'browser', 'branding', 'unofficial');
|
|
31
|
+
// Check if unofficial branding exists as our base
|
|
32
|
+
if (!(await pathExists(unofficialDir))) {
|
|
33
|
+
throw new BrandingError(`Unofficial branding directory not found at ${unofficialDir}`);
|
|
34
|
+
}
|
|
35
|
+
// Copy unofficial branding as base (if our branding doesn't exist yet)
|
|
36
|
+
if (!(await pathExists(brandingDir))) {
|
|
37
|
+
await copyDir(unofficialDir, brandingDir);
|
|
38
|
+
}
|
|
39
|
+
// Create/update configure.sh with custom values
|
|
40
|
+
await createConfigureScript(brandingDir, config);
|
|
41
|
+
// Update localization files
|
|
42
|
+
await updateBrandProperties(brandingDir, config);
|
|
43
|
+
await updateBrandFtl(brandingDir, config);
|
|
44
|
+
// Patch moz.configure for MOZ_APP_VENDOR
|
|
45
|
+
await patchMozConfigure(engineDir, config);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Creates the branding configure.sh script.
|
|
49
|
+
*/
|
|
50
|
+
async function createConfigureScript(brandingDir, config) {
|
|
51
|
+
const configureShPath = join(brandingDir, 'configure.sh');
|
|
52
|
+
await writeText(configureShPath, buildConfigureScriptContent(config));
|
|
53
|
+
}
|
|
54
|
+
function buildConfigureScriptContent(config) {
|
|
55
|
+
return `# This Source Code Form is subject to the terms of the Mozilla Public
|
|
56
|
+
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
57
|
+
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
58
|
+
|
|
59
|
+
MOZ_APP_DISPLAYNAME="${escapeShellValue(config.name)}"
|
|
60
|
+
MOZ_MACBUNDLE_ID="${escapeShellValue(config.appId)}"
|
|
61
|
+
`;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Updates the brand.properties localization file.
|
|
65
|
+
*/
|
|
66
|
+
async function updateBrandProperties(brandingDir, config) {
|
|
67
|
+
const propsPath = join(brandingDir, 'locales', 'en-US', 'brand.properties');
|
|
68
|
+
if (!(await pathExists(propsPath))) {
|
|
69
|
+
warn('brand.properties not found in branding directory — browser will use default strings');
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
await writeText(propsPath, buildBrandPropertiesContent(config));
|
|
73
|
+
}
|
|
74
|
+
function buildBrandPropertiesContent(config) {
|
|
75
|
+
return `# This Source Code Form is subject to the terms of the Mozilla Public
|
|
76
|
+
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
77
|
+
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
78
|
+
|
|
79
|
+
brandShorterName=${escapePropertiesValue(config.name)}
|
|
80
|
+
brandShortName=${escapePropertiesValue(config.name)}
|
|
81
|
+
brandFullName=${escapePropertiesValue(config.name)}
|
|
82
|
+
`;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Updates the brand.ftl localization file.
|
|
86
|
+
*/
|
|
87
|
+
async function updateBrandFtl(brandingDir, config) {
|
|
88
|
+
const ftlPath = join(brandingDir, 'locales', 'en-US', 'brand.ftl');
|
|
89
|
+
if (!(await pathExists(ftlPath))) {
|
|
90
|
+
warn('brand.ftl not found in branding directory — browser will use default strings');
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
await writeText(ftlPath, buildBrandFtlContent(config));
|
|
94
|
+
}
|
|
95
|
+
function buildBrandFtlContent(config) {
|
|
96
|
+
return `# This Source Code Form is subject to the terms of the Mozilla Public
|
|
97
|
+
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
98
|
+
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
99
|
+
|
|
100
|
+
## Brand names
|
|
101
|
+
##
|
|
102
|
+
## These brand names can be used in messages.
|
|
103
|
+
|
|
104
|
+
-brand-shorter-name = ${escapeFtlValue(config.name)}
|
|
105
|
+
-brand-short-name = ${escapeFtlValue(config.name)}
|
|
106
|
+
-brand-shortcut-name = ${escapeFtlValue(config.name)}
|
|
107
|
+
-brand-full-name = ${escapeFtlValue(config.name)}
|
|
108
|
+
-brand-product-name = ${escapeFtlValue(config.name)}
|
|
109
|
+
-vendor-short-name = ${escapeFtlValue(config.vendor)}
|
|
110
|
+
trademarkInfo = { " " }
|
|
111
|
+
`;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Patches browser/moz.configure to set custom vendor.
|
|
115
|
+
*
|
|
116
|
+
* Mozilla's build system requires MOZ_APP_VENDOR to be set via imply_option
|
|
117
|
+
* in moz.configure, not through mozconfig.
|
|
118
|
+
*/
|
|
119
|
+
async function patchMozConfigure(engineDir, config) {
|
|
120
|
+
const mozConfigurePath = join(engineDir, 'browser', 'moz.configure');
|
|
121
|
+
if (!(await pathExists(mozConfigurePath))) {
|
|
122
|
+
throw new BrandingError(`browser/moz.configure not found at ${mozConfigurePath}`);
|
|
123
|
+
}
|
|
124
|
+
let content = await readText(mozConfigurePath);
|
|
125
|
+
// Replace MOZ_APP_VENDOR imply_option
|
|
126
|
+
const vendorRegex = /imply_option\("MOZ_APP_VENDOR",\s*"[^"]*"\)/;
|
|
127
|
+
if (!vendorRegex.test(content)) {
|
|
128
|
+
throw new BrandingError('Could not find MOZ_APP_VENDOR imply_option in browser/moz.configure');
|
|
129
|
+
}
|
|
130
|
+
content = content.replace(vendorRegex, buildMozConfigureVendorLine(config));
|
|
131
|
+
await writeText(mozConfigurePath, content);
|
|
132
|
+
}
|
|
133
|
+
function buildMozConfigureVendorLine(config) {
|
|
134
|
+
return `imply_option("MOZ_APP_VENDOR", "${escapeString(config.vendor)}")`;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Escapes a string for use in Python/configure file.
|
|
138
|
+
*/
|
|
139
|
+
function escapeString(value) {
|
|
140
|
+
return value
|
|
141
|
+
.replace(/\\/g, '\\\\')
|
|
142
|
+
.replace(/"/g, '\\"')
|
|
143
|
+
.replace(/\n/g, '\\n')
|
|
144
|
+
.replace(/\r/g, '\\r')
|
|
145
|
+
.replace(/\t/g, '\\t');
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Escapes a string for use inside a shell double-quoted context.
|
|
149
|
+
* Prevents command injection via $, backticks, !, and escape sequences.
|
|
150
|
+
*/
|
|
151
|
+
function escapeShellValue(value) {
|
|
152
|
+
return value
|
|
153
|
+
.replace(/\\/g, '\\\\')
|
|
154
|
+
.replace(/"/g, '\\"')
|
|
155
|
+
.replace(/\$/g, '\\$')
|
|
156
|
+
.replace(/`/g, '\\`')
|
|
157
|
+
.replace(/!/g, '\\!');
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Escapes a string for use in .properties file values.
|
|
161
|
+
* Prevents key/value injection via = and : delimiters.
|
|
162
|
+
*/
|
|
163
|
+
function escapePropertiesValue(value) {
|
|
164
|
+
return value
|
|
165
|
+
.replace(/\\/g, '\\\\')
|
|
166
|
+
.replace(/\n/g, '\\n')
|
|
167
|
+
.replace(/\r/g, '\\r')
|
|
168
|
+
.replace(/\t/g, '\\t');
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Escapes a string for use in Fluent (.ftl) file values.
|
|
172
|
+
* Prevents placeables injection via { and }.
|
|
173
|
+
*/
|
|
174
|
+
function escapeFtlValue(value) {
|
|
175
|
+
return value.replace(/\\/g, '\\\\').replace(/\{/g, '\\{').replace(/\}/g, '\\}');
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Checks if branding has been set up for the given configuration.
|
|
179
|
+
*
|
|
180
|
+
* @param engineDir - Path to the engine directory
|
|
181
|
+
* @param config - Branding configuration to check for
|
|
182
|
+
* @returns true if branding is already set up
|
|
183
|
+
*/
|
|
184
|
+
export async function isBrandingSetup(engineDir, config) {
|
|
185
|
+
const brandingDir = join(engineDir, 'browser', 'branding', config.binaryName);
|
|
186
|
+
const configureShPath = join(brandingDir, 'configure.sh');
|
|
187
|
+
const propsPath = join(brandingDir, 'locales', 'en-US', 'brand.properties');
|
|
188
|
+
const ftlPath = join(brandingDir, 'locales', 'en-US', 'brand.ftl');
|
|
189
|
+
const mozConfigurePath = join(engineDir, 'browser', 'moz.configure');
|
|
190
|
+
if (!(await pathExists(configureShPath))) {
|
|
191
|
+
return false;
|
|
192
|
+
}
|
|
193
|
+
const configureContent = await readText(configureShPath);
|
|
194
|
+
if (configureContent !== buildConfigureScriptContent(config)) {
|
|
195
|
+
return false;
|
|
196
|
+
}
|
|
197
|
+
if (await pathExists(propsPath)) {
|
|
198
|
+
const propsContent = await readText(propsPath);
|
|
199
|
+
if (propsContent !== buildBrandPropertiesContent(config)) {
|
|
200
|
+
return false;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
if (await pathExists(ftlPath)) {
|
|
204
|
+
const ftlContent = await readText(ftlPath);
|
|
205
|
+
if (ftlContent !== buildBrandFtlContent(config)) {
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
if (!(await pathExists(mozConfigurePath))) {
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
const mozConfigureContent = await readText(mozConfigurePath);
|
|
213
|
+
return mozConfigureContent.includes(buildMozConfigureVendorLine(config));
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Checks whether a file path belongs to the tool-managed branding directory.
|
|
217
|
+
* @param file - File path (relative to engine root)
|
|
218
|
+
* @param binaryName - The configured binary name (used as branding directory name)
|
|
219
|
+
* @returns true if the path is managed by branding tooling
|
|
220
|
+
*/
|
|
221
|
+
export function isBrandingManagedPath(file, binaryName) {
|
|
222
|
+
const normalized = file.replace(/\\/g, '/');
|
|
223
|
+
const brandingRoot = `browser/branding/${binaryName}`;
|
|
224
|
+
return (normalized === 'browser/moz.configure' ||
|
|
225
|
+
normalized === brandingRoot ||
|
|
226
|
+
normalized === `${brandingRoot}/` ||
|
|
227
|
+
normalized.startsWith(`${brandingRoot}/`));
|
|
228
|
+
}
|
|
229
|
+
//# sourceMappingURL=branding.js.map
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { RegisterResult } from './manifest-register.js';
|
|
2
|
+
export declare const DEFAULT_BROWSER_SUBSCRIPT_DIR = "browser/base/content";
|
|
3
|
+
/**
|
|
4
|
+
* Result of a wire operation.
|
|
5
|
+
*/
|
|
6
|
+
export interface WireResult {
|
|
7
|
+
/** Whether the subscript was added to browser-main.js */
|
|
8
|
+
subscriptAdded: boolean;
|
|
9
|
+
/** Whether the init expression was added to browser-init.js */
|
|
10
|
+
initAdded: boolean;
|
|
11
|
+
/** Whether the destroy expression was added to browser-init.js */
|
|
12
|
+
destroyAdded: boolean;
|
|
13
|
+
/** Whether the DOM fragment was inserted into browser.xhtml */
|
|
14
|
+
domInserted: boolean;
|
|
15
|
+
/** Result of jar.mn registration */
|
|
16
|
+
jarMnResult: RegisterResult;
|
|
17
|
+
}
|
|
18
|
+
export interface WireOptions {
|
|
19
|
+
/** Init expression to add to browser-init.js onLoad() */
|
|
20
|
+
init?: string | undefined;
|
|
21
|
+
/** Destroy expression to add to browser-init.js onUnload() */
|
|
22
|
+
destroy?: string | undefined;
|
|
23
|
+
/** Path to `.inc.xhtml` file relative to engine root */
|
|
24
|
+
domFilePath?: string | undefined;
|
|
25
|
+
/** Dry run — don't write any files */
|
|
26
|
+
dryRun?: boolean | undefined;
|
|
27
|
+
/** Insert init block after the block containing this name */
|
|
28
|
+
after?: string | undefined;
|
|
29
|
+
/** Subscript directory relative to engine/ (default: "browser/base/content") */
|
|
30
|
+
subscriptDir?: string | undefined;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Wires a chrome subscript into the browser.
|
|
34
|
+
*
|
|
35
|
+
* @param root - Project root directory
|
|
36
|
+
* @param name - Subscript name (without .js extension)
|
|
37
|
+
* @param options - Wire options
|
|
38
|
+
* @returns Wire result
|
|
39
|
+
*/
|
|
40
|
+
export declare function wireSubscript(root: string, name: string, options?: WireOptions): Promise<WireResult>;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
+
import { join, relative } from 'node:path';
|
|
3
|
+
import { toRootRelativePath } from '../utils/paths.js';
|
|
4
|
+
import { getProjectPaths } from './config.js';
|
|
5
|
+
import { registerBrowserContent } from './manifest-register.js';
|
|
6
|
+
import { addDestroyToBrowserInit, addDomFragment, addInitToBrowserInit, addSubscriptToBrowserMain, } from './wire-targets.js';
|
|
7
|
+
export const DEFAULT_BROWSER_SUBSCRIPT_DIR = 'browser/base/content';
|
|
8
|
+
const BROWSER_BASE_DIR = 'browser/base';
|
|
9
|
+
/**
|
|
10
|
+
* Wires a chrome subscript into the browser.
|
|
11
|
+
*
|
|
12
|
+
* @param root - Project root directory
|
|
13
|
+
* @param name - Subscript name (without .js extension)
|
|
14
|
+
* @param options - Wire options
|
|
15
|
+
* @returns Wire result
|
|
16
|
+
*/
|
|
17
|
+
export async function wireSubscript(root, name, options = {}) {
|
|
18
|
+
const { engine: engineDir } = getProjectPaths(root);
|
|
19
|
+
const subscriptDir = toRootRelativePath(engineDir, options.subscriptDir ?? DEFAULT_BROWSER_SUBSCRIPT_DIR);
|
|
20
|
+
// Compute jar.mn source path relative to browser/base/
|
|
21
|
+
let jarMnSourcePath;
|
|
22
|
+
if (subscriptDir !== DEFAULT_BROWSER_SUBSCRIPT_DIR) {
|
|
23
|
+
const relPath = relative(join(engineDir, BROWSER_BASE_DIR), join(engineDir, subscriptDir)).replace(/\\/g, '/');
|
|
24
|
+
jarMnSourcePath = `${relPath}/${name}.js`;
|
|
25
|
+
}
|
|
26
|
+
if (options.dryRun) {
|
|
27
|
+
return {
|
|
28
|
+
subscriptAdded: true,
|
|
29
|
+
initAdded: !!options.init,
|
|
30
|
+
destroyAdded: !!options.destroy,
|
|
31
|
+
domInserted: !!options.domFilePath,
|
|
32
|
+
jarMnResult: {
|
|
33
|
+
manifest: 'browser/base/jar.mn',
|
|
34
|
+
entry: `[dry-run] Would register content/browser/${name}.js`,
|
|
35
|
+
skipped: false,
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
// 1. Add subscript to browser-main.js
|
|
40
|
+
const subscriptAdded = await addSubscriptToBrowserMain(engineDir, name);
|
|
41
|
+
// 2. Add init expression to browser-init.js (if provided)
|
|
42
|
+
let initAdded = false;
|
|
43
|
+
if (options.init) {
|
|
44
|
+
initAdded = await addInitToBrowserInit(engineDir, options.init, options.after);
|
|
45
|
+
}
|
|
46
|
+
// 3. Add destroy expression to browser-init.js onUnload() (if provided)
|
|
47
|
+
let destroyAdded = false;
|
|
48
|
+
if (options.destroy) {
|
|
49
|
+
destroyAdded = await addDestroyToBrowserInit(engineDir, options.destroy);
|
|
50
|
+
}
|
|
51
|
+
// 4. Add #include directive to browser.xhtml (if provided)
|
|
52
|
+
let domInserted = false;
|
|
53
|
+
if (options.domFilePath) {
|
|
54
|
+
domInserted = await addDomFragment(engineDir, toRootRelativePath(engineDir, options.domFilePath));
|
|
55
|
+
}
|
|
56
|
+
// 5. Register in jar.mn
|
|
57
|
+
const jarMnResult = await registerBrowserContent(engineDir, `${name}.js`, undefined, jarMnSourcePath);
|
|
58
|
+
return {
|
|
59
|
+
subscriptAdded,
|
|
60
|
+
initAdded,
|
|
61
|
+
destroyAdded,
|
|
62
|
+
domInserted,
|
|
63
|
+
jarMnResult,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=browser-wire.js.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared pre-flight logic for build and package commands:
|
|
3
|
+
* story cleanup, branding setup, Furnace component application, and mozconfig generation.
|
|
4
|
+
*/
|
|
5
|
+
import type { FireForgeConfig, ProjectPaths } from '../types/config.js';
|
|
6
|
+
/**
|
|
7
|
+
* Result of the build preparation phase.
|
|
8
|
+
*/
|
|
9
|
+
export interface BuildPreparation {
|
|
10
|
+
/** Number of Furnace components applied (0 if none or no furnace.json) */
|
|
11
|
+
furnaceApplied: number;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Runs the shared pre-flight steps for build and package commands:
|
|
15
|
+
* 1. Cleans Furnace stories from engine (prevents leaking into production)
|
|
16
|
+
* 2. Sets up branding directory if not already done
|
|
17
|
+
* 3. Applies Furnace components if furnace.json exists
|
|
18
|
+
* 4. Generates mozconfig
|
|
19
|
+
*
|
|
20
|
+
* @param projectRoot - Root directory of the project
|
|
21
|
+
* @param paths - Resolved project paths
|
|
22
|
+
* @param config - Loaded FireForge configuration
|
|
23
|
+
* @returns Preparation results
|
|
24
|
+
*/
|
|
25
|
+
export declare function prepareBuildEnvironment(projectRoot: string, paths: ProjectPaths, config: FireForgeConfig): Promise<BuildPreparation>;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
+
/**
|
|
3
|
+
* Shared pre-flight logic for build and package commands:
|
|
4
|
+
* story cleanup, branding setup, Furnace component application, and mozconfig generation.
|
|
5
|
+
*/
|
|
6
|
+
import { spinner, warn } from '../utils/logger.js';
|
|
7
|
+
import { isBrandingSetup, setupBranding } from './branding.js';
|
|
8
|
+
import { applyAllComponents } from './furnace-apply.js';
|
|
9
|
+
import { furnaceConfigExists, loadFurnaceConfig } from './furnace-config.js';
|
|
10
|
+
import { cleanStories } from './furnace-stories.js';
|
|
11
|
+
import { generateMozconfig } from './mach.js';
|
|
12
|
+
/**
|
|
13
|
+
* Runs the shared pre-flight steps for build and package commands:
|
|
14
|
+
* 1. Cleans Furnace stories from engine (prevents leaking into production)
|
|
15
|
+
* 2. Sets up branding directory if not already done
|
|
16
|
+
* 3. Applies Furnace components if furnace.json exists
|
|
17
|
+
* 4. Generates mozconfig
|
|
18
|
+
*
|
|
19
|
+
* @param projectRoot - Root directory of the project
|
|
20
|
+
* @param paths - Resolved project paths
|
|
21
|
+
* @param config - Loaded FireForge configuration
|
|
22
|
+
* @returns Preparation results
|
|
23
|
+
*/
|
|
24
|
+
export async function prepareBuildEnvironment(projectRoot, paths, config) {
|
|
25
|
+
// Clean stories before build to ensure they don't leak into production binary
|
|
26
|
+
await cleanStories(paths.engine);
|
|
27
|
+
// Set up custom branding directory and patch moz.configure
|
|
28
|
+
const brandingConfig = {
|
|
29
|
+
name: config.name,
|
|
30
|
+
vendor: config.vendor,
|
|
31
|
+
appId: config.appId,
|
|
32
|
+
binaryName: config.binaryName,
|
|
33
|
+
};
|
|
34
|
+
if (!(await isBrandingSetup(paths.engine, brandingConfig))) {
|
|
35
|
+
const brandingSpinner = spinner('Setting up branding...');
|
|
36
|
+
try {
|
|
37
|
+
await setupBranding(paths.engine, brandingConfig);
|
|
38
|
+
brandingSpinner.stop('Branding configured');
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
brandingSpinner.error('Failed to set up branding');
|
|
42
|
+
throw error;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
// Apply Furnace components if furnace.json exists
|
|
46
|
+
let furnaceApplied = 0;
|
|
47
|
+
if (await furnaceConfigExists(projectRoot)) {
|
|
48
|
+
const furnaceConfig = await loadFurnaceConfig(projectRoot);
|
|
49
|
+
const hasComponents = Object.keys(furnaceConfig.overrides).length > 0 ||
|
|
50
|
+
Object.keys(furnaceConfig.custom).length > 0;
|
|
51
|
+
if (hasComponents) {
|
|
52
|
+
const furnaceSpinner = spinner('Applying Furnace components...');
|
|
53
|
+
try {
|
|
54
|
+
const result = await applyAllComponents(projectRoot);
|
|
55
|
+
furnaceApplied = result.applied.length;
|
|
56
|
+
if (furnaceApplied > 0) {
|
|
57
|
+
furnaceSpinner.stop(`Applied ${furnaceApplied} component${furnaceApplied === 1 ? '' : 's'}`);
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
furnaceSpinner.stop('Components up to date');
|
|
61
|
+
}
|
|
62
|
+
if (result.errors.length > 0) {
|
|
63
|
+
for (const err of result.errors) {
|
|
64
|
+
warn(`Furnace: ${err.name} — ${err.error}`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
for (const applied of result.applied) {
|
|
68
|
+
if (applied.stepErrors && applied.stepErrors.length > 0) {
|
|
69
|
+
for (const stepErr of applied.stepErrors) {
|
|
70
|
+
warn(`Furnace: ${applied.name} [${stepErr.step}] ${stepErr.error}`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
furnaceSpinner.error('Failed to apply Furnace components');
|
|
77
|
+
throw error;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
// Generate mozconfig
|
|
82
|
+
const mozconfigSpinner = spinner('Generating mozconfig...');
|
|
83
|
+
try {
|
|
84
|
+
await generateMozconfig(paths.configs, paths.engine, config);
|
|
85
|
+
mozconfigSpinner.stop('mozconfig generated');
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
mozconfigSpinner.error('Failed to generate mozconfig');
|
|
89
|
+
throw error;
|
|
90
|
+
}
|
|
91
|
+
return { furnaceApplied };
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=build-prepare.js.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Immutable config mutation with dot-path keys.
|
|
3
|
+
*/
|
|
4
|
+
import type { FireForgeConfig } from '../types/config.js';
|
|
5
|
+
/**
|
|
6
|
+
* Creates a mutated copy of a config with a nested key set to a new value,
|
|
7
|
+
* optionally re-validated.
|
|
8
|
+
* @param config - Original config
|
|
9
|
+
* @param key - Dot-separated config path
|
|
10
|
+
* @param value - New value
|
|
11
|
+
* @param skipValidation - If true, skip re-validation (for --force)
|
|
12
|
+
* @returns The mutated config
|
|
13
|
+
*/
|
|
14
|
+
export declare function mutateConfig(config: FireForgeConfig, key: string, value: unknown, skipValidation?: false): FireForgeConfig;
|
|
15
|
+
export declare function mutateConfig(config: FireForgeConfig, key: string, value: unknown, skipValidation: true): Record<string, unknown>;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
+
/**
|
|
3
|
+
* Immutable config mutation with dot-path keys.
|
|
4
|
+
*/
|
|
5
|
+
import { ConfigError } from '../errors/config.js';
|
|
6
|
+
import { toError } from '../utils/errors.js';
|
|
7
|
+
import { verbose } from '../utils/logger.js';
|
|
8
|
+
import { isObject } from '../utils/validation.js';
|
|
9
|
+
import { validateConfig } from './config-validate.js';
|
|
10
|
+
function cloneConfigDocument(config) {
|
|
11
|
+
const cloned = structuredClone(config);
|
|
12
|
+
if (!isObject(cloned)) {
|
|
13
|
+
throw new ConfigError('Config clone unexpectedly produced a non-object value');
|
|
14
|
+
}
|
|
15
|
+
return cloned;
|
|
16
|
+
}
|
|
17
|
+
function getOrCreateChildRecord(parent, key) {
|
|
18
|
+
const existing = parent[key];
|
|
19
|
+
if (isObject(existing)) {
|
|
20
|
+
return existing;
|
|
21
|
+
}
|
|
22
|
+
const child = {};
|
|
23
|
+
parent[key] = child;
|
|
24
|
+
return child;
|
|
25
|
+
}
|
|
26
|
+
export function mutateConfig(config, key, value, skipValidation = false) {
|
|
27
|
+
const raw = cloneConfigDocument(config);
|
|
28
|
+
const parts = key.split('.');
|
|
29
|
+
let current = raw;
|
|
30
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
31
|
+
const part = parts[i];
|
|
32
|
+
if (part === undefined)
|
|
33
|
+
continue;
|
|
34
|
+
current = getOrCreateChildRecord(current, part);
|
|
35
|
+
}
|
|
36
|
+
const lastPart = parts[parts.length - 1];
|
|
37
|
+
if (lastPart !== undefined) {
|
|
38
|
+
current[lastPart] = value;
|
|
39
|
+
}
|
|
40
|
+
if (!skipValidation) {
|
|
41
|
+
return validateConfig(raw);
|
|
42
|
+
}
|
|
43
|
+
try {
|
|
44
|
+
validateConfig(raw);
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
verbose(`Skipping config revalidation for forced mutation on "${key}": ${toError(error).message}`);
|
|
48
|
+
}
|
|
49
|
+
return raw;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=config-mutate.js.map
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project path derivation from a root directory.
|
|
3
|
+
*/
|
|
4
|
+
import type { ProjectPaths } from '../types/config.js';
|
|
5
|
+
/** Name of the configuration file */
|
|
6
|
+
export declare const CONFIG_FILENAME = "fireforge.json";
|
|
7
|
+
/** Name of the fireforge data directory */
|
|
8
|
+
export declare const FIREFORGE_DIR = ".fireforge";
|
|
9
|
+
/** Name of the state file */
|
|
10
|
+
export declare const STATE_FILENAME = "state.json";
|
|
11
|
+
/** Name of the engine directory */
|
|
12
|
+
export declare const ENGINE_DIR = "engine";
|
|
13
|
+
/** Name of the patches directory */
|
|
14
|
+
export declare const PATCHES_DIR = "patches";
|
|
15
|
+
/** Name of the configs directory */
|
|
16
|
+
export declare const CONFIGS_DIR = "configs";
|
|
17
|
+
/** Name of the source directory */
|
|
18
|
+
export declare const SRC_DIR = "src";
|
|
19
|
+
/** Supported top-level fireforge.json keys backed by the current schema. */
|
|
20
|
+
export declare const SUPPORTED_CONFIG_ROOT_KEYS: readonly ["name", "vendor", "appId", "binaryName", "firefox", "build", "license", "wire"];
|
|
21
|
+
/** Supported config paths that can be read or set without --force. */
|
|
22
|
+
export declare const SUPPORTED_CONFIG_PATHS: readonly ["name", "vendor", "appId", "binaryName", "license", "firefox", "firefox.version", "firefox.product", "build", "build.jobs", "wire", "wire.subscriptDir"];
|
|
23
|
+
/**
|
|
24
|
+
* Gets all project paths based on a root directory.
|
|
25
|
+
* @param root - Root directory of the project
|
|
26
|
+
* @returns All project paths
|
|
27
|
+
*/
|
|
28
|
+
export declare function getProjectPaths(root: string): ProjectPaths;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
+
/**
|
|
3
|
+
* Project path derivation from a root directory.
|
|
4
|
+
*/
|
|
5
|
+
import { join } from 'node:path';
|
|
6
|
+
/** Name of the configuration file */
|
|
7
|
+
export const CONFIG_FILENAME = 'fireforge.json';
|
|
8
|
+
/** Name of the fireforge data directory */
|
|
9
|
+
export const FIREFORGE_DIR = '.fireforge';
|
|
10
|
+
/** Name of the state file */
|
|
11
|
+
export const STATE_FILENAME = 'state.json';
|
|
12
|
+
/** Name of the engine directory */
|
|
13
|
+
export const ENGINE_DIR = 'engine';
|
|
14
|
+
/** Name of the patches directory */
|
|
15
|
+
export const PATCHES_DIR = 'patches';
|
|
16
|
+
/** Name of the configs directory */
|
|
17
|
+
export const CONFIGS_DIR = 'configs';
|
|
18
|
+
/** Name of the source directory */
|
|
19
|
+
export const SRC_DIR = 'src';
|
|
20
|
+
/** Supported top-level fireforge.json keys backed by the current schema. */
|
|
21
|
+
export const SUPPORTED_CONFIG_ROOT_KEYS = [
|
|
22
|
+
'name',
|
|
23
|
+
'vendor',
|
|
24
|
+
'appId',
|
|
25
|
+
'binaryName',
|
|
26
|
+
'firefox',
|
|
27
|
+
'build',
|
|
28
|
+
'license',
|
|
29
|
+
'wire',
|
|
30
|
+
];
|
|
31
|
+
/** Supported config paths that can be read or set without --force. */
|
|
32
|
+
export const SUPPORTED_CONFIG_PATHS = [
|
|
33
|
+
'name',
|
|
34
|
+
'vendor',
|
|
35
|
+
'appId',
|
|
36
|
+
'binaryName',
|
|
37
|
+
'license',
|
|
38
|
+
'firefox',
|
|
39
|
+
'firefox.version',
|
|
40
|
+
'firefox.product',
|
|
41
|
+
'build',
|
|
42
|
+
'build.jobs',
|
|
43
|
+
'wire',
|
|
44
|
+
'wire.subscriptDir',
|
|
45
|
+
];
|
|
46
|
+
/**
|
|
47
|
+
* Gets all project paths based on a root directory.
|
|
48
|
+
* @param root - Root directory of the project
|
|
49
|
+
* @returns All project paths
|
|
50
|
+
*/
|
|
51
|
+
export function getProjectPaths(root) {
|
|
52
|
+
const fireforgeDir = join(root, FIREFORGE_DIR);
|
|
53
|
+
return {
|
|
54
|
+
root,
|
|
55
|
+
config: join(root, CONFIG_FILENAME),
|
|
56
|
+
fireforgeDir,
|
|
57
|
+
state: join(fireforgeDir, STATE_FILENAME),
|
|
58
|
+
engine: join(root, ENGINE_DIR),
|
|
59
|
+
patches: join(root, PATCHES_DIR),
|
|
60
|
+
configs: join(root, CONFIGS_DIR),
|
|
61
|
+
src: join(root, SRC_DIR),
|
|
62
|
+
componentsDir: join(root, 'components'),
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=config-paths.js.map
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project state file management (.fireforge/state.json).
|
|
3
|
+
*/
|
|
4
|
+
import type { FireForgeState } from '../types/config.js';
|
|
5
|
+
/**
|
|
6
|
+
* Validates a parsed project state object and returns a typed FireForgeState.
|
|
7
|
+
* @param data - Parsed JSON state data
|
|
8
|
+
* @returns Validated FireForgeState
|
|
9
|
+
*/
|
|
10
|
+
export declare function validateFireForgeState(data: unknown): FireForgeState;
|
|
11
|
+
/**
|
|
12
|
+
* Loads the fireforge state, or returns defaults if it doesn't exist.
|
|
13
|
+
* @param root - Root directory of the project
|
|
14
|
+
* @returns FireForge state
|
|
15
|
+
*/
|
|
16
|
+
export declare function loadState(root: string): Promise<FireForgeState>;
|
|
17
|
+
/**
|
|
18
|
+
* Saves the fireforge state.
|
|
19
|
+
* @param root - Root directory of the project
|
|
20
|
+
* @param state - State to save
|
|
21
|
+
*/
|
|
22
|
+
export declare function saveState(root: string, state: FireForgeState): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Updates specific fields in the fireforge state.
|
|
25
|
+
* @param root - Root directory of the project
|
|
26
|
+
* @param updates - Fields to update, or a transactional updater function
|
|
27
|
+
*/
|
|
28
|
+
export declare function updateState(root: string, updates: Partial<FireForgeState> | ((current: FireForgeState) => FireForgeState)): Promise<void>;
|