@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,200 @@
|
|
|
1
|
+
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
+
/**
|
|
3
|
+
* Lightweight runtime object parsing and field extraction helpers.
|
|
4
|
+
*
|
|
5
|
+
* Reduces repetitive "validate unknown → cast" boilerplate across
|
|
6
|
+
* config validation, manifest parsing, and metadata validation.
|
|
7
|
+
*/
|
|
8
|
+
import { isArray, isNumber, isObject, isString } from './validation.js';
|
|
9
|
+
/**
|
|
10
|
+
* A parsed record wrapper that provides typed field extraction
|
|
11
|
+
* with clear error messages. Construct via {@link parseObject}.
|
|
12
|
+
*/
|
|
13
|
+
export class ParsedRecord {
|
|
14
|
+
#data;
|
|
15
|
+
#label;
|
|
16
|
+
constructor(data, label) {
|
|
17
|
+
this.#data = data;
|
|
18
|
+
this.#label = label;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Extracts a required string field.
|
|
22
|
+
* @param key - Field name
|
|
23
|
+
* @returns The string value
|
|
24
|
+
* @throws Error if the field is missing or not a string
|
|
25
|
+
*/
|
|
26
|
+
string(key) {
|
|
27
|
+
const value = this.#data[key];
|
|
28
|
+
if (!isString(value)) {
|
|
29
|
+
throw new Error(`${this.#label}.${key} must be a string`);
|
|
30
|
+
}
|
|
31
|
+
return value;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Extracts an optional string field.
|
|
35
|
+
* @param key - Field name
|
|
36
|
+
* @returns The string value or undefined
|
|
37
|
+
* @throws Error if the field is present but not a string
|
|
38
|
+
*/
|
|
39
|
+
optionalString(key) {
|
|
40
|
+
const value = this.#data[key];
|
|
41
|
+
if (value === undefined)
|
|
42
|
+
return undefined;
|
|
43
|
+
if (!isString(value)) {
|
|
44
|
+
throw new Error(`${this.#label}.${key} must be a string`);
|
|
45
|
+
}
|
|
46
|
+
return value;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Extracts a required number field.
|
|
50
|
+
* @param key - Field name
|
|
51
|
+
* @returns The number value
|
|
52
|
+
* @throws Error if the field is missing or not a number
|
|
53
|
+
*/
|
|
54
|
+
number(key) {
|
|
55
|
+
const value = this.#data[key];
|
|
56
|
+
if (!isNumber(value)) {
|
|
57
|
+
throw new Error(`${this.#label}.${key} must be a number`);
|
|
58
|
+
}
|
|
59
|
+
return value;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Extracts an optional number field.
|
|
63
|
+
* @param key - Field name
|
|
64
|
+
* @returns The number value or undefined
|
|
65
|
+
* @throws Error if the field is present but not a number
|
|
66
|
+
*/
|
|
67
|
+
optionalNumber(key) {
|
|
68
|
+
const value = this.#data[key];
|
|
69
|
+
if (value === undefined)
|
|
70
|
+
return undefined;
|
|
71
|
+
if (!isNumber(value)) {
|
|
72
|
+
throw new Error(`${this.#label}.${key} must be a number`);
|
|
73
|
+
}
|
|
74
|
+
return value;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Extracts a required non-negative integer field.
|
|
78
|
+
* @param key - Field name
|
|
79
|
+
* @returns The integer value
|
|
80
|
+
* @throws Error if the field is missing, not a number, or negative
|
|
81
|
+
*/
|
|
82
|
+
nonNegativeInteger(key) {
|
|
83
|
+
const value = this.#data[key];
|
|
84
|
+
if (typeof value !== 'number' || !Number.isInteger(value) || value < 0) {
|
|
85
|
+
throw new Error(`${this.#label}.${key} must be a non-negative integer`);
|
|
86
|
+
}
|
|
87
|
+
return value;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Extracts an optional non-negative integer field.
|
|
91
|
+
* @param key - Field name
|
|
92
|
+
* @returns The integer value or undefined
|
|
93
|
+
* @throws Error if the field is present but not a non-negative integer
|
|
94
|
+
*/
|
|
95
|
+
optionalNonNegativeInteger(key) {
|
|
96
|
+
const value = this.#data[key];
|
|
97
|
+
if (value === undefined)
|
|
98
|
+
return undefined;
|
|
99
|
+
if (!isNumber(value) || !Number.isInteger(value) || value < 0) {
|
|
100
|
+
throw new Error(`${this.#label}.${key} must be a non-negative integer`);
|
|
101
|
+
}
|
|
102
|
+
return value;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Extracts a required string field and validates it against a predicate.
|
|
106
|
+
* @param key - Field name
|
|
107
|
+
* @param predicate - Validation function
|
|
108
|
+
* @param allowed - Description of allowed values for the error message
|
|
109
|
+
* @returns The validated string value
|
|
110
|
+
*/
|
|
111
|
+
stringEnum(key, predicate, allowed) {
|
|
112
|
+
const value = this.string(key);
|
|
113
|
+
if (!predicate(value)) {
|
|
114
|
+
throw new Error(`${this.#label}.${key} must be ${allowed}`);
|
|
115
|
+
}
|
|
116
|
+
return value;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Extracts a required string field and validates it with a custom check.
|
|
120
|
+
* @param key - Field name
|
|
121
|
+
* @param check - Validation function returning true if valid
|
|
122
|
+
* @param constraint - Description of the constraint for the error message
|
|
123
|
+
* @returns The validated string value
|
|
124
|
+
*/
|
|
125
|
+
validatedString(key, check, constraint) {
|
|
126
|
+
const value = this.string(key);
|
|
127
|
+
if (!check(value)) {
|
|
128
|
+
throw new Error(`${this.#label}.${key} must be ${constraint}`);
|
|
129
|
+
}
|
|
130
|
+
return value;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Extracts a required array-of-strings field.
|
|
134
|
+
* @param key - Field name
|
|
135
|
+
* @returns The string array
|
|
136
|
+
* @throws Error if the field is missing or not an array of strings
|
|
137
|
+
*/
|
|
138
|
+
stringArray(key) {
|
|
139
|
+
const value = this.#data[key];
|
|
140
|
+
if (!isArray(value) || !value.every(isString)) {
|
|
141
|
+
throw new Error(`${this.#label}.${key} must be an array of strings`);
|
|
142
|
+
}
|
|
143
|
+
return [...value];
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Extracts a required nested object field.
|
|
147
|
+
* @param key - Field name
|
|
148
|
+
* @returns A new ParsedRecord wrapping the nested object
|
|
149
|
+
* @throws Error if the field is missing or not an object
|
|
150
|
+
*/
|
|
151
|
+
object(key) {
|
|
152
|
+
const value = this.#data[key];
|
|
153
|
+
if (!isObject(value)) {
|
|
154
|
+
throw new Error(`${this.#label}.${key} must be an object`);
|
|
155
|
+
}
|
|
156
|
+
return new ParsedRecord(value, `${this.#label}.${key}`);
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Extracts an optional nested object field.
|
|
160
|
+
* @param key - Field name
|
|
161
|
+
* @returns A new ParsedRecord wrapping the nested object, or undefined
|
|
162
|
+
* @throws Error if the field is present but not an object
|
|
163
|
+
*/
|
|
164
|
+
optionalObject(key) {
|
|
165
|
+
const value = this.#data[key];
|
|
166
|
+
if (value === undefined)
|
|
167
|
+
return undefined;
|
|
168
|
+
if (!isObject(value)) {
|
|
169
|
+
throw new Error(`${this.#label}.${key} must be an object`);
|
|
170
|
+
}
|
|
171
|
+
return new ParsedRecord(value, `${this.#label}.${key}`);
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Returns the raw value of a field without validation.
|
|
175
|
+
* @param key - Field name
|
|
176
|
+
*/
|
|
177
|
+
raw(key) {
|
|
178
|
+
return this.#data[key];
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Returns all keys in the underlying record.
|
|
182
|
+
*/
|
|
183
|
+
keys() {
|
|
184
|
+
return Object.keys(this.#data);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Wraps an unknown value as a ParsedRecord after verifying it is an object.
|
|
189
|
+
* @param data - The unknown value to parse
|
|
190
|
+
* @param label - Label for error messages (e.g. "Config", "patches[0]")
|
|
191
|
+
* @returns A ParsedRecord for typed field extraction
|
|
192
|
+
* @throws Error if data is not a plain object
|
|
193
|
+
*/
|
|
194
|
+
export function parseObject(data, label) {
|
|
195
|
+
if (!isObject(data)) {
|
|
196
|
+
throw new Error(`${label} must be an object`);
|
|
197
|
+
}
|
|
198
|
+
return new ParsedRecord(data, label);
|
|
199
|
+
}
|
|
200
|
+
//# sourceMappingURL=parse.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** Converts Windows path separators to forward slashes for stable comparisons. */
|
|
2
|
+
export declare function normalizePathSlashes(path: string): string;
|
|
3
|
+
/** Checks whether a path is explicitly absolute on either POSIX or Windows. */
|
|
4
|
+
export declare function isExplicitAbsolutePath(path: string): boolean;
|
|
5
|
+
/** Resolves a candidate path and returns whether it stays within the given root. */
|
|
6
|
+
export declare function isPathInsideRoot(root: string, candidate: string): boolean;
|
|
7
|
+
/** Checks whether a relative path stays contained within an arbitrary root. */
|
|
8
|
+
export declare function isContainedRelativePath(path: string): boolean;
|
|
9
|
+
/** Converts a candidate path to a normalized root-relative path, rejecting escapes. */
|
|
10
|
+
export declare function toRootRelativePath(root: string, candidate: string): string;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
+
import { isAbsolute, relative, resolve } from 'node:path';
|
|
3
|
+
const WINDOWS_ABSOLUTE_PATH = /^[a-zA-Z]:[\\/]/;
|
|
4
|
+
const RELATIVE_PATH_ROOT = resolve('/__fireforge_path_root__');
|
|
5
|
+
/** Converts Windows path separators to forward slashes for stable comparisons. */
|
|
6
|
+
export function normalizePathSlashes(path) {
|
|
7
|
+
return path.replace(/\\/g, '/');
|
|
8
|
+
}
|
|
9
|
+
/** Checks whether a path is explicitly absolute on either POSIX or Windows. */
|
|
10
|
+
export function isExplicitAbsolutePath(path) {
|
|
11
|
+
return isAbsolute(path) || WINDOWS_ABSOLUTE_PATH.test(path);
|
|
12
|
+
}
|
|
13
|
+
/** Resolves a candidate path and returns whether it stays within the given root. */
|
|
14
|
+
export function isPathInsideRoot(root, candidate) {
|
|
15
|
+
const resolvedRoot = resolve(root);
|
|
16
|
+
const resolvedCandidate = isExplicitAbsolutePath(candidate)
|
|
17
|
+
? resolve(candidate)
|
|
18
|
+
: resolve(resolvedRoot, candidate);
|
|
19
|
+
const relativePath = relative(resolvedRoot, resolvedCandidate);
|
|
20
|
+
return (relativePath === '' ||
|
|
21
|
+
(!relativePath.startsWith('..') &&
|
|
22
|
+
!isAbsolute(relativePath) &&
|
|
23
|
+
!WINDOWS_ABSOLUTE_PATH.test(relativePath)));
|
|
24
|
+
}
|
|
25
|
+
/** Checks whether a relative path stays contained within an arbitrary root. */
|
|
26
|
+
export function isContainedRelativePath(path) {
|
|
27
|
+
if (isExplicitAbsolutePath(path)) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
return isPathInsideRoot(RELATIVE_PATH_ROOT, path);
|
|
31
|
+
}
|
|
32
|
+
/** Converts a candidate path to a normalized root-relative path, rejecting escapes. */
|
|
33
|
+
export function toRootRelativePath(root, candidate) {
|
|
34
|
+
const resolvedRoot = resolve(root);
|
|
35
|
+
const resolvedCandidate = isExplicitAbsolutePath(candidate)
|
|
36
|
+
? resolve(candidate)
|
|
37
|
+
: resolve(resolvedRoot, candidate);
|
|
38
|
+
if (!isPathInsideRoot(resolvedRoot, resolvedCandidate)) {
|
|
39
|
+
throw new Error(`Path escapes root: ${candidate}`);
|
|
40
|
+
}
|
|
41
|
+
return normalizePathSlashes(relative(resolvedRoot, resolvedCandidate));
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Supported operating system platforms.
|
|
3
|
+
*/
|
|
4
|
+
export type Platform = 'darwin' | 'linux' | 'win32';
|
|
5
|
+
/**
|
|
6
|
+
* Supported CPU architectures.
|
|
7
|
+
*/
|
|
8
|
+
export type Arch = 'x64' | 'arm64';
|
|
9
|
+
/**
|
|
10
|
+
* Gets the current operating system platform.
|
|
11
|
+
* @throws Error if running on an unsupported platform
|
|
12
|
+
*/
|
|
13
|
+
export declare function getPlatform(): Platform;
|
|
14
|
+
/**
|
|
15
|
+
* Gets the current CPU architecture.
|
|
16
|
+
* @throws Error if running on an unsupported architecture
|
|
17
|
+
*/
|
|
18
|
+
export declare function getArch(): Arch;
|
|
19
|
+
/**
|
|
20
|
+
* Gets the mozconfig filename for the current platform.
|
|
21
|
+
*/
|
|
22
|
+
export declare function getMozconfigName(): string;
|
|
23
|
+
/**
|
|
24
|
+
* Checks if the current platform is macOS.
|
|
25
|
+
*/
|
|
26
|
+
export declare function isDarwin(): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Checks if the current platform is Linux.
|
|
29
|
+
*/
|
|
30
|
+
export declare function isLinux(): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Checks if the current platform is Windows.
|
|
33
|
+
*/
|
|
34
|
+
export declare function isWindows(): boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Gets the appropriate file extension for executables on the current platform.
|
|
37
|
+
*/
|
|
38
|
+
export declare function getExecutableExtension(): string;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
+
import { arch, platform } from 'node:os';
|
|
3
|
+
import { GeneralError } from '../errors/base.js';
|
|
4
|
+
/**
|
|
5
|
+
* Gets the current operating system platform.
|
|
6
|
+
* @throws Error if running on an unsupported platform
|
|
7
|
+
*/
|
|
8
|
+
export function getPlatform() {
|
|
9
|
+
const p = platform();
|
|
10
|
+
if (p === 'darwin' || p === 'linux' || p === 'win32') {
|
|
11
|
+
return p;
|
|
12
|
+
}
|
|
13
|
+
throw new GeneralError(`Unsupported platform: ${p}. FireForge supports darwin, linux, and win32.`);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Gets the current CPU architecture.
|
|
17
|
+
* @throws Error if running on an unsupported architecture
|
|
18
|
+
*/
|
|
19
|
+
export function getArch() {
|
|
20
|
+
const a = arch();
|
|
21
|
+
if (a === 'x64' || a === 'arm64') {
|
|
22
|
+
return a;
|
|
23
|
+
}
|
|
24
|
+
throw new GeneralError(`Unsupported architecture: ${a}. FireForge supports x64 and arm64.`);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Gets the mozconfig filename for the current platform.
|
|
28
|
+
*/
|
|
29
|
+
export function getMozconfigName() {
|
|
30
|
+
return `${getPlatform()}.mozconfig`;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Checks if the current platform is macOS.
|
|
34
|
+
*/
|
|
35
|
+
export function isDarwin() {
|
|
36
|
+
return platform() === 'darwin';
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Checks if the current platform is Linux.
|
|
40
|
+
*/
|
|
41
|
+
export function isLinux() {
|
|
42
|
+
return platform() === 'linux';
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Checks if the current platform is Windows.
|
|
46
|
+
*/
|
|
47
|
+
export function isWindows() {
|
|
48
|
+
return platform() === 'win32';
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Gets the appropriate file extension for executables on the current platform.
|
|
52
|
+
*/
|
|
53
|
+
export function getExecutableExtension() {
|
|
54
|
+
return isWindows() ? '.exe' : '';
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=platform.js.map
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Result of executing a command.
|
|
3
|
+
*/
|
|
4
|
+
export interface ExecResult {
|
|
5
|
+
/** Standard output content */
|
|
6
|
+
stdout: string;
|
|
7
|
+
/** Standard error content */
|
|
8
|
+
stderr: string;
|
|
9
|
+
/** Process exit code */
|
|
10
|
+
exitCode: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Options for command execution.
|
|
14
|
+
*/
|
|
15
|
+
export interface ExecOptions {
|
|
16
|
+
/** Working directory for the command */
|
|
17
|
+
cwd?: string;
|
|
18
|
+
/** Environment variables */
|
|
19
|
+
env?: Record<string, string>;
|
|
20
|
+
/** Timeout in milliseconds */
|
|
21
|
+
timeout?: number;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Executes a command and returns its output.
|
|
25
|
+
* @param command - Command to execute
|
|
26
|
+
* @param args - Command arguments
|
|
27
|
+
* @param options - Execution options
|
|
28
|
+
* @returns Execution result with stdout, stderr, and exit code
|
|
29
|
+
*/
|
|
30
|
+
export declare function exec(command: string, args: string[], options?: ExecOptions): Promise<ExecResult>;
|
|
31
|
+
/**
|
|
32
|
+
* Callback for streaming output.
|
|
33
|
+
*/
|
|
34
|
+
export type StreamCallback = (data: string) => void;
|
|
35
|
+
/**
|
|
36
|
+
* Options for streaming command execution.
|
|
37
|
+
*/
|
|
38
|
+
export interface StreamOptions extends ExecOptions {
|
|
39
|
+
/** Callback for stdout data */
|
|
40
|
+
onStdout?: StreamCallback;
|
|
41
|
+
/** Callback for stderr data */
|
|
42
|
+
onStderr?: StreamCallback;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Executes a command and streams its output.
|
|
46
|
+
* @param command - Command to execute
|
|
47
|
+
* @param args - Command arguments
|
|
48
|
+
* @param options - Execution options
|
|
49
|
+
* @returns Exit code of the process
|
|
50
|
+
*/
|
|
51
|
+
export declare function execStream(command: string, args: string[], options?: StreamOptions): Promise<number>;
|
|
52
|
+
/**
|
|
53
|
+
* Executes a command and inherits stdio (shows output directly).
|
|
54
|
+
* @param command - Command to execute
|
|
55
|
+
* @param args - Command arguments
|
|
56
|
+
* @param options - Execution options
|
|
57
|
+
* @returns Exit code of the process
|
|
58
|
+
*/
|
|
59
|
+
export declare function execInherit(command: string, args: string[], options?: ExecOptions): Promise<number>;
|
|
60
|
+
/**
|
|
61
|
+
* Executes a command while inheriting stdin, streaming stdout/stderr live,
|
|
62
|
+
* and capturing the emitted output for diagnostics.
|
|
63
|
+
* @param command - Command to execute
|
|
64
|
+
* @param args - Command arguments
|
|
65
|
+
* @param options - Execution options
|
|
66
|
+
* @returns Execution result with stdout, stderr, and exit code
|
|
67
|
+
*/
|
|
68
|
+
export declare function execInheritCapture(command: string, args: string[], options?: ExecOptions): Promise<ExecResult>;
|
|
69
|
+
/**
|
|
70
|
+
* Finds an executable in the system PATH.
|
|
71
|
+
* @param name - Name of the executable
|
|
72
|
+
* @returns Full path to the executable, or undefined if not found
|
|
73
|
+
*/
|
|
74
|
+
export declare function findExecutable(name: string): Promise<string | undefined>;
|
|
75
|
+
/**
|
|
76
|
+
* Checks if an executable exists in the system PATH.
|
|
77
|
+
* @param name - Name of the executable
|
|
78
|
+
* @returns True if the executable exists
|
|
79
|
+
*/
|
|
80
|
+
export declare function executableExists(name: string): Promise<boolean>;
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
+
import { spawn } from 'node:child_process';
|
|
3
|
+
import { constants as osConstants } from 'node:os';
|
|
4
|
+
// 50 MB cap per stream to prevent OOM — large toolchain builds (e.g. Firefox, Chromium)
|
|
5
|
+
// can easily blow past this, so we truncate rather than let the buffer grow unbounded.
|
|
6
|
+
const MAX_OUTPUT_SIZE = 50 * 1024 * 1024;
|
|
7
|
+
function createStreamCollector(mirror) {
|
|
8
|
+
const chunks = [];
|
|
9
|
+
let totalLength = 0;
|
|
10
|
+
let truncated = false;
|
|
11
|
+
return {
|
|
12
|
+
onData: (data) => {
|
|
13
|
+
const chunk = data.toString();
|
|
14
|
+
mirror?.write(chunk);
|
|
15
|
+
if (truncated)
|
|
16
|
+
return;
|
|
17
|
+
const remaining = MAX_OUTPUT_SIZE - totalLength;
|
|
18
|
+
if (chunk.length > remaining) {
|
|
19
|
+
chunks.push(chunk.slice(0, remaining));
|
|
20
|
+
chunks.push('\n[truncated — output exceeded 50 MB]');
|
|
21
|
+
totalLength = MAX_OUTPUT_SIZE;
|
|
22
|
+
truncated = true;
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
chunks.push(chunk);
|
|
26
|
+
totalLength += chunk.length;
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
getText: () => chunks.join(''),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function exitCodeFromClose(code, signal) {
|
|
33
|
+
if (code !== null) {
|
|
34
|
+
return code;
|
|
35
|
+
}
|
|
36
|
+
if (signal) {
|
|
37
|
+
const signalNumber = osConstants.signals[signal];
|
|
38
|
+
if (typeof signalNumber === 'number') {
|
|
39
|
+
return 128 + signalNumber;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return 1;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Executes a command and returns its output.
|
|
46
|
+
* @param command - Command to execute
|
|
47
|
+
* @param args - Command arguments
|
|
48
|
+
* @param options - Execution options
|
|
49
|
+
* @returns Execution result with stdout, stderr, and exit code
|
|
50
|
+
*/
|
|
51
|
+
export async function exec(command, args, options = {}) {
|
|
52
|
+
return new Promise((resolve, reject) => {
|
|
53
|
+
const child = spawn(command, args, {
|
|
54
|
+
cwd: options.cwd,
|
|
55
|
+
env: { ...process.env, ...options.env },
|
|
56
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
57
|
+
timeout: options.timeout,
|
|
58
|
+
});
|
|
59
|
+
const out = createStreamCollector();
|
|
60
|
+
const err = createStreamCollector();
|
|
61
|
+
child.stdout.on('data', out.onData);
|
|
62
|
+
child.stderr.on('data', err.onData);
|
|
63
|
+
child.on('error', (error) => {
|
|
64
|
+
reject(error);
|
|
65
|
+
});
|
|
66
|
+
child.on('close', (code, signal) => {
|
|
67
|
+
resolve({
|
|
68
|
+
stdout: out.getText(),
|
|
69
|
+
stderr: err.getText(),
|
|
70
|
+
exitCode: exitCodeFromClose(code, signal),
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Executes a command and streams its output.
|
|
77
|
+
* @param command - Command to execute
|
|
78
|
+
* @param args - Command arguments
|
|
79
|
+
* @param options - Execution options
|
|
80
|
+
* @returns Exit code of the process
|
|
81
|
+
*/
|
|
82
|
+
export async function execStream(command, args, options = {}) {
|
|
83
|
+
return new Promise((resolve, reject) => {
|
|
84
|
+
const child = spawn(command, args, {
|
|
85
|
+
cwd: options.cwd,
|
|
86
|
+
env: { ...process.env, ...options.env },
|
|
87
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
88
|
+
timeout: options.timeout,
|
|
89
|
+
});
|
|
90
|
+
child.stdout.on('data', (data) => {
|
|
91
|
+
options.onStdout?.(data.toString());
|
|
92
|
+
});
|
|
93
|
+
child.stderr.on('data', (data) => {
|
|
94
|
+
options.onStderr?.(data.toString());
|
|
95
|
+
});
|
|
96
|
+
child.on('error', (error) => {
|
|
97
|
+
reject(error);
|
|
98
|
+
});
|
|
99
|
+
child.on('close', (code, signal) => {
|
|
100
|
+
resolve(exitCodeFromClose(code, signal));
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Executes a command and inherits stdio (shows output directly).
|
|
106
|
+
* @param command - Command to execute
|
|
107
|
+
* @param args - Command arguments
|
|
108
|
+
* @param options - Execution options
|
|
109
|
+
* @returns Exit code of the process
|
|
110
|
+
*/
|
|
111
|
+
export async function execInherit(command, args, options = {}) {
|
|
112
|
+
return new Promise((resolve, reject) => {
|
|
113
|
+
const child = spawn(command, args, {
|
|
114
|
+
cwd: options.cwd,
|
|
115
|
+
env: { ...process.env, ...options.env },
|
|
116
|
+
stdio: 'inherit',
|
|
117
|
+
timeout: options.timeout,
|
|
118
|
+
});
|
|
119
|
+
child.on('error', (error) => {
|
|
120
|
+
reject(error);
|
|
121
|
+
});
|
|
122
|
+
child.on('close', (code, signal) => {
|
|
123
|
+
resolve(exitCodeFromClose(code, signal));
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Executes a command while inheriting stdin, streaming stdout/stderr live,
|
|
129
|
+
* and capturing the emitted output for diagnostics.
|
|
130
|
+
* @param command - Command to execute
|
|
131
|
+
* @param args - Command arguments
|
|
132
|
+
* @param options - Execution options
|
|
133
|
+
* @returns Execution result with stdout, stderr, and exit code
|
|
134
|
+
*/
|
|
135
|
+
export async function execInheritCapture(command, args, options = {}) {
|
|
136
|
+
return new Promise((resolve, reject) => {
|
|
137
|
+
const child = spawn(command, args, {
|
|
138
|
+
cwd: options.cwd,
|
|
139
|
+
env: { ...process.env, ...options.env },
|
|
140
|
+
stdio: ['inherit', 'pipe', 'pipe'],
|
|
141
|
+
timeout: options.timeout,
|
|
142
|
+
});
|
|
143
|
+
const out = createStreamCollector(process.stdout);
|
|
144
|
+
const err = createStreamCollector(process.stderr);
|
|
145
|
+
child.stdout.on('data', out.onData);
|
|
146
|
+
child.stderr.on('data', err.onData);
|
|
147
|
+
child.on('error', (error) => {
|
|
148
|
+
reject(error);
|
|
149
|
+
});
|
|
150
|
+
child.on('close', (code, signal) => {
|
|
151
|
+
resolve({
|
|
152
|
+
stdout: out.getText(),
|
|
153
|
+
stderr: err.getText(),
|
|
154
|
+
exitCode: exitCodeFromClose(code, signal),
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Finds an executable in the system PATH.
|
|
161
|
+
* @param name - Name of the executable
|
|
162
|
+
* @returns Full path to the executable, or undefined if not found
|
|
163
|
+
*/
|
|
164
|
+
export async function findExecutable(name) {
|
|
165
|
+
const command = process.platform === 'win32' ? 'where' : 'which';
|
|
166
|
+
try {
|
|
167
|
+
const result = await exec(command, [name]);
|
|
168
|
+
if (result.exitCode === 0 && result.stdout.trim()) {
|
|
169
|
+
// Return the first line (first match)
|
|
170
|
+
return result.stdout.trim().split('\n')[0];
|
|
171
|
+
}
|
|
172
|
+
return undefined;
|
|
173
|
+
}
|
|
174
|
+
catch (error) {
|
|
175
|
+
void error;
|
|
176
|
+
return undefined;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Checks if an executable exists in the system PATH.
|
|
181
|
+
* @param name - Name of the executable
|
|
182
|
+
* @returns True if the executable exists
|
|
183
|
+
*/
|
|
184
|
+
export async function executableExists(name) {
|
|
185
|
+
const path = await findExecutable(name);
|
|
186
|
+
return path !== undefined;
|
|
187
|
+
}
|
|
188
|
+
//# sourceMappingURL=process.js.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Escapes special regex characters in a string.
|
|
3
|
+
*/
|
|
4
|
+
export declare function escapeRegex(str: string): string;
|
|
5
|
+
/** Matches hex color values like #fff, #ff00ff, #ff00ff80 (longest-first alternation) */
|
|
6
|
+
export declare const CSS_HEX_COLOR: RegExp;
|
|
7
|
+
/** Matches rgb() or rgba() function calls */
|
|
8
|
+
export declare const CSS_RGB_COLOR: RegExp;
|
|
9
|
+
/** Matches hsl() or hsla() function calls */
|
|
10
|
+
export declare const CSS_HSL_COLOR: RegExp;
|
|
11
|
+
/**
|
|
12
|
+
* Returns true if the content contains any raw CSS color values (hex, rgb, hsl).
|
|
13
|
+
*/
|
|
14
|
+
export declare function hasRawCssColors(content: string): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Strips JS single-line and multi-line comments from source code, replacing them
|
|
17
|
+
* with spaces of equal length to preserve character offsets. String literals
|
|
18
|
+
* (single-quoted, double-quoted, and template) are preserved intact.
|
|
19
|
+
*/
|
|
20
|
+
export declare function stripJsComments(source: string): string;
|
|
21
|
+
/**
|
|
22
|
+
* Counts the total number of raw CSS color values (hex, rgb, hsl) in content.
|
|
23
|
+
*/
|
|
24
|
+
export declare function countRawCssColors(content: string): number;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
+
/**
|
|
3
|
+
* Escapes special regex characters in a string.
|
|
4
|
+
*/
|
|
5
|
+
export function escapeRegex(str) {
|
|
6
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
7
|
+
}
|
|
8
|
+
/** Matches hex color values like #fff, #ff00ff, #ff00ff80 (longest-first alternation) */
|
|
9
|
+
export const CSS_HEX_COLOR = /#(?:[0-9a-fA-F]{8}|[0-9a-fA-F]{6}|[0-9a-fA-F]{3,4})\b/;
|
|
10
|
+
/** Matches rgb() or rgba() function calls */
|
|
11
|
+
export const CSS_RGB_COLOR = /\brgba?\s*\(/;
|
|
12
|
+
/** Matches hsl() or hsla() function calls */
|
|
13
|
+
export const CSS_HSL_COLOR = /\bhsla?\s*\(/;
|
|
14
|
+
// Global variants for counting (cached to avoid re-creation per call)
|
|
15
|
+
const CSS_HEX_COLOR_G = new RegExp(CSS_HEX_COLOR.source, 'g');
|
|
16
|
+
const CSS_RGB_COLOR_G = new RegExp(CSS_RGB_COLOR.source, 'g');
|
|
17
|
+
const CSS_HSL_COLOR_G = new RegExp(CSS_HSL_COLOR.source, 'g');
|
|
18
|
+
/**
|
|
19
|
+
* Returns true if the content contains any raw CSS color values (hex, rgb, hsl).
|
|
20
|
+
*/
|
|
21
|
+
export function hasRawCssColors(content) {
|
|
22
|
+
return CSS_HEX_COLOR.test(content) || CSS_RGB_COLOR.test(content) || CSS_HSL_COLOR.test(content);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Strips JS single-line and multi-line comments from source code, replacing them
|
|
26
|
+
* with spaces of equal length to preserve character offsets. String literals
|
|
27
|
+
* (single-quoted, double-quoted, and template) are preserved intact.
|
|
28
|
+
*/
|
|
29
|
+
export function stripJsComments(source) {
|
|
30
|
+
return source.replace(/\/\/.*$|\/\*[\s\S]*?\*\/|"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|`(?:\\.|[^`\\])*`/gm, (match) => (match.startsWith('/') ? ' '.repeat(match.length) : match));
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Counts the total number of raw CSS color values (hex, rgb, hsl) in content.
|
|
34
|
+
*/
|
|
35
|
+
export function countRawCssColors(content) {
|
|
36
|
+
return ((content.match(CSS_HEX_COLOR_G)?.length ?? 0) +
|
|
37
|
+
(content.match(CSS_RGB_COLOR_G)?.length ?? 0) +
|
|
38
|
+
(content.match(CSS_HSL_COLOR_G)?.length ?? 0));
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=regex.js.map
|