@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.
Files changed (316) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/LICENSE.md +294 -0
  3. package/README.md +435 -0
  4. package/dist/bin/fireforge.d.ts +10 -0
  5. package/dist/bin/fireforge.js +29 -0
  6. package/dist/src/cli.d.ts +33 -0
  7. package/dist/src/cli.js +180 -0
  8. package/dist/src/commands/bootstrap.d.ts +9 -0
  9. package/dist/src/commands/bootstrap.js +73 -0
  10. package/dist/src/commands/build.d.ts +11 -0
  11. package/dist/src/commands/build.js +102 -0
  12. package/dist/src/commands/config.d.ts +13 -0
  13. package/dist/src/commands/config.js +135 -0
  14. package/dist/src/commands/discard.d.ts +12 -0
  15. package/dist/src/commands/discard.js +84 -0
  16. package/dist/src/commands/doctor.d.ts +18 -0
  17. package/dist/src/commands/doctor.js +356 -0
  18. package/dist/src/commands/download.d.ts +11 -0
  19. package/dist/src/commands/download.js +127 -0
  20. package/dist/src/commands/export-all.d.ts +11 -0
  21. package/dist/src/commands/export-all.js +122 -0
  22. package/dist/src/commands/export-shared.d.ts +48 -0
  23. package/dist/src/commands/export-shared.js +208 -0
  24. package/dist/src/commands/export.d.ts +13 -0
  25. package/dist/src/commands/export.js +178 -0
  26. package/dist/src/commands/furnace/apply.d.ts +7 -0
  27. package/dist/src/commands/furnace/apply.js +80 -0
  28. package/dist/src/commands/furnace/create.d.ts +8 -0
  29. package/dist/src/commands/furnace/create.js +377 -0
  30. package/dist/src/commands/furnace/deploy.d.ts +8 -0
  31. package/dist/src/commands/furnace/deploy.js +338 -0
  32. package/dist/src/commands/furnace/diff.d.ts +7 -0
  33. package/dist/src/commands/furnace/diff.js +119 -0
  34. package/dist/src/commands/furnace/index.d.ts +16 -0
  35. package/dist/src/commands/furnace/index.js +121 -0
  36. package/dist/src/commands/furnace/list.d.ts +5 -0
  37. package/dist/src/commands/furnace/list.js +65 -0
  38. package/dist/src/commands/furnace/override.d.ts +8 -0
  39. package/dist/src/commands/furnace/override.js +188 -0
  40. package/dist/src/commands/furnace/preview.d.ts +7 -0
  41. package/dist/src/commands/furnace/preview.js +96 -0
  42. package/dist/src/commands/furnace/remove.d.ts +8 -0
  43. package/dist/src/commands/furnace/remove.js +159 -0
  44. package/dist/src/commands/furnace/scan.d.ts +5 -0
  45. package/dist/src/commands/furnace/scan.js +112 -0
  46. package/dist/src/commands/furnace/status.d.ts +7 -0
  47. package/dist/src/commands/furnace/status.js +137 -0
  48. package/dist/src/commands/furnace/validate.d.ts +6 -0
  49. package/dist/src/commands/furnace/validate.js +91 -0
  50. package/dist/src/commands/furnace/validation-output.d.ts +7 -0
  51. package/dist/src/commands/furnace/validation-output.js +22 -0
  52. package/dist/src/commands/import.d.ts +11 -0
  53. package/dist/src/commands/import.js +241 -0
  54. package/dist/src/commands/lint.d.ts +10 -0
  55. package/dist/src/commands/lint.js +118 -0
  56. package/dist/src/commands/package.d.ts +11 -0
  57. package/dist/src/commands/package.js +80 -0
  58. package/dist/src/commands/re-export.d.ts +12 -0
  59. package/dist/src/commands/re-export.js +242 -0
  60. package/dist/src/commands/rebase/abort.d.ts +7 -0
  61. package/dist/src/commands/rebase/abort.js +49 -0
  62. package/dist/src/commands/rebase/confirm.d.ts +18 -0
  63. package/dist/src/commands/rebase/confirm.js +33 -0
  64. package/dist/src/commands/rebase/continue.d.ts +7 -0
  65. package/dist/src/commands/rebase/continue.js +81 -0
  66. package/dist/src/commands/rebase/index.d.ts +22 -0
  67. package/dist/src/commands/rebase/index.js +127 -0
  68. package/dist/src/commands/rebase/patch-loop.d.ts +9 -0
  69. package/dist/src/commands/rebase/patch-loop.js +135 -0
  70. package/dist/src/commands/rebase/summary.d.ts +12 -0
  71. package/dist/src/commands/rebase/summary.js +43 -0
  72. package/dist/src/commands/rebase.d.ts +4 -0
  73. package/dist/src/commands/rebase.js +6 -0
  74. package/dist/src/commands/register.d.ts +13 -0
  75. package/dist/src/commands/register.js +67 -0
  76. package/dist/src/commands/reset.d.ts +11 -0
  77. package/dist/src/commands/reset.js +83 -0
  78. package/dist/src/commands/resolve.d.ts +9 -0
  79. package/dist/src/commands/resolve.js +124 -0
  80. package/dist/src/commands/run.d.ts +9 -0
  81. package/dist/src/commands/run.js +91 -0
  82. package/dist/src/commands/setup-support.d.ts +23 -0
  83. package/dist/src/commands/setup-support.js +310 -0
  84. package/dist/src/commands/setup.d.ts +11 -0
  85. package/dist/src/commands/setup.js +94 -0
  86. package/dist/src/commands/status.d.ts +11 -0
  87. package/dist/src/commands/status.js +268 -0
  88. package/dist/src/commands/test.d.ts +12 -0
  89. package/dist/src/commands/test.js +182 -0
  90. package/dist/src/commands/token-coverage.d.ts +5 -0
  91. package/dist/src/commands/token-coverage.js +57 -0
  92. package/dist/src/commands/token.d.ts +14 -0
  93. package/dist/src/commands/token.js +121 -0
  94. package/dist/src/commands/watch.d.ts +9 -0
  95. package/dist/src/commands/watch.js +112 -0
  96. package/dist/src/commands/wire.d.ts +13 -0
  97. package/dist/src/commands/wire.js +149 -0
  98. package/dist/src/core/ast-utils.d.ts +47 -0
  99. package/dist/src/core/ast-utils.js +57 -0
  100. package/dist/src/core/brand-validation.d.ts +7 -0
  101. package/dist/src/core/brand-validation.js +15 -0
  102. package/dist/src/core/branding.d.ts +49 -0
  103. package/dist/src/core/branding.js +229 -0
  104. package/dist/src/core/browser-wire.d.ts +40 -0
  105. package/dist/src/core/browser-wire.js +66 -0
  106. package/dist/src/core/build-prepare.d.ts +25 -0
  107. package/dist/src/core/build-prepare.js +93 -0
  108. package/dist/src/core/config-mutate.d.ts +15 -0
  109. package/dist/src/core/config-mutate.js +51 -0
  110. package/dist/src/core/config-paths.d.ts +28 -0
  111. package/dist/src/core/config-paths.js +65 -0
  112. package/dist/src/core/config-state.d.ts +28 -0
  113. package/dist/src/core/config-state.js +152 -0
  114. package/dist/src/core/config-validate.d.ts +11 -0
  115. package/dist/src/core/config-validate.js +141 -0
  116. package/dist/src/core/config.d.ts +39 -0
  117. package/dist/src/core/config.js +70 -0
  118. package/dist/src/core/file-lock.d.ts +11 -0
  119. package/dist/src/core/file-lock.js +80 -0
  120. package/dist/src/core/firefox-archive.d.ts +40 -0
  121. package/dist/src/core/firefox-archive.js +63 -0
  122. package/dist/src/core/firefox-cache.d.ts +23 -0
  123. package/dist/src/core/firefox-cache.js +134 -0
  124. package/dist/src/core/firefox-download.d.ts +21 -0
  125. package/dist/src/core/firefox-download.js +129 -0
  126. package/dist/src/core/firefox-extract.d.ts +21 -0
  127. package/dist/src/core/firefox-extract.js +53 -0
  128. package/dist/src/core/firefox.d.ts +34 -0
  129. package/dist/src/core/firefox.js +78 -0
  130. package/dist/src/core/furnace-apply-helpers.d.ts +21 -0
  131. package/dist/src/core/furnace-apply-helpers.js +244 -0
  132. package/dist/src/core/furnace-apply.d.ts +16 -0
  133. package/dist/src/core/furnace-apply.js +147 -0
  134. package/dist/src/core/furnace-config.d.ts +94 -0
  135. package/dist/src/core/furnace-config.js +372 -0
  136. package/dist/src/core/furnace-constants.d.ts +4 -0
  137. package/dist/src/core/furnace-constants.js +6 -0
  138. package/dist/src/core/furnace-registration-ast.d.ts +24 -0
  139. package/dist/src/core/furnace-registration-ast.js +218 -0
  140. package/dist/src/core/furnace-registration-remove.d.ts +14 -0
  141. package/dist/src/core/furnace-registration-remove.js +89 -0
  142. package/dist/src/core/furnace-registration-validate.d.ts +20 -0
  143. package/dist/src/core/furnace-registration-validate.js +40 -0
  144. package/dist/src/core/furnace-registration.d.ts +29 -0
  145. package/dist/src/core/furnace-registration.js +96 -0
  146. package/dist/src/core/furnace-rollback.d.ts +20 -0
  147. package/dist/src/core/furnace-rollback.js +66 -0
  148. package/dist/src/core/furnace-scanner.d.ts +40 -0
  149. package/dist/src/core/furnace-scanner.js +143 -0
  150. package/dist/src/core/furnace-stories.d.ts +37 -0
  151. package/dist/src/core/furnace-stories.js +185 -0
  152. package/dist/src/core/furnace-validate-accessibility.d.ts +6 -0
  153. package/dist/src/core/furnace-validate-accessibility.js +32 -0
  154. package/dist/src/core/furnace-validate-checks.d.ts +4 -0
  155. package/dist/src/core/furnace-validate-checks.js +7 -0
  156. package/dist/src/core/furnace-validate-compatibility.d.ts +6 -0
  157. package/dist/src/core/furnace-validate-compatibility.js +57 -0
  158. package/dist/src/core/furnace-validate-helpers.d.ts +28 -0
  159. package/dist/src/core/furnace-validate-helpers.js +129 -0
  160. package/dist/src/core/furnace-validate-registration.d.ts +37 -0
  161. package/dist/src/core/furnace-validate-registration.js +220 -0
  162. package/dist/src/core/furnace-validate-structure.d.ts +6 -0
  163. package/dist/src/core/furnace-validate-structure.js +66 -0
  164. package/dist/src/core/furnace-validate.d.ts +16 -0
  165. package/dist/src/core/furnace-validate.js +103 -0
  166. package/dist/src/core/git-base.d.ts +47 -0
  167. package/dist/src/core/git-base.js +50 -0
  168. package/dist/src/core/git-diff.d.ts +63 -0
  169. package/dist/src/core/git-diff.js +246 -0
  170. package/dist/src/core/git-file-ops.d.ts +65 -0
  171. package/dist/src/core/git-file-ops.js +141 -0
  172. package/dist/src/core/git-status.d.ts +65 -0
  173. package/dist/src/core/git-status.js +163 -0
  174. package/dist/src/core/git.d.ts +113 -0
  175. package/dist/src/core/git.js +363 -0
  176. package/dist/src/core/license-headers.d.ts +36 -0
  177. package/dist/src/core/license-headers.js +83 -0
  178. package/dist/src/core/mach-build-artifacts.d.ts +29 -0
  179. package/dist/src/core/mach-build-artifacts.js +117 -0
  180. package/dist/src/core/mach-mozconfig.d.ts +17 -0
  181. package/dist/src/core/mach-mozconfig.js +50 -0
  182. package/dist/src/core/mach-python.d.ts +16 -0
  183. package/dist/src/core/mach-python.js +126 -0
  184. package/dist/src/core/mach.d.ts +106 -0
  185. package/dist/src/core/mach.js +166 -0
  186. package/dist/src/core/manifest-helpers.d.ts +25 -0
  187. package/dist/src/core/manifest-helpers.js +96 -0
  188. package/dist/src/core/manifest-register.d.ts +30 -0
  189. package/dist/src/core/manifest-register.js +65 -0
  190. package/dist/src/core/manifest-rules.d.ts +39 -0
  191. package/dist/src/core/manifest-rules.js +151 -0
  192. package/dist/src/core/manifest-tokenizers.d.ts +34 -0
  193. package/dist/src/core/manifest-tokenizers.js +84 -0
  194. package/dist/src/core/parser-fallback.d.ts +36 -0
  195. package/dist/src/core/parser-fallback.js +43 -0
  196. package/dist/src/core/patch-apply-fuzz.d.ts +29 -0
  197. package/dist/src/core/patch-apply-fuzz.js +70 -0
  198. package/dist/src/core/patch-apply.d.ts +46 -0
  199. package/dist/src/core/patch-apply.js +235 -0
  200. package/dist/src/core/patch-export.d.ts +99 -0
  201. package/dist/src/core/patch-export.js +314 -0
  202. package/dist/src/core/patch-files.d.ts +11 -0
  203. package/dist/src/core/patch-files.js +51 -0
  204. package/dist/src/core/patch-lint.d.ts +72 -0
  205. package/dist/src/core/patch-lint.js +403 -0
  206. package/dist/src/core/patch-lock.d.ts +8 -0
  207. package/dist/src/core/patch-lock.js +29 -0
  208. package/dist/src/core/patch-manifest-consistency.d.ts +24 -0
  209. package/dist/src/core/patch-manifest-consistency.js +135 -0
  210. package/dist/src/core/patch-manifest-io.d.ts +36 -0
  211. package/dist/src/core/patch-manifest-io.js +77 -0
  212. package/dist/src/core/patch-manifest-query.d.ts +48 -0
  213. package/dist/src/core/patch-manifest-query.js +124 -0
  214. package/dist/src/core/patch-manifest-validate.d.ts +22 -0
  215. package/dist/src/core/patch-manifest-validate.js +72 -0
  216. package/dist/src/core/patch-manifest.d.ts +11 -0
  217. package/dist/src/core/patch-manifest.js +12 -0
  218. package/dist/src/core/patch-parse.d.ts +43 -0
  219. package/dist/src/core/patch-parse.js +143 -0
  220. package/dist/src/core/patch-transform.d.ts +21 -0
  221. package/dist/src/core/patch-transform.js +138 -0
  222. package/dist/src/core/rebase-session.d.ts +47 -0
  223. package/dist/src/core/rebase-session.js +65 -0
  224. package/dist/src/core/register-browser-content.d.ts +11 -0
  225. package/dist/src/core/register-browser-content.js +116 -0
  226. package/dist/src/core/register-module.d.ts +11 -0
  227. package/dist/src/core/register-module.js +76 -0
  228. package/dist/src/core/register-shared-css.d.ts +11 -0
  229. package/dist/src/core/register-shared-css.js +117 -0
  230. package/dist/src/core/register-test-manifest.d.ts +18 -0
  231. package/dist/src/core/register-test-manifest.js +99 -0
  232. package/dist/src/core/state-file.d.ts +4 -0
  233. package/dist/src/core/state-file.js +25 -0
  234. package/dist/src/core/token-coverage.d.ts +12 -0
  235. package/dist/src/core/token-coverage.js +74 -0
  236. package/dist/src/core/token-manager.d.ts +55 -0
  237. package/dist/src/core/token-manager.js +387 -0
  238. package/dist/src/core/wire-destroy.d.ts +21 -0
  239. package/dist/src/core/wire-destroy.js +103 -0
  240. package/dist/src/core/wire-dom-fragment.d.ts +23 -0
  241. package/dist/src/core/wire-dom-fragment.js +129 -0
  242. package/dist/src/core/wire-init.d.ts +23 -0
  243. package/dist/src/core/wire-init.js +201 -0
  244. package/dist/src/core/wire-subscript.d.ts +20 -0
  245. package/dist/src/core/wire-subscript.js +134 -0
  246. package/dist/src/core/wire-targets.d.ts +7 -0
  247. package/dist/src/core/wire-targets.js +9 -0
  248. package/dist/src/core/wire-utils.d.ts +88 -0
  249. package/dist/src/core/wire-utils.js +279 -0
  250. package/dist/src/errors/base.d.ts +60 -0
  251. package/dist/src/errors/base.js +87 -0
  252. package/dist/src/errors/build.d.ts +52 -0
  253. package/dist/src/errors/build.js +114 -0
  254. package/dist/src/errors/codes.d.ts +29 -0
  255. package/dist/src/errors/codes.js +30 -0
  256. package/dist/src/errors/config.d.ts +31 -0
  257. package/dist/src/errors/config.js +61 -0
  258. package/dist/src/errors/download.d.ts +42 -0
  259. package/dist/src/errors/download.js +95 -0
  260. package/dist/src/errors/furnace.d.ts +10 -0
  261. package/dist/src/errors/furnace.js +22 -0
  262. package/dist/src/errors/git.d.ts +41 -0
  263. package/dist/src/errors/git.js +99 -0
  264. package/dist/src/errors/patch.d.ts +10 -0
  265. package/dist/src/errors/patch.js +26 -0
  266. package/dist/src/errors/rebase.d.ts +20 -0
  267. package/dist/src/errors/rebase.js +30 -0
  268. package/dist/src/index.d.ts +21 -0
  269. package/dist/src/index.js +21 -0
  270. package/dist/src/types/cli.d.ts +14 -0
  271. package/dist/src/types/cli.js +2 -0
  272. package/dist/src/types/commands/index.d.ts +6 -0
  273. package/dist/src/types/commands/index.js +6 -0
  274. package/dist/src/types/commands/options.d.ts +239 -0
  275. package/dist/src/types/commands/options.js +6 -0
  276. package/dist/src/types/commands/patches.d.ts +89 -0
  277. package/dist/src/types/commands/patches.js +6 -0
  278. package/dist/src/types/commands/project.d.ts +71 -0
  279. package/dist/src/types/commands/project.js +6 -0
  280. package/dist/src/types/config.d.ts +101 -0
  281. package/dist/src/types/config.js +2 -0
  282. package/dist/src/types/furnace.d.ts +158 -0
  283. package/dist/src/types/furnace.js +2 -0
  284. package/dist/src/types/index.d.ts +6 -0
  285. package/dist/src/types/index.js +6 -0
  286. package/dist/src/utils/errors.d.ts +2 -0
  287. package/dist/src/utils/errors.js +15 -0
  288. package/dist/src/utils/fs.d.ts +72 -0
  289. package/dist/src/utils/fs.js +179 -0
  290. package/dist/src/utils/logger.d.ts +58 -0
  291. package/dist/src/utils/logger.js +120 -0
  292. package/dist/src/utils/options.d.ts +8 -0
  293. package/dist/src/utils/options.js +16 -0
  294. package/dist/src/utils/package-root.d.ts +10 -0
  295. package/dist/src/utils/package-root.js +53 -0
  296. package/dist/src/utils/parse.d.ts +110 -0
  297. package/dist/src/utils/parse.js +200 -0
  298. package/dist/src/utils/paths.d.ts +10 -0
  299. package/dist/src/utils/paths.js +43 -0
  300. package/dist/src/utils/platform.d.ts +38 -0
  301. package/dist/src/utils/platform.js +56 -0
  302. package/dist/src/utils/process.d.ts +80 -0
  303. package/dist/src/utils/process.js +188 -0
  304. package/dist/src/utils/regex.d.ts +24 -0
  305. package/dist/src/utils/regex.js +40 -0
  306. package/dist/src/utils/validation.d.ts +133 -0
  307. package/dist/src/utils/validation.js +250 -0
  308. package/package.json +106 -0
  309. package/templates/configs/common.mozconfig +24 -0
  310. package/templates/configs/darwin.mozconfig +10 -0
  311. package/templates/configs/linux.mozconfig +12 -0
  312. package/templates/configs/win32.mozconfig +14 -0
  313. package/templates/licenses/0BSD.md +14 -0
  314. package/templates/licenses/EUPL-1.2.md +294 -0
  315. package/templates/licenses/GPL-2.0-or-later.md +339 -0
  316. package/templates/licenses/MPL-2.0.md +383 -0
@@ -0,0 +1,77 @@
1
+ // SPDX-License-Identifier: EUPL-1.2
2
+ /**
3
+ * Manifest I/O: load, save, and add operations for patches.json.
4
+ */
5
+ import { join } from 'node:path';
6
+ import { toError } from '../utils/errors.js';
7
+ import { pathExists, readJson, writeJson } from '../utils/fs.js';
8
+ import { validatePatchesManifest } from './patch-manifest-validate.js';
9
+ /** Filename for the patches manifest */
10
+ export const PATCHES_MANIFEST = 'patches.json';
11
+ /**
12
+ * Loads and validates the patches manifest, returning full state information.
13
+ * @param patchesDir - Path to the patches directory
14
+ */
15
+ export async function loadPatchesManifestState(patchesDir) {
16
+ const manifestPath = join(patchesDir, PATCHES_MANIFEST);
17
+ if (!(await pathExists(manifestPath))) {
18
+ return { exists: false, manifest: null, parseError: undefined };
19
+ }
20
+ try {
21
+ const manifest = validatePatchesManifest(await readJson(manifestPath));
22
+ return {
23
+ exists: true,
24
+ manifest,
25
+ parseError: undefined,
26
+ };
27
+ }
28
+ catch (error) {
29
+ return {
30
+ exists: true,
31
+ manifest: null,
32
+ parseError: toError(error),
33
+ };
34
+ }
35
+ }
36
+ /**
37
+ * Loads the patches manifest if it exists.
38
+ * @param patchesDir - Path to the patches directory
39
+ * @returns PatchesManifest or null if not found
40
+ */
41
+ export async function loadPatchesManifest(patchesDir) {
42
+ const state = await loadPatchesManifestState(patchesDir);
43
+ return state.manifest;
44
+ }
45
+ /**
46
+ * Saves the patches manifest.
47
+ * @param patchesDir - Path to the patches directory
48
+ * @param manifest - Manifest to save
49
+ */
50
+ export async function savePatchesManifest(patchesDir, manifest) {
51
+ const manifestPath = join(patchesDir, PATCHES_MANIFEST);
52
+ await writeJson(manifestPath, manifest);
53
+ }
54
+ /**
55
+ * Adds or updates a patch entry in the manifest.
56
+ * @param patchesDir - Path to the patches directory
57
+ * @param metadata - Patch metadata to add/update
58
+ * @param removeFilenames - Optional filenames to remove in the same read-modify-write cycle
59
+ */
60
+ export async function addPatchToManifest(patchesDir, metadata, removeFilenames) {
61
+ const manifest = (await loadPatchesManifest(patchesDir)) ?? {
62
+ version: 1,
63
+ patches: [],
64
+ };
65
+ // Remove existing entry with same filename if present
66
+ manifest.patches = manifest.patches.filter((p) => p.filename !== metadata.filename);
67
+ // Remove superseded entries in the same cycle to avoid race conditions
68
+ if (removeFilenames && removeFilenames.length > 0) {
69
+ const removeSet = new Set(removeFilenames);
70
+ manifest.patches = manifest.patches.filter((p) => !removeSet.has(p.filename));
71
+ }
72
+ // Add new entry and sort by order
73
+ manifest.patches.push(metadata);
74
+ manifest.patches.sort((a, b) => a.order - b.order);
75
+ await savePatchesManifest(patchesDir, manifest);
76
+ }
77
+ //# sourceMappingURL=patch-manifest-io.js.map
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Query helpers: finding patches by file, integrity checks, version compat, stamping.
3
+ */
4
+ import type { PatchesManifest, PatchInfo, PatchMetadata } from '../types/commands/index.js';
5
+ /**
6
+ * Gets all file paths claimed by patches other than the excluded one.
7
+ * @param manifest - The patches manifest
8
+ * @param excludeFilename - Filename to exclude from collection
9
+ * @returns Set of file paths claimed by other patches
10
+ */
11
+ export declare function getClaimedFiles(manifest: PatchesManifest, excludeFilename: string): Set<string>;
12
+ /**
13
+ * Checks ESR version compatibility.
14
+ * @param patchVersion - Version the patch was created for
15
+ * @param currentVersion - Current project version
16
+ * @returns Warning message if versions differ, null if compatible
17
+ */
18
+ export declare function checkVersionCompatibility(patchVersion: string, currentVersion: string): string | null;
19
+ /**
20
+ * Finds all patches that affect a specific file.
21
+ * @param patchesDir - Path to the patches directory
22
+ * @param filePath - File path to search for
23
+ * @returns Patches affecting the file, sorted by order
24
+ */
25
+ export declare function findPatchesAffectingFile(patchesDir: string, filePath: string): Promise<Array<{
26
+ patch: PatchInfo;
27
+ metadata: PatchMetadata;
28
+ }>>;
29
+ /**
30
+ * Validates that all patches can be applied successfully.
31
+ * Detects modification patches that reference files not in the source.
32
+ * @param patchesDir - Path to the patches directory
33
+ * @param engineDir - Path to the engine directory
34
+ * @returns Array of validation issues with details
35
+ */
36
+ export declare function validatePatchIntegrity(patchesDir: string, engineDir: string): Promise<Array<{
37
+ filename: string;
38
+ message: string;
39
+ targetFile: string | null;
40
+ }>>;
41
+ /**
42
+ * Stamps multiple patches with a new `sourceEsrVersion` in a single
43
+ * manifest read-modify-write cycle.
44
+ * @param patchesDir - Path to the patches directory
45
+ * @param filenames - Patch filenames to update
46
+ * @param newVersion - Version string to set (e.g. "140.0esr")
47
+ */
48
+ export declare function stampPatchVersions(patchesDir: string, filenames: string[], newVersion: string): Promise<void>;
@@ -0,0 +1,124 @@
1
+ // SPDX-License-Identifier: EUPL-1.2
2
+ /**
3
+ * Query helpers: finding patches by file, integrity checks, version compat, stamping.
4
+ */
5
+ import { readText } from '../utils/fs.js';
6
+ import { fileExistsInHead } from './git-file-ops.js';
7
+ import { discoverPatches, getAllTargetFilesFromPatch } from './patch-files.js';
8
+ import { loadPatchesManifest, savePatchesManifest } from './patch-manifest-io.js';
9
+ import { isNewFileInPatch } from './patch-parse.js';
10
+ /**
11
+ * Gets all file paths claimed by patches other than the excluded one.
12
+ * @param manifest - The patches manifest
13
+ * @param excludeFilename - Filename to exclude from collection
14
+ * @returns Set of file paths claimed by other patches
15
+ */
16
+ export function getClaimedFiles(manifest, excludeFilename) {
17
+ const claimed = new Set();
18
+ for (const patch of manifest.patches) {
19
+ if (patch.filename === excludeFilename)
20
+ continue;
21
+ for (const file of patch.filesAffected) {
22
+ claimed.add(file);
23
+ }
24
+ }
25
+ return claimed;
26
+ }
27
+ /**
28
+ * Checks ESR version compatibility.
29
+ * @param patchVersion - Version the patch was created for
30
+ * @param currentVersion - Current project version
31
+ * @returns Warning message if versions differ, null if compatible
32
+ */
33
+ export function checkVersionCompatibility(patchVersion, currentVersion) {
34
+ if (patchVersion === currentVersion) {
35
+ return null;
36
+ }
37
+ // Extract major version numbers
38
+ const patchMajor = parseInt(patchVersion.split('.')[0] ?? '0', 10);
39
+ const currentMajor = parseInt(currentVersion.split('.')[0] ?? '0', 10);
40
+ if (patchMajor !== currentMajor) {
41
+ return (`Patch was created for Firefox ${patchVersion}, ` +
42
+ `but current version is ${currentVersion}. ` +
43
+ `Major version mismatch may cause conflicts.`);
44
+ }
45
+ return (`Patch was created for Firefox ${patchVersion}, ` + `current version is ${currentVersion}.`);
46
+ }
47
+ /**
48
+ * Finds all patches that affect a specific file.
49
+ * @param patchesDir - Path to the patches directory
50
+ * @param filePath - File path to search for
51
+ * @returns Patches affecting the file, sorted by order
52
+ */
53
+ export async function findPatchesAffectingFile(patchesDir, filePath) {
54
+ const manifest = await loadPatchesManifest(patchesDir);
55
+ if (!manifest)
56
+ return [];
57
+ const patches = await discoverPatches(patchesDir);
58
+ const results = [];
59
+ for (const metadata of manifest.patches) {
60
+ if (metadata.filesAffected.includes(filePath)) {
61
+ const patch = patches.find((p) => p.filename === metadata.filename);
62
+ if (patch) {
63
+ results.push({ patch, metadata });
64
+ }
65
+ }
66
+ }
67
+ // Sort by order
68
+ results.sort((a, b) => a.patch.order - b.patch.order);
69
+ return results;
70
+ }
71
+ /**
72
+ * Validates that all patches can be applied successfully.
73
+ * Detects modification patches that reference files not in the source.
74
+ * @param patchesDir - Path to the patches directory
75
+ * @param engineDir - Path to the engine directory
76
+ * @returns Array of validation issues with details
77
+ */
78
+ export async function validatePatchIntegrity(patchesDir, engineDir) {
79
+ const issues = [];
80
+ const patches = await discoverPatches(patchesDir);
81
+ for (const patch of patches) {
82
+ // Check all files in the patch (supports multi-file patches)
83
+ const patchContent = await readText(patch.path);
84
+ const targetFiles = await getAllTargetFilesFromPatch(patch.path);
85
+ for (const targetFile of targetFiles) {
86
+ // Skip new-file sections — they don't need to exist in HEAD
87
+ if (isNewFileInPatch(patchContent, targetFile))
88
+ continue;
89
+ const existsInHead = await fileExistsInHead(engineDir, targetFile);
90
+ if (!existsInHead) {
91
+ issues.push({
92
+ filename: patch.filename,
93
+ message: `Modification patch for file that doesn't exist in source. Re-export with: fireforge export ${targetFile}`,
94
+ targetFile,
95
+ });
96
+ }
97
+ }
98
+ }
99
+ return issues;
100
+ }
101
+ /**
102
+ * Stamps multiple patches with a new `sourceEsrVersion` in a single
103
+ * manifest read-modify-write cycle.
104
+ * @param patchesDir - Path to the patches directory
105
+ * @param filenames - Patch filenames to update
106
+ * @param newVersion - Version string to set (e.g. "140.0esr")
107
+ */
108
+ export async function stampPatchVersions(patchesDir, filenames, newVersion) {
109
+ const manifest = await loadPatchesManifest(patchesDir);
110
+ if (!manifest)
111
+ return;
112
+ const filenameSet = new Set(filenames);
113
+ let modified = false;
114
+ for (const patch of manifest.patches) {
115
+ if (filenameSet.has(patch.filename) && patch.sourceEsrVersion !== newVersion) {
116
+ patch.sourceEsrVersion = newVersion;
117
+ modified = true;
118
+ }
119
+ }
120
+ if (modified) {
121
+ await savePatchesManifest(patchesDir, manifest);
122
+ }
123
+ }
124
+ //# sourceMappingURL=patch-manifest-query.js.map
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Schema validation for patches.json manifest data.
3
+ */
4
+ import type { PatchCategory, PatchesManifest, PatchMetadata } from '../types/commands/index.js';
5
+ /**
6
+ * Validates a single patch metadata entry from raw data.
7
+ * @param data - Raw data to validate
8
+ * @param index - Array index for error messages
9
+ * @returns Validated PatchMetadata
10
+ */
11
+ export declare function validatePatchMetadata(data: unknown, index: number): PatchMetadata;
12
+ /** Validates raw patches.json data and returns the typed manifest shape. */
13
+ export declare function validatePatchesManifest(data: unknown): PatchesManifest;
14
+ /**
15
+ * Infers patch metadata from a filename pattern.
16
+ * @param filename - Patch filename (e.g. "001-ui-toolbar.patch")
17
+ * @returns Inferred category and name
18
+ */
19
+ export declare function inferPatchMetadataFromFilename(filename: string): {
20
+ category: PatchCategory;
21
+ name: string;
22
+ };
@@ -0,0 +1,72 @@
1
+ // SPDX-License-Identifier: EUPL-1.2
2
+ /**
3
+ * Schema validation for patches.json manifest data.
4
+ */
5
+ import { parseObject } from '../utils/parse.js';
6
+ import { isArray, isObject, isValidFirefoxVersion, isValidPatchCategory, PATCH_CATEGORIES, } from '../utils/validation.js';
7
+ /**
8
+ * Validates a single patch metadata entry from raw data.
9
+ * @param data - Raw data to validate
10
+ * @param index - Array index for error messages
11
+ * @returns Validated PatchMetadata
12
+ */
13
+ export function validatePatchMetadata(data, index) {
14
+ const rec = parseObject(data, `patches[${index}]`);
15
+ const filename = rec.string('filename');
16
+ const name = rec.string('name');
17
+ const description = rec.string('description');
18
+ const createdAt = rec.string('createdAt');
19
+ const sourceEsrVersion = rec.string('sourceEsrVersion');
20
+ const order = rec.nonNegativeInteger('order');
21
+ const category = rec.stringEnum('category', (v) => isValidPatchCategory(v), `one of: ${PATCH_CATEGORIES.join(', ')}`);
22
+ if (!isValidFirefoxVersion(sourceEsrVersion)) {
23
+ throw new Error(`patches[${index}].sourceEsrVersion must be a valid Firefox version string`);
24
+ }
25
+ const filesAffected = rec.stringArray('filesAffected');
26
+ return {
27
+ filename,
28
+ order,
29
+ category,
30
+ name,
31
+ description,
32
+ createdAt,
33
+ sourceEsrVersion,
34
+ filesAffected,
35
+ };
36
+ }
37
+ /** Validates raw patches.json data and returns the typed manifest shape. */
38
+ export function validatePatchesManifest(data) {
39
+ if (!isObject(data)) {
40
+ throw new Error('patches.json must be a JSON object');
41
+ }
42
+ if (data['version'] !== 1) {
43
+ throw new Error('patches.json version must be 1');
44
+ }
45
+ if (!isArray(data['patches'])) {
46
+ throw new Error('patches.json field "patches" must be an array');
47
+ }
48
+ return {
49
+ version: 1,
50
+ patches: data['patches'].map((patch, index) => validatePatchMetadata(patch, index)),
51
+ };
52
+ }
53
+ /**
54
+ * Infers patch metadata from a filename pattern.
55
+ * @param filename - Patch filename (e.g. "001-ui-toolbar.patch")
56
+ * @returns Inferred category and name
57
+ */
58
+ export function inferPatchMetadataFromFilename(filename) {
59
+ const categorizedMatch = /^(\d+)-([a-z]+)-(.+)\.patch$/.exec(filename);
60
+ if (categorizedMatch?.[2] && categorizedMatch[3]) {
61
+ const category = categorizedMatch[2];
62
+ if (PATCH_CATEGORIES.includes(category)) {
63
+ return { category, name: categorizedMatch[3] };
64
+ }
65
+ }
66
+ const legacyMatch = /^(\d+)-(.+)\.patch$/.exec(filename);
67
+ if (legacyMatch?.[2]) {
68
+ return { category: 'infra', name: legacyMatch[2] };
69
+ }
70
+ return { category: 'infra', name: filename.replace(/\.patch$/, '') };
71
+ }
72
+ //# sourceMappingURL=patch-manifest-validate.js.map
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Patches manifest — re-exports from focused sub-modules.
3
+ *
4
+ * Callers should continue to import from this module; the internal split
5
+ * is an implementation detail.
6
+ */
7
+ export type { PatchManifestConsistencyIssue } from './patch-manifest-consistency.js';
8
+ export { rebuildPatchesManifest, validatePatchesManifestConsistency, } from './patch-manifest-consistency.js';
9
+ export { addPatchToManifest, loadPatchesManifest, PATCHES_MANIFEST, savePatchesManifest, } from './patch-manifest-io.js';
10
+ export { checkVersionCompatibility, findPatchesAffectingFile, getClaimedFiles, stampPatchVersions, validatePatchIntegrity, } from './patch-manifest-query.js';
11
+ export { validatePatchesManifest } from './patch-manifest-validate.js';
@@ -0,0 +1,12 @@
1
+ // SPDX-License-Identifier: EUPL-1.2
2
+ /**
3
+ * Patches manifest — re-exports from focused sub-modules.
4
+ *
5
+ * Callers should continue to import from this module; the internal split
6
+ * is an implementation detail.
7
+ */
8
+ export { rebuildPatchesManifest, validatePatchesManifestConsistency, } from './patch-manifest-consistency.js';
9
+ export { addPatchToManifest, loadPatchesManifest, PATCHES_MANIFEST, savePatchesManifest, } from './patch-manifest-io.js';
10
+ export { checkVersionCompatibility, findPatchesAffectingFile, getClaimedFiles, stampPatchVersions, validatePatchIntegrity, } from './patch-manifest-query.js';
11
+ export { validatePatchesManifest } from './patch-manifest-validate.js';
12
+ //# sourceMappingURL=patch-manifest.js.map
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Pure parsing functions for extracting information from patch files.
3
+ * All functions are synchronous and operate on string content.
4
+ */
5
+ /**
6
+ * Extracts the order number from a patch filename.
7
+ * Expects format like "001-description.patch"
8
+ * @param filename - Patch filename
9
+ * @returns Order number, or Infinity if no prefix
10
+ */
11
+ export declare function extractOrder(filename: string): number;
12
+ /**
13
+ * Checks whether a specific file is a new-file addition within a patch.
14
+ * For multi-file patches, only inspects the section belonging to targetFile.
15
+ * @param patchContent - The full patch content
16
+ * @param targetFile - The file path to check
17
+ * @returns true if the patch creates targetFile as a new file
18
+ */
19
+ export declare function isNewFileInPatch(patchContent: string, targetFile: string): boolean;
20
+ /**
21
+ * Extracts affected file paths from a diff/patch content.
22
+ * @param diffContent - The diff content to parse
23
+ * @returns Array of file paths
24
+ */
25
+ export declare function extractAffectedFiles(diffContent: string): string[];
26
+ /**
27
+ * Parses hunks from a patch file for a specific target file.
28
+ * @param patchContent - The full patch content
29
+ * @param targetFile - The file path to extract hunks for
30
+ * @returns Array of hunk objects with line info and changes
31
+ */
32
+ export declare function parseHunksForFile(patchContent: string, targetFile: string): Array<{
33
+ oldStart: number;
34
+ oldCount: number;
35
+ newStart: number;
36
+ newCount: number;
37
+ lines: string[];
38
+ noNewlineAtEnd: boolean;
39
+ }>;
40
+ /**
41
+ * Extracts conflicting file paths from git apply error message.
42
+ */
43
+ export declare function extractConflictingFiles(error?: string): string[];
@@ -0,0 +1,143 @@
1
+ // SPDX-License-Identifier: EUPL-1.2
2
+ /**
3
+ * Pure parsing functions for extracting information from patch files.
4
+ * All functions are synchronous and operate on string content.
5
+ */
6
+ /**
7
+ * Extracts the order number from a patch filename.
8
+ * Expects format like "001-description.patch"
9
+ * @param filename - Patch filename
10
+ * @returns Order number, or Infinity if no prefix
11
+ */
12
+ export function extractOrder(filename) {
13
+ const match = /^(\d+)-/.exec(filename);
14
+ if (match?.[1]) {
15
+ return parseInt(match[1], 10);
16
+ }
17
+ return Infinity;
18
+ }
19
+ /**
20
+ * Checks whether a specific file is a new-file addition within a patch.
21
+ * For multi-file patches, only inspects the section belonging to targetFile.
22
+ * @param patchContent - The full patch content
23
+ * @param targetFile - The file path to check
24
+ * @returns true if the patch creates targetFile as a new file
25
+ */
26
+ export function isNewFileInPatch(patchContent, targetFile) {
27
+ const lines = patchContent.split('\n');
28
+ let inTargetFile = false;
29
+ for (const line of lines) {
30
+ if (line.startsWith('diff --git')) {
31
+ const match = /^diff --git a\/.+ b\/(.+)$/.exec(line);
32
+ inTargetFile = match?.[1] === targetFile;
33
+ continue;
34
+ }
35
+ if (!inTargetFile)
36
+ continue;
37
+ // Found hunk header — stop scanning metadata for this file section
38
+ if (line.startsWith('@@'))
39
+ break;
40
+ if (line.startsWith('new file mode ')) {
41
+ return true;
42
+ }
43
+ }
44
+ return false;
45
+ }
46
+ /**
47
+ * Extracts affected file paths from a diff/patch content.
48
+ * @param diffContent - The diff content to parse
49
+ * @returns Array of file paths
50
+ */
51
+ export function extractAffectedFiles(diffContent) {
52
+ const files = new Set();
53
+ const lines = diffContent.split('\n');
54
+ for (const line of lines) {
55
+ // Match "diff --git a/path/to/file b/path/to/file"
56
+ const diffMatch = /^diff --git a\/.+ b\/(.+)$/.exec(line);
57
+ if (diffMatch?.[1]) {
58
+ files.add(diffMatch[1]);
59
+ continue;
60
+ }
61
+ // Match "+++ b/path/to/file" for new files
62
+ const addMatch = /^\+\+\+ b\/(.+)$/.exec(line);
63
+ if (addMatch?.[1] && addMatch[1] !== '/dev/null') {
64
+ files.add(addMatch[1]);
65
+ }
66
+ }
67
+ return Array.from(files).sort();
68
+ }
69
+ /**
70
+ * Parses hunks from a patch file for a specific target file.
71
+ * @param patchContent - The full patch content
72
+ * @param targetFile - The file path to extract hunks for
73
+ * @returns Array of hunk objects with line info and changes
74
+ */
75
+ export function parseHunksForFile(patchContent, targetFile) {
76
+ const hunks = [];
77
+ const lines = patchContent.split('\n');
78
+ let inTargetFile = false;
79
+ let currentHunk = null;
80
+ for (let i = 0; i < lines.length; i++) {
81
+ const line = lines[i] ?? '';
82
+ // Check for diff header
83
+ if (line.startsWith('diff --git')) {
84
+ // Check if this is for our target file
85
+ const match = /^diff --git a\/.+ b\/(.+)$/.exec(line);
86
+ if (currentHunk) {
87
+ hunks.push(currentHunk);
88
+ }
89
+ inTargetFile = match?.[1] === targetFile;
90
+ currentHunk = null;
91
+ continue;
92
+ }
93
+ if (!inTargetFile)
94
+ continue;
95
+ // Check for hunk header
96
+ const hunkMatch = /^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/.exec(line);
97
+ if (hunkMatch) {
98
+ if (currentHunk) {
99
+ hunks.push(currentHunk);
100
+ }
101
+ currentHunk = {
102
+ oldStart: parseInt(hunkMatch[1] ?? '0', 10),
103
+ oldCount: parseInt(hunkMatch[2] ?? '1', 10),
104
+ newStart: parseInt(hunkMatch[3] ?? '0', 10),
105
+ newCount: parseInt(hunkMatch[4] ?? '1', 10),
106
+ lines: [],
107
+ noNewlineAtEnd: false,
108
+ };
109
+ continue;
110
+ }
111
+ // Collect hunk lines
112
+ if (currentHunk) {
113
+ if (line === '\') {
114
+ currentHunk.noNewlineAtEnd = true;
115
+ }
116
+ else if (line.startsWith('+') || line.startsWith('-') || line.startsWith(' ')) {
117
+ currentHunk.lines.push(line);
118
+ }
119
+ }
120
+ }
121
+ if (currentHunk) {
122
+ hunks.push(currentHunk);
123
+ }
124
+ return hunks;
125
+ }
126
+ /**
127
+ * Extracts conflicting file paths from git apply error message.
128
+ */
129
+ export function extractConflictingFiles(error) {
130
+ if (!error)
131
+ return [];
132
+ const files = [];
133
+ const lines = error.split('\n');
134
+ for (const line of lines) {
135
+ // Match "error: patch failed: path/to/file:line"
136
+ const match = /error: patch failed: ([^:]+)/.exec(line);
137
+ if (match?.[1]) {
138
+ files.push(match[1]);
139
+ }
140
+ }
141
+ return files;
142
+ }
143
+ //# sourceMappingURL=patch-parse.js.map
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Pure content transformation functions for patch operations.
3
+ * These operate on file content strings without filesystem side effects.
4
+ */
5
+ /**
6
+ * Extracts the complete file content from a "new file" patch.
7
+ * When targetFile is provided, only extracts content for that file
8
+ * (required for multi-file patches).
9
+ * @param patchPath - Path to the patch file
10
+ * @param targetFile - Optional target file to scope extraction to
11
+ * @returns The file content that the patch would create
12
+ */
13
+ export declare function extractNewFileContent(patchPath: string, targetFile?: string): Promise<string>;
14
+ /**
15
+ * Applies a patch's changes to content.
16
+ * @param content - Original content (null for new files)
17
+ * @param patchPath - Path to the patch file
18
+ * @param targetFile - The file path within the patch
19
+ * @returns Modified content
20
+ */
21
+ export declare function applyPatchToContent(content: string | null, patchPath: string, targetFile: string): Promise<string>;