@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,96 @@
1
+ /**
2
+ * Inserts a line into an array of lines in alphabetical order within a
3
+ * specified range. The comparison key is extracted from each line.
4
+ *
5
+ * @returns Object with insertIndex and previousEntry
6
+ */
7
+ export function findAlphabeticalPosition(lines, startLine, endLine, newKey, extractKey) {
8
+ // Check if existing entries are actually sorted; if not, append at end
9
+ const existingKeys = [];
10
+ for (let i = startLine; i < endLine; i++) {
11
+ const line = lines[i];
12
+ if (line === undefined)
13
+ continue;
14
+ const key = extractKey(line);
15
+ if (key !== undefined) {
16
+ existingKeys.push(key);
17
+ }
18
+ }
19
+ const isSorted = existingKeys.every((k, idx) => idx === 0 || k.localeCompare(existingKeys[idx - 1] ?? '') >= 0);
20
+ if (!isSorted) {
21
+ return { insertIndex: endLine, previousEntry: undefined };
22
+ }
23
+ let insertIndex = endLine;
24
+ let previousEntry;
25
+ for (let i = startLine; i < endLine; i++) {
26
+ const line = lines[i];
27
+ if (line === undefined)
28
+ continue;
29
+ const key = extractKey(line);
30
+ if (key === undefined)
31
+ continue;
32
+ if (key > newKey) {
33
+ insertIndex = i;
34
+ break;
35
+ }
36
+ insertIndex = i + 1;
37
+ previousEntry = line.trim();
38
+ }
39
+ return { insertIndex, previousEntry };
40
+ }
41
+ /**
42
+ * Find alphabetical position within a tokenized jar.mn section.
43
+ */
44
+ export function findAlphabeticalTokenPosition(tokens, sectionTargetPattern, newKey) {
45
+ // Find entry tokens in the section matching the pattern
46
+ const sectionEntries = tokens.filter((t) => t.type === 'entry' && t.parsed && sectionTargetPattern.test(t.parsed.target));
47
+ let insertLineIndex;
48
+ let previousEntry;
49
+ if (sectionEntries.length === 0) {
50
+ // Empty section: find the section header and insert after it
51
+ const headerToken = tokens.find((t) => t.type === 'header' || (t.type === 'directive' && sectionTargetPattern.test(t.raw)));
52
+ if (headerToken) {
53
+ return { insertIndex: headerToken.lineIndex + 1, previousEntry: undefined };
54
+ }
55
+ return { insertIndex: -1, previousEntry: undefined };
56
+ }
57
+ // Default: after the last section entry
58
+ insertLineIndex = (sectionEntries[sectionEntries.length - 1]?.lineIndex ?? 0) + 1;
59
+ for (const entry of sectionEntries) {
60
+ if (!entry.parsed)
61
+ continue;
62
+ const match = sectionTargetPattern.exec(entry.parsed.target);
63
+ const key = match?.[1] ?? entry.parsed.target;
64
+ if (key > newKey) {
65
+ insertLineIndex = entry.lineIndex;
66
+ break;
67
+ }
68
+ insertLineIndex = entry.lineIndex + 1;
69
+ previousEntry = entry.raw.trim();
70
+ }
71
+ return { insertIndex: insertLineIndex, previousEntry };
72
+ }
73
+ /**
74
+ * Find alphabetical position within tokenized moz.build list items.
75
+ */
76
+ export function findAlphabeticalMozBuildPosition(tokens, newKey) {
77
+ const items = tokens.filter((t) => t.type === 'list-item');
78
+ if (items.length === 0) {
79
+ // Insert after list-open
80
+ const openToken = tokens.find((t) => t.type === 'list-open');
81
+ return { insertIndex: (openToken?.lineIndex ?? 0) + 1, previousEntry: undefined };
82
+ }
83
+ let insertLineIndex = (items[items.length - 1]?.lineIndex ?? 0) + 1;
84
+ let previousEntry;
85
+ for (const item of items) {
86
+ const key = item.parsed?.value ?? '';
87
+ if (key > newKey) {
88
+ insertLineIndex = item.lineIndex;
89
+ break;
90
+ }
91
+ insertLineIndex = item.lineIndex + 1;
92
+ previousEntry = item.raw.trim();
93
+ }
94
+ return { insertIndex: insertLineIndex, previousEntry };
95
+ }
96
+ //# sourceMappingURL=manifest-helpers.js.map
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Manifest registration barrel — re-exports all registration targets
3
+ * and provides the shared RegisterResult interface.
4
+ */
5
+ /**
6
+ * Result of a manifest registration operation.
7
+ */
8
+ export interface RegisterResult {
9
+ /** The manifest file that was modified */
10
+ manifest: string;
11
+ /** The entry that was inserted */
12
+ entry: string;
13
+ /** The entry after which the new entry was inserted (for user display) */
14
+ previousEntry?: string | undefined;
15
+ /** Whether the entry already existed (skipped) */
16
+ skipped: boolean;
17
+ /** Whether --after target was not found and fell back to alphabetical */
18
+ afterFallback?: boolean | undefined;
19
+ }
20
+ export { registerBrowserContent } from './register-browser-content.js';
21
+ export { registerFireForgeModule } from './register-module.js';
22
+ export { registerSharedCSS } from './register-shared-css.js';
23
+ export { deregisterTestManifest, registerTestManifest } from './register-test-manifest.js';
24
+ /**
25
+ * Registers a widget file (mjs or css) in toolkit/content/jar.mn.
26
+ *
27
+ * Entry format (3-space indent):
28
+ * content/global/elements/{file} (widgets/{tagName}/{file})
29
+ */
30
+ export declare function registerToolkitWidget(engineDir: string, tagName: string, fileName: string, dryRun?: boolean): Promise<RegisterResult>;
@@ -0,0 +1,65 @@
1
+ // SPDX-License-Identifier: EUPL-1.2
2
+ /**
3
+ * Manifest registration barrel — re-exports all registration targets
4
+ * and provides the shared RegisterResult interface.
5
+ */
6
+ import { join } from 'node:path';
7
+ import { GeneralError } from '../errors/base.js';
8
+ import { pathExists, readText, writeText } from '../utils/fs.js';
9
+ import { findAlphabeticalPosition } from './manifest-helpers.js';
10
+ // Re-export from split modules so existing import sites continue working
11
+ export { registerBrowserContent } from './register-browser-content.js';
12
+ export { registerFireForgeModule } from './register-module.js';
13
+ export { registerSharedCSS } from './register-shared-css.js';
14
+ export { deregisterTestManifest, registerTestManifest } from './register-test-manifest.js';
15
+ // ---------------------------------------------------------------------------
16
+ // toolkit/content/jar.mn — widget registration
17
+ // ---------------------------------------------------------------------------
18
+ /**
19
+ * Registers a widget file (mjs or css) in toolkit/content/jar.mn.
20
+ *
21
+ * Entry format (3-space indent):
22
+ * content/global/elements/{file} (widgets/{tagName}/{file})
23
+ */
24
+ export async function registerToolkitWidget(engineDir, tagName, fileName, dryRun = false) {
25
+ const manifest = 'toolkit/content/jar.mn';
26
+ const manifestPath = join(engineDir, manifest);
27
+ if (!(await pathExists(manifestPath))) {
28
+ throw new GeneralError(`Manifest not found: ${manifest}`);
29
+ }
30
+ const entry = ` content/global/elements/${fileName} (widgets/${tagName}/${fileName})`.replace(/\\/g, '/');
31
+ let content = await readText(manifestPath);
32
+ // Idempotency check
33
+ if (content.includes(`content/global/elements/${fileName}`)) {
34
+ return { manifest, entry, skipped: true };
35
+ }
36
+ const lines = content.split('\n');
37
+ // Find insertion point among existing content/global/elements/ lines
38
+ const extractKey = (line) => {
39
+ const match = /^\s+content\/global\/elements\/([^\s]+)/.exec(line);
40
+ return match?.[1];
41
+ };
42
+ let sectionStart = -1;
43
+ let sectionEnd = lines.length;
44
+ for (let i = 0; i < lines.length; i++) {
45
+ const line = lines[i];
46
+ if (line === undefined)
47
+ continue;
48
+ if (/^\s+content\/global\/elements\//.test(line)) {
49
+ if (sectionStart === -1)
50
+ sectionStart = i;
51
+ sectionEnd = i + 1;
52
+ }
53
+ }
54
+ if (sectionStart === -1) {
55
+ throw new GeneralError('Could not find content/global/elements/ section in toolkit/content/jar.mn');
56
+ }
57
+ const { insertIndex, previousEntry } = findAlphabeticalPosition(lines, sectionStart, sectionEnd, fileName, extractKey);
58
+ lines.splice(insertIndex, 0, entry);
59
+ content = lines.join('\n');
60
+ if (!dryRun) {
61
+ await writeText(manifestPath, content);
62
+ }
63
+ return { manifest, entry, previousEntry, skipped: false };
64
+ }
65
+ //# sourceMappingURL=manifest-register.js.map
@@ -0,0 +1,39 @@
1
+ import type { RegisterResult } from './manifest-register.js';
2
+ /** Pattern rules mapping file paths to manifest types */
3
+ export interface PatternRule {
4
+ /** Regex to match the file path (relative to engine/) */
5
+ pattern: RegExp;
6
+ /** Checks whether the file is already registered in its manifest */
7
+ isRegistered: (engineDir: string, ...args: string[]) => Promise<boolean>;
8
+ /** Register function */
9
+ register: (engineDir: string, after: string | undefined, dryRun: boolean, ...args: string[]) => Promise<RegisterResult>;
10
+ /** Extract arguments from the regex match */
11
+ extractArgs: (match: RegExpMatchArray) => string[];
12
+ }
13
+ /** Returns manifest registration rules for the supported engine file patterns. */
14
+ export declare function getRules(binaryName: string): PatternRule[];
15
+ /**
16
+ * Checks if a file path matches any known registrable pattern.
17
+ * @param filePath - Path relative to engine/
18
+ * @param binaryName - Binary name from fireforge.json (used for module directory)
19
+ * @returns True if the file matches a known registration pattern
20
+ */
21
+ export declare function matchesRegistrablePattern(filePath: string, binaryName: string): boolean;
22
+ /**
23
+ * Checks whether a supported registrable file is already present in its manifest.
24
+ *
25
+ * @param root - Project root directory
26
+ * @param filePath - Path relative to engine/
27
+ * @returns True if the file is already registered in its manifest
28
+ */
29
+ export declare function isFileRegistered(root: string, filePath: string): Promise<boolean>;
30
+ /**
31
+ * Registers a file in the appropriate build manifest.
32
+ *
33
+ * @param root - Project root directory
34
+ * @param filePath - Path relative to engine/
35
+ * @param dryRun - If true, return what would be done without writing
36
+ * @param after - Optional substring to place entry after (instead of alphabetical)
37
+ * @returns Registration result
38
+ */
39
+ export declare function registerFile(root: string, filePath: string, dryRun?: boolean, after?: string): Promise<RegisterResult>;
@@ -0,0 +1,151 @@
1
+ // SPDX-License-Identifier: EUPL-1.2
2
+ import { basename, join } from 'node:path';
3
+ import { GeneralError, InvalidArgumentError } from '../errors/base.js';
4
+ import { pathExists, readText } from '../utils/fs.js';
5
+ import { escapeRegex } from '../utils/regex.js';
6
+ import { getProjectPaths, loadConfig } from './config.js';
7
+ import { registerBrowserContent, registerFireForgeModule, registerSharedCSS, registerTestManifest, registerToolkitWidget, } from './manifest-register.js';
8
+ /** Returns manifest registration rules for the supported engine file patterns. */
9
+ export function getRules(binaryName) {
10
+ const moduleDir = `browser/modules/${binaryName}`;
11
+ return [
12
+ {
13
+ pattern: /^browser\/themes\/shared\/(.+\.css)$/,
14
+ isRegistered: (engineDir, fileName) => isSharedCSSRegistered(engineDir, fileName),
15
+ register: (engineDir, after, dryRun, fileName) => registerSharedCSS(engineDir, fileName, after, dryRun),
16
+ extractArgs: (m) => [m[1] ?? ''],
17
+ },
18
+ {
19
+ pattern: /^browser\/base\/content\/(.+\.(?:js|mjs))$/,
20
+ isRegistered: (engineDir, fileName) => isBrowserContentRegistered(engineDir, fileName),
21
+ register: (engineDir, after, dryRun, fileName) => registerBrowserContent(engineDir, fileName, after, undefined, dryRun),
22
+ extractArgs: (m) => [m[1] ?? ''],
23
+ },
24
+ {
25
+ pattern: /^browser\/base\/content\/test\/([^/]+)\/browser\.toml$/,
26
+ isRegistered: (_engineDir, testDir) => isTestManifestRegistered(_engineDir, testDir),
27
+ register: (_engineDir, _after, dryRun, testDir) => registerTestManifest(_engineDir, testDir, dryRun),
28
+ extractArgs: (m) => [m[1] ?? ''],
29
+ },
30
+ {
31
+ pattern: new RegExp(`^browser/modules/${escapeRegex(binaryName)}/(.+\\.sys\\.mjs)$`),
32
+ isRegistered: (_engineDir, fileName) => isFireForgeModuleRegistered(_engineDir, fileName, moduleDir),
33
+ register: (_engineDir, _after, dryRun, fileName) => registerFireForgeModule(_engineDir, fileName, moduleDir, dryRun),
34
+ extractArgs: (m) => [m[1] ?? ''],
35
+ },
36
+ {
37
+ pattern: /^toolkit\/content\/widgets\/([^/]+)\/(.+\.(?:mjs|css))$/,
38
+ isRegistered: (_engineDir, tagName, fileName) => isToolkitWidgetRegistered(_engineDir, tagName, fileName),
39
+ register: (_engineDir, _after, dryRun, tagName, fileName) => registerToolkitWidget(_engineDir, tagName, fileName, dryRun),
40
+ extractArgs: (m) => [m[1] ?? '', m[2] ?? ''],
41
+ },
42
+ ];
43
+ }
44
+ async function isSharedCSSRegistered(engineDir, fileName) {
45
+ const manifestPath = join(engineDir, 'browser/themes/shared/jar.inc.mn');
46
+ if (!(await pathExists(manifestPath))) {
47
+ throw new GeneralError('Manifest not found: browser/themes/shared/jar.inc.mn');
48
+ }
49
+ const name = basename(fileName, '.css');
50
+ const content = await readText(manifestPath);
51
+ return content.includes(`skin/classic/browser/${name}.css`);
52
+ }
53
+ async function isBrowserContentRegistered(engineDir, fileName) {
54
+ const manifestPath = join(engineDir, 'browser/base/jar.mn');
55
+ if (!(await pathExists(manifestPath))) {
56
+ throw new GeneralError('Manifest not found: browser/base/jar.mn');
57
+ }
58
+ const content = await readText(manifestPath);
59
+ return content.includes(`content/browser/${fileName}`);
60
+ }
61
+ async function isTestManifestRegistered(engineDir, testDir) {
62
+ const manifestPath = join(engineDir, 'browser/base/moz.build');
63
+ if (!(await pathExists(manifestPath))) {
64
+ throw new GeneralError('Manifest not found: browser/base/moz.build');
65
+ }
66
+ const content = await readText(manifestPath);
67
+ return content.includes(`content/test/${testDir}/browser.toml`);
68
+ }
69
+ async function isFireForgeModuleRegistered(engineDir, fileName, moduleDir) {
70
+ const manifestPath = join(engineDir, moduleDir, 'moz.build');
71
+ if (!(await pathExists(manifestPath))) {
72
+ throw new GeneralError(`Manifest not found: ${moduleDir}/moz.build`);
73
+ }
74
+ const content = await readText(manifestPath);
75
+ return content.includes(`"${fileName}"`);
76
+ }
77
+ async function isToolkitWidgetRegistered(engineDir, _tagName, fileName) {
78
+ const manifestPath = join(engineDir, 'toolkit/content/jar.mn');
79
+ if (!(await pathExists(manifestPath))) {
80
+ throw new GeneralError('Manifest not found: toolkit/content/jar.mn');
81
+ }
82
+ const content = await readText(manifestPath);
83
+ return content.includes(`content/global/elements/${fileName}`);
84
+ }
85
+ /**
86
+ * Checks if a file path matches any known registrable pattern.
87
+ * @param filePath - Path relative to engine/
88
+ * @param binaryName - Binary name from fireforge.json (used for module directory)
89
+ * @returns True if the file matches a known registration pattern
90
+ */
91
+ export function matchesRegistrablePattern(filePath, binaryName) {
92
+ const normalized = filePath.replace(/\\/g, '/');
93
+ const rules = getRules(binaryName);
94
+ return rules.some((rule) => rule.pattern.test(normalized));
95
+ }
96
+ /**
97
+ * Checks whether a supported registrable file is already present in its manifest.
98
+ *
99
+ * @param root - Project root directory
100
+ * @param filePath - Path relative to engine/
101
+ * @returns True if the file is already registered in its manifest
102
+ */
103
+ export async function isFileRegistered(root, filePath) {
104
+ const { engine: engineDir } = getProjectPaths(root);
105
+ const config = await loadConfig(root);
106
+ const rules = getRules(config.binaryName);
107
+ const normalizedPath = filePath.replace(/\\/g, '/');
108
+ for (const rule of rules) {
109
+ const match = normalizedPath.match(rule.pattern);
110
+ if (match) {
111
+ const args = rule.extractArgs(match);
112
+ return rule.isRegistered(engineDir, ...args);
113
+ }
114
+ }
115
+ throw new InvalidArgumentError(`Unknown file pattern: "${normalizedPath}". Supported patterns:\n` +
116
+ ' browser/themes/shared/*.css\n' +
117
+ ' browser/base/content/*.js\n' +
118
+ ' browser/base/content/test/*/browser.toml\n' +
119
+ ` browser/modules/${config.binaryName}/*.sys.mjs\n` +
120
+ ' toolkit/content/widgets/*/*.{mjs,css}', 'path');
121
+ }
122
+ /**
123
+ * Registers a file in the appropriate build manifest.
124
+ *
125
+ * @param root - Project root directory
126
+ * @param filePath - Path relative to engine/
127
+ * @param dryRun - If true, return what would be done without writing
128
+ * @param after - Optional substring to place entry after (instead of alphabetical)
129
+ * @returns Registration result
130
+ */
131
+ export async function registerFile(root, filePath, dryRun = false, after) {
132
+ const { engine: engineDir } = getProjectPaths(root);
133
+ const config = await loadConfig(root);
134
+ const rules = getRules(config.binaryName);
135
+ // Normalize path separators
136
+ const normalizedPath = filePath.replace(/\\/g, '/');
137
+ for (const rule of rules) {
138
+ const match = normalizedPath.match(rule.pattern);
139
+ if (match) {
140
+ const args = rule.extractArgs(match);
141
+ return rule.register(engineDir, after, dryRun, ...args);
142
+ }
143
+ }
144
+ throw new InvalidArgumentError(`Unknown file pattern: "${normalizedPath}". Supported patterns:\n` +
145
+ ' browser/themes/shared/*.css\n' +
146
+ ' browser/base/content/*.js\n' +
147
+ ' browser/base/content/test/*/browser.toml\n' +
148
+ ` browser/modules/${config.binaryName}/*.sys.mjs\n` +
149
+ ' toolkit/content/widgets/*/*.{mjs,css}', 'path');
150
+ }
151
+ //# sourceMappingURL=manifest-rules.js.map
@@ -0,0 +1,34 @@
1
+ /** Token for jar.mn / jar.inc.mn files */
2
+ export interface JarMnToken {
3
+ type: 'header' | 'directive' | 'entry' | 'empty' | 'comment';
4
+ raw: string;
5
+ lineIndex: number;
6
+ parsed?: {
7
+ target: string;
8
+ source: string;
9
+ } | undefined;
10
+ }
11
+ /** Token for moz.build Python-style list blocks */
12
+ export interface MozBuildToken {
13
+ type: 'list-open' | 'list-item' | 'list-close' | 'other';
14
+ raw: string;
15
+ lineIndex: number;
16
+ parsed?: {
17
+ value: string;
18
+ } | undefined;
19
+ }
20
+ /**
21
+ * Tokenizes a jar.mn file into structured tokens.
22
+ * Recognizes headers, `%` directives, entries with (source) paths,
23
+ * comments, and blank lines.
24
+ */
25
+ export declare function tokenizeJarMn(lines: string[]): JarMnToken[];
26
+ /**
27
+ * Tokenizes a moz.build Python list block, returning the tokens and their
28
+ * line range within the file.
29
+ */
30
+ export declare function tokenizeMozBuildList(lines: string[], listPattern: RegExp): {
31
+ tokens: MozBuildToken[];
32
+ startLine: number;
33
+ endLine: number;
34
+ } | null;
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Tokenizes a jar.mn file into structured tokens.
3
+ * Recognizes headers, `%` directives, entries with (source) paths,
4
+ * comments, and blank lines.
5
+ */
6
+ export function tokenizeJarMn(lines) {
7
+ const tokens = [];
8
+ for (let i = 0; i < lines.length; i++) {
9
+ const raw = lines[i] ?? '';
10
+ const trimmed = raw.trim();
11
+ if (trimmed === '') {
12
+ tokens.push({ type: 'empty', raw, lineIndex: i });
13
+ continue;
14
+ }
15
+ if (trimmed.startsWith('#')) {
16
+ tokens.push({ type: 'comment', raw, lineIndex: i });
17
+ continue;
18
+ }
19
+ if (trimmed.startsWith('%')) {
20
+ tokens.push({ type: 'directive', raw, lineIndex: i });
21
+ continue;
22
+ }
23
+ // Entries with source paths: " target/path (source/path)" or "target/path (source/path)"
24
+ const entryMatch = /^(\s*)(\S+)\s+\(([^)]+)\)/.exec(raw);
25
+ if (entryMatch) {
26
+ tokens.push({
27
+ type: 'entry',
28
+ raw,
29
+ lineIndex: i,
30
+ parsed: { target: entryMatch[2] ?? '', source: entryMatch[3] ?? '' },
31
+ });
32
+ continue;
33
+ }
34
+ // Non-indented lines without (source) are headers (e.g., "browser.jar:" or Python assignment)
35
+ if (/^\S.*[:+=]/.test(raw)) {
36
+ tokens.push({ type: 'header', raw, lineIndex: i });
37
+ continue;
38
+ }
39
+ // Fallback: treat indented lines without (source) as entries
40
+ tokens.push({ type: 'entry', raw, lineIndex: i });
41
+ }
42
+ return tokens;
43
+ }
44
+ /**
45
+ * Tokenizes a moz.build Python list block, returning the tokens and their
46
+ * line range within the file.
47
+ */
48
+ export function tokenizeMozBuildList(lines, listPattern) {
49
+ const tokens = [];
50
+ let startLine = -1;
51
+ let endLine = -1;
52
+ for (let i = 0; i < lines.length; i++) {
53
+ const raw = lines[i] ?? '';
54
+ if (startLine === -1) {
55
+ if (listPattern.test(raw)) {
56
+ startLine = i;
57
+ tokens.push({ type: 'list-open', raw, lineIndex: i });
58
+ }
59
+ continue;
60
+ }
61
+ // Inside the list block
62
+ if (/^\s*\]/.test(raw)) {
63
+ endLine = i;
64
+ tokens.push({ type: 'list-close', raw, lineIndex: i });
65
+ break;
66
+ }
67
+ const itemMatch = /^\s+["']([^"']+)["']/.exec(raw);
68
+ if (itemMatch) {
69
+ tokens.push({
70
+ type: 'list-item',
71
+ raw,
72
+ lineIndex: i,
73
+ parsed: { value: itemMatch[1] ?? '' },
74
+ });
75
+ }
76
+ else {
77
+ tokens.push({ type: 'other', raw, lineIndex: i });
78
+ }
79
+ }
80
+ if (startLine === -1 || endLine === -1)
81
+ return null;
82
+ return { tokens, startLine, endLine };
83
+ }
84
+ //# sourceMappingURL=manifest-tokenizers.js.map
@@ -0,0 +1,36 @@
1
+ export interface ParserFallbackEvent {
2
+ context: string;
3
+ reason: string;
4
+ }
5
+ /** Returns recorded parser fallback events without clearing the event buffer. */
6
+ export declare function peekParserFallbackEvents(): ParserFallbackEvent[];
7
+ /** Returns and clears the recorded parser fallback events. */
8
+ export declare function consumeParserFallbackEvents(): ParserFallbackEvent[];
9
+ /**
10
+ * Result of a parser-with-fallback invocation, carrying both the computed
11
+ * value and metadata about which code path produced it.
12
+ */
13
+ export interface ParserResult<T> {
14
+ /** The computed value (from either the primary or fallback path). */
15
+ value: T;
16
+ /** True when the primary parser failed and the fallback was used. */
17
+ usedFallback: boolean;
18
+ /** The error that caused the primary parser to fail (undefined when primary succeeded). */
19
+ fallbackReason?: string;
20
+ }
21
+ /**
22
+ * Wraps a primary (AST/tokenizer) parser with a legacy (regex/line-based)
23
+ * fallback. If the primary throws, a warning is logged and the fallback is
24
+ * used instead.
25
+ *
26
+ * Returns a {@link ParserResult} so callers (and tests) can detect which
27
+ * code path was taken and surface it in logs or assertions.
28
+ *
29
+ * @param primary - The modern parser implementation
30
+ * @param fallback - The legacy fallback implementation
31
+ * @param context - File/context name used in the warning message
32
+ * @param rethrowIf - Optional predicate; if it returns true for the caught
33
+ * error the error is re-thrown instead of falling back (useful for
34
+ * domain-specific errors that should not be swallowed).
35
+ */
36
+ export declare function withParserFallback<T>(primary: () => T, fallback: () => T, context: string, rethrowIf?: (error: unknown) => boolean): ParserResult<T>;
@@ -0,0 +1,43 @@
1
+ // SPDX-License-Identifier: EUPL-1.2
2
+ import { toError } from '../utils/errors.js';
3
+ import { warn } from '../utils/logger.js';
4
+ const parserFallbackEvents = [];
5
+ /** Returns recorded parser fallback events without clearing the event buffer. */
6
+ export function peekParserFallbackEvents() {
7
+ return [...parserFallbackEvents];
8
+ }
9
+ /** Returns and clears the recorded parser fallback events. */
10
+ export function consumeParserFallbackEvents() {
11
+ const events = [...parserFallbackEvents];
12
+ parserFallbackEvents.length = 0;
13
+ return events;
14
+ }
15
+ /**
16
+ * Wraps a primary (AST/tokenizer) parser with a legacy (regex/line-based)
17
+ * fallback. If the primary throws, a warning is logged and the fallback is
18
+ * used instead.
19
+ *
20
+ * Returns a {@link ParserResult} so callers (and tests) can detect which
21
+ * code path was taken and surface it in logs or assertions.
22
+ *
23
+ * @param primary - The modern parser implementation
24
+ * @param fallback - The legacy fallback implementation
25
+ * @param context - File/context name used in the warning message
26
+ * @param rethrowIf - Optional predicate; if it returns true for the caught
27
+ * error the error is re-thrown instead of falling back (useful for
28
+ * domain-specific errors that should not be swallowed).
29
+ */
30
+ export function withParserFallback(primary, fallback, context, rethrowIf) {
31
+ try {
32
+ return { value: primary(), usedFallback: false };
33
+ }
34
+ catch (error) {
35
+ if (rethrowIf?.(error))
36
+ throw error;
37
+ const reason = toError(error).message;
38
+ parserFallbackEvents.push({ context, reason });
39
+ warn(`AST/tokenizer parsing failed for ${context}, falling back to legacy. Error: ${reason}`);
40
+ return { value: fallback(), usedFallback: true, fallbackReason: reason };
41
+ }
42
+ }
43
+ //# sourceMappingURL=parser-fallback.js.map
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Fuzzy patch application with escalating fuzz factors.
3
+ *
4
+ * Tries an exact `git apply` first, then retries with increasing `--fuzz=N`
5
+ * values. If all fuzz levels fail, falls through to `git apply --reject`
6
+ * so the user gets `.rej` files for manual resolution.
7
+ */
8
+ export interface FuzzyApplyResult {
9
+ /** Whether the patch was applied successfully. */
10
+ success: boolean;
11
+ /** Fuzz factor that succeeded (0 = exact match). */
12
+ fuzzFactor: number;
13
+ /** Error description when `success` is false. */
14
+ error?: string;
15
+ /** List of `.rej` files created (when falling through to --reject). */
16
+ rejectFiles?: string[];
17
+ }
18
+ /**
19
+ * Attempts to apply a patch with escalating fuzz factors.
20
+ *
21
+ * 1. `git apply --check` at fuzz 0 … maxFuzz
22
+ * 2. `git apply --fuzz=N` at the first passing level
23
+ * 3. Fall through to `git apply --reject` if nothing succeeds
24
+ *
25
+ * @param patchPath - Absolute path to the `.patch` file
26
+ * @param engineDir - Working directory (engine/)
27
+ * @param maxFuzz - Maximum fuzz factor to try (default 3)
28
+ */
29
+ export declare function applyPatchWithFuzz(patchPath: string, engineDir: string, maxFuzz?: number): Promise<FuzzyApplyResult>;