@hominis/fireforge 0.10.1 → 0.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +93 -1
- package/README.md +125 -238
- package/dist/bin/fireforge.js +26 -0
- package/dist/src/cli.d.ts +1 -1
- package/dist/src/cli.js +131 -52
- package/dist/src/commands/bootstrap.js +6 -2
- package/dist/src/commands/build.js +4 -2
- package/dist/src/commands/discard.js +16 -4
- package/dist/src/commands/doctor-furnace.d.ts +8 -0
- package/dist/src/commands/doctor-furnace.js +422 -0
- package/dist/src/commands/doctor.d.ts +115 -0
- package/dist/src/commands/doctor.js +327 -258
- package/dist/src/commands/download.js +16 -1
- package/dist/src/commands/export-all.js +15 -0
- package/dist/src/commands/export-flow.d.ts +91 -0
- package/dist/src/commands/export-flow.js +344 -0
- package/dist/src/commands/export.js +151 -5
- package/dist/src/commands/furnace/apply.d.ts +3 -2
- package/dist/src/commands/furnace/apply.js +169 -36
- package/dist/src/commands/furnace/create.js +162 -52
- package/dist/src/commands/furnace/deploy.js +156 -144
- package/dist/src/commands/furnace/diff.d.ts +8 -4
- package/dist/src/commands/furnace/diff.js +142 -73
- package/dist/src/commands/furnace/index.d.ts +6 -2
- package/dist/src/commands/furnace/index.js +76 -25
- package/dist/src/commands/furnace/init.d.ts +11 -0
- package/dist/src/commands/furnace/init.js +76 -0
- package/dist/src/commands/furnace/list.d.ts +4 -1
- package/dist/src/commands/furnace/list.js +35 -3
- package/dist/src/commands/furnace/override.d.ts +8 -0
- package/dist/src/commands/furnace/override.js +216 -26
- package/dist/src/commands/furnace/preview.js +184 -30
- package/dist/src/commands/furnace/refresh.d.ts +10 -0
- package/dist/src/commands/furnace/refresh.js +268 -0
- package/dist/src/commands/furnace/remove.js +285 -89
- package/dist/src/commands/furnace/rename.d.ts +5 -0
- package/dist/src/commands/furnace/rename.js +308 -0
- package/dist/src/commands/furnace/scan.d.ts +4 -1
- package/dist/src/commands/furnace/scan.js +72 -11
- package/dist/src/commands/furnace/status.js +85 -20
- package/dist/src/commands/furnace/sync.d.ts +12 -0
- package/dist/src/commands/furnace/sync.js +77 -0
- package/dist/src/commands/furnace/validate.d.ts +4 -1
- package/dist/src/commands/furnace/validate.js +99 -3
- package/dist/src/commands/furnace/validation-output.d.ts +24 -1
- package/dist/src/commands/furnace/validation-output.js +93 -1
- package/dist/src/commands/import.js +37 -4
- package/dist/src/commands/lint.js +11 -2
- package/dist/src/commands/manifest.d.ts +39 -0
- package/dist/src/commands/manifest.js +59 -0
- package/dist/src/commands/patch/delete.d.ts +28 -0
- package/dist/src/commands/patch/delete.js +209 -0
- package/dist/src/commands/patch/index.d.ts +17 -0
- package/dist/src/commands/patch/index.js +25 -0
- package/dist/src/commands/patch/reorder.d.ts +30 -0
- package/dist/src/commands/patch/reorder.js +377 -0
- package/dist/src/commands/re-export-files.d.ts +17 -0
- package/dist/src/commands/re-export-files.js +177 -0
- package/dist/src/commands/re-export.js +44 -0
- package/dist/src/commands/rebase/abort.d.ts +1 -1
- package/dist/src/commands/rebase/abort.js +12 -3
- package/dist/src/commands/rebase/confirm.d.ts +3 -3
- package/dist/src/commands/rebase/confirm.js +4 -4
- package/dist/src/commands/rebase/index.js +13 -4
- package/dist/src/commands/reset.js +20 -4
- package/dist/src/commands/run.js +46 -1
- package/dist/src/commands/setup-support.js +6 -5
- package/dist/src/commands/status.js +97 -6
- package/dist/src/commands/test.js +5 -37
- package/dist/src/commands/verify.d.ts +31 -0
- package/dist/src/commands/verify.js +126 -0
- package/dist/src/core/build-prepare.js +40 -16
- package/dist/src/core/destructive.d.ts +96 -0
- package/dist/src/core/destructive.js +137 -0
- package/dist/src/core/diff-hunks.d.ts +73 -0
- package/dist/src/core/diff-hunks.js +268 -0
- package/dist/src/core/firefox.d.ts +1 -1
- package/dist/src/core/firefox.js +1 -1
- package/dist/src/core/furnace-apply-helpers.d.ts +89 -6
- package/dist/src/core/furnace-apply-helpers.js +302 -57
- package/dist/src/core/furnace-apply-output.d.ts +16 -0
- package/dist/src/core/furnace-apply-output.js +57 -0
- package/dist/src/core/furnace-apply.d.ts +21 -3
- package/dist/src/core/furnace-apply.js +260 -29
- package/dist/src/core/furnace-checksum-utils.d.ts +4 -0
- package/dist/src/core/furnace-checksum-utils.js +24 -0
- package/dist/src/core/furnace-config.d.ts +28 -1
- package/dist/src/core/furnace-config.js +180 -17
- package/dist/src/core/furnace-constants.d.ts +22 -0
- package/dist/src/core/furnace-constants.js +36 -0
- package/dist/src/core/furnace-graph-utils.d.ts +11 -0
- package/dist/src/core/furnace-graph-utils.js +94 -0
- package/dist/src/core/furnace-operation.d.ts +108 -0
- package/dist/src/core/furnace-operation.js +220 -0
- package/dist/src/core/furnace-refresh.d.ts +20 -0
- package/dist/src/core/furnace-refresh.js +118 -0
- package/dist/src/core/furnace-registration-ast.d.ts +5 -0
- package/dist/src/core/furnace-registration-ast.js +134 -4
- package/dist/src/core/furnace-registration-remove.d.ts +25 -3
- package/dist/src/core/furnace-registration-remove.js +196 -62
- package/dist/src/core/furnace-registration-validate.d.ts +13 -1
- package/dist/src/core/furnace-registration-validate.js +15 -3
- package/dist/src/core/furnace-registration.d.ts +27 -4
- package/dist/src/core/furnace-registration.js +93 -11
- package/dist/src/core/furnace-rollback.d.ts +11 -0
- package/dist/src/core/furnace-rollback.js +78 -7
- package/dist/src/core/furnace-scanner.d.ts +8 -2
- package/dist/src/core/furnace-scanner.js +152 -55
- package/dist/src/core/furnace-stories.js +7 -5
- package/dist/src/core/furnace-validate-accessibility.js +7 -1
- package/dist/src/core/furnace-validate-compatibility.d.ts +1 -1
- package/dist/src/core/furnace-validate-compatibility.js +85 -1
- package/dist/src/core/furnace-validate-helpers.d.ts +4 -0
- package/dist/src/core/furnace-validate-helpers.js +31 -0
- package/dist/src/core/furnace-validate-registration.d.ts +17 -2
- package/dist/src/core/furnace-validate-registration.js +73 -3
- package/dist/src/core/furnace-validate-structure.d.ts +10 -2
- package/dist/src/core/furnace-validate-structure.js +45 -3
- package/dist/src/core/furnace-validate.d.ts +10 -1
- package/dist/src/core/furnace-validate.js +80 -6
- package/dist/src/core/furnace-version-drift.d.ts +55 -0
- package/dist/src/core/furnace-version-drift.js +101 -0
- package/dist/src/core/git-file-ops.d.ts +8 -0
- package/dist/src/core/git-file-ops.js +19 -6
- package/dist/src/core/lint-projection.d.ts +25 -0
- package/dist/src/core/lint-projection.js +44 -0
- package/dist/src/core/mach.d.ts +4 -2
- package/dist/src/core/mach.js +17 -2
- package/dist/src/core/markdown-table.d.ts +104 -0
- package/dist/src/core/markdown-table.js +266 -0
- package/dist/src/core/ownership-table.d.ts +53 -0
- package/dist/src/core/ownership-table.js +144 -0
- package/dist/src/core/patch-apply.d.ts +17 -3
- package/dist/src/core/patch-apply.js +86 -8
- package/dist/src/core/patch-export.d.ts +119 -5
- package/dist/src/core/patch-export.js +183 -25
- package/dist/src/core/patch-lint-cross.d.ts +195 -0
- package/dist/src/core/patch-lint-cross.js +428 -0
- package/dist/src/core/patch-lint-diff.d.ts +33 -0
- package/dist/src/core/patch-lint-diff.js +84 -0
- package/dist/src/core/patch-lint.d.ts +2 -4
- package/dist/src/core/patch-lint.js +12 -50
- package/dist/src/core/patch-lock.js +2 -1
- package/dist/src/core/patch-manifest-io.d.ts +102 -1
- package/dist/src/core/patch-manifest-io.js +270 -2
- package/dist/src/core/patch-manifest-query.d.ts +1 -1
- package/dist/src/core/patch-manifest-query.js +1 -1
- package/dist/src/core/patch-manifest.d.ts +1 -1
- package/dist/src/core/patch-manifest.js +1 -1
- package/dist/src/core/patch-transform.d.ts +12 -0
- package/dist/src/core/patch-transform.js +21 -7
- package/dist/src/core/token-manager.js +67 -69
- package/dist/src/core/wire-destroy.js +6 -3
- package/dist/src/core/wire-init.js +10 -4
- package/dist/src/core/wire-subscript.js +9 -3
- package/dist/src/core/wire-utils.d.ts +52 -5
- package/dist/src/core/wire-utils.js +69 -6
- package/dist/src/errors/base.d.ts +20 -0
- package/dist/src/errors/base.js +24 -0
- package/dist/src/errors/furnace.js +7 -1
- package/dist/src/errors/rebase.js +6 -1
- package/dist/src/types/commands/index.d.ts +1 -1
- package/dist/src/types/commands/options.d.ts +125 -4
- package/dist/src/types/commands/patches.d.ts +11 -1
- package/dist/src/types/config.d.ts +1 -1
- package/dist/src/types/furnace.d.ts +55 -1
- package/dist/src/utils/fs.d.ts +12 -0
- package/dist/src/utils/fs.js +30 -1
- package/dist/src/utils/package-root.d.ts +5 -0
- package/dist/src/utils/package-root.js +12 -0
- package/dist/src/utils/process.js +9 -4
- package/dist/src/utils/validation.d.ts +20 -2
- package/dist/src/utils/validation.js +26 -3
- package/package.json +1 -1
|
@@ -7,16 +7,18 @@ import { PatchError } from '../errors/patch.js';
|
|
|
7
7
|
import { readText } from '../utils/fs.js';
|
|
8
8
|
import { isNewFileInPatch, parseHunksForFile } from './patch-parse.js';
|
|
9
9
|
/**
|
|
10
|
-
* Extracts the complete file content from a "new file" patch
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
10
|
+
* Extracts the complete file content from a "new file" patch given a raw
|
|
11
|
+
* diff string already in memory. Callers with a patch file path should
|
|
12
|
+
* prefer {@link extractNewFileContent}; this helper exists for code paths
|
|
13
|
+
* that already hold the diff (e.g. the in-flight export planner) and do
|
|
14
|
+
* not want to round-trip through the filesystem.
|
|
15
|
+
*
|
|
16
|
+
* @param diff - Raw unified-diff content
|
|
14
17
|
* @param targetFile - Optional target file to scope extraction to
|
|
15
18
|
* @returns The file content that the patch would create
|
|
16
19
|
*/
|
|
17
|
-
export
|
|
18
|
-
const
|
|
19
|
-
const lines = content.split('\n');
|
|
20
|
+
export function extractNewFileContentFromDiff(diff, targetFile) {
|
|
21
|
+
const lines = diff.split('\n');
|
|
20
22
|
const contentLines = [];
|
|
21
23
|
let inHunk = false;
|
|
22
24
|
let inTargetFile = !targetFile; // If no targetFile, accept all sections
|
|
@@ -60,6 +62,18 @@ export async function extractNewFileContent(patchPath, targetFile) {
|
|
|
60
62
|
const result = contentLines.join('\n');
|
|
61
63
|
return hasNoNewlineMarker ? result : result + '\n';
|
|
62
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* Extracts the complete file content from a "new file" patch.
|
|
67
|
+
* When targetFile is provided, only extracts content for that file
|
|
68
|
+
* (required for multi-file patches).
|
|
69
|
+
* @param patchPath - Path to the patch file
|
|
70
|
+
* @param targetFile - Optional target file to scope extraction to
|
|
71
|
+
* @returns The file content that the patch would create
|
|
72
|
+
*/
|
|
73
|
+
export async function extractNewFileContent(patchPath, targetFile) {
|
|
74
|
+
const content = await readText(patchPath);
|
|
75
|
+
return extractNewFileContentFromDiff(content, targetFile);
|
|
76
|
+
}
|
|
63
77
|
/**
|
|
64
78
|
* Applies a patch's changes to content.
|
|
65
79
|
* @param content - Original content (null for new files)
|
|
@@ -9,6 +9,7 @@ import { escapeRegex } from '../utils/regex.js';
|
|
|
9
9
|
import { validateTokenName } from '../utils/validation.js';
|
|
10
10
|
import { getProjectPaths, loadConfig } from './config.js';
|
|
11
11
|
import { loadFurnaceConfig } from './furnace-config.js';
|
|
12
|
+
import { findTableAfterHeading, findTableByColumns, insertRow, rewriteTableRows, updateCellByKey, } from './markdown-table.js';
|
|
12
13
|
/** Returns the token CSS path relative to engine root for a given binary name. */
|
|
13
14
|
export function getTokensCssPath(binaryName) {
|
|
14
15
|
return `browser/themes/shared/${binaryName}-tokens.css`;
|
|
@@ -290,7 +291,27 @@ async function addTokenToCSS(engineDir, options, tokensCssPath) {
|
|
|
290
291
|
return true;
|
|
291
292
|
}
|
|
292
293
|
/**
|
|
293
|
-
*
|
|
294
|
+
* Strips surrounding backticks from a cell, if present. Token cells are
|
|
295
|
+
* usually wrapped in inline code fences (`` `--foo` ``) and the parser
|
|
296
|
+
* returns them verbatim.
|
|
297
|
+
*/
|
|
298
|
+
function stripInlineCode(cell) {
|
|
299
|
+
const trimmed = cell.trim();
|
|
300
|
+
if (trimmed.startsWith('`') && trimmed.endsWith('`') && trimmed.length >= 2) {
|
|
301
|
+
return trimmed.slice(1, -1);
|
|
302
|
+
}
|
|
303
|
+
return trimmed;
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Adds a token row to the main token table, the unmapped table (for
|
|
307
|
+
* literal values), and bumps the mode count table. Each sub-update runs
|
|
308
|
+
* against a freshly parsed view of the document so that splice indices
|
|
309
|
+
* stay valid as rewrites are layered.
|
|
310
|
+
*
|
|
311
|
+
* The old implementation walked `split('\n')` by hand, detected rows by
|
|
312
|
+
* literal `|`-prefix, and used a whitespace-sensitive regex to increment
|
|
313
|
+
* the mode count. Switching to {@link findTableByColumns} and
|
|
314
|
+
* {@link updateCellByKey} removes those formatting traps.
|
|
294
315
|
*/
|
|
295
316
|
async function addTokenToDocs(engineDir, options) {
|
|
296
317
|
const filePath = join(engineDir, '..', TOKENS_DOC);
|
|
@@ -298,90 +319,67 @@ async function addTokenToDocs(engineDir, options) {
|
|
|
298
319
|
// Docs file is optional
|
|
299
320
|
return { docsAdded: false, unmappedAdded: false, countUpdated: false };
|
|
300
321
|
}
|
|
301
|
-
|
|
302
|
-
|
|
322
|
+
const originalContent = await readText(filePath);
|
|
323
|
+
let lines = originalContent.split('\n');
|
|
303
324
|
let docsAdded = false;
|
|
304
325
|
let unmappedAdded = false;
|
|
305
326
|
let countUpdated = false;
|
|
306
327
|
const annotation = getModeAnnotation(options.mode, options.value);
|
|
307
328
|
const isLiteral = !options.value.startsWith('var(');
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
//
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
!
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
if (cells[1] === '' || !cells[1]) {
|
|
327
|
-
lastRowInCategory = i;
|
|
329
|
+
const mapsTo = isLiteral ? '—' : options.value.replace(/var\(([^)]+)\)/, '$1');
|
|
330
|
+
const tokenCell = `\`${options.tokenName}\``;
|
|
331
|
+
const valueCell = `\`${options.value}\``;
|
|
332
|
+
// --- Main token table: Category | Token | Value | Maps to | Mode ---
|
|
333
|
+
const mainTable = findTableByColumns(lines, ['Category', 'Token', 'Value', 'Mode']);
|
|
334
|
+
if (mainTable) {
|
|
335
|
+
// The doc convention allows the Category cell to be blank on
|
|
336
|
+
// continuation rows that belong to the previous category. Group rows
|
|
337
|
+
// by carrying the last non-empty Category value forward.
|
|
338
|
+
let lastGroupRowIndex = -1;
|
|
339
|
+
let currentCategory = '';
|
|
340
|
+
for (let i = 0; i < mainTable.rows.length; i++) {
|
|
341
|
+
const row = mainTable.rows[i];
|
|
342
|
+
if (!row)
|
|
343
|
+
continue;
|
|
344
|
+
const cell = row[0]?.trim() ?? '';
|
|
345
|
+
if (cell) {
|
|
346
|
+
currentCategory = cell;
|
|
328
347
|
}
|
|
329
|
-
|
|
330
|
-
|
|
348
|
+
if (currentCategory === options.category) {
|
|
349
|
+
lastGroupRowIndex = i;
|
|
331
350
|
}
|
|
332
351
|
}
|
|
333
|
-
|
|
334
|
-
|
|
352
|
+
if (lastGroupRowIndex !== -1) {
|
|
353
|
+
insertRow(mainTable, ['', tokenCell, valueCell, mapsTo, annotation], lastGroupRowIndex + 1);
|
|
354
|
+
lines = rewriteTableRows(lines, mainTable);
|
|
355
|
+
docsAdded = true;
|
|
335
356
|
}
|
|
336
357
|
}
|
|
337
|
-
|
|
338
|
-
// Insert a new row after the last row in this category
|
|
339
|
-
const mapsTo = isLiteral ? '—' : options.value.replace(/var\(([^)]+)\)/, '$1');
|
|
340
|
-
const newRow = `| | \`${options.tokenName}\` | \`${options.value}\` | ${mapsTo} | ${annotation} |`;
|
|
341
|
-
lines.splice(lastRowInCategory + 1, 0, newRow);
|
|
342
|
-
docsAdded = true;
|
|
343
|
-
}
|
|
344
|
-
// If the value is a literal (not a var() reference), add to unmapped table
|
|
358
|
+
// --- Unmapped table: populated for literal (non-var()) values only ---
|
|
345
359
|
if (isLiteral) {
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
unmappedTableStart = i;
|
|
351
|
-
break;
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
if (unmappedTableStart !== -1) {
|
|
355
|
-
// Find the last row of the unmapped table
|
|
356
|
-
let lastUnmappedRow = unmappedTableStart;
|
|
357
|
-
for (let i = unmappedTableStart + 1; i < lines.length; i++) {
|
|
358
|
-
const line = lines[i] ?? '';
|
|
359
|
-
if (line.startsWith('|') && !line.startsWith('|--') && !line.startsWith('| Token')) {
|
|
360
|
-
lastUnmappedRow = i;
|
|
361
|
-
}
|
|
362
|
-
else if (!line.startsWith('|')) {
|
|
363
|
-
break;
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
const unmappedRow = `| \`${options.tokenName}\` | \`${options.value}\` | ${options.description ?? ''} |`;
|
|
367
|
-
lines.splice(lastUnmappedRow + 1, 0, unmappedRow);
|
|
360
|
+
const unmappedTable = findTableAfterHeading(lines, /not yet mapped|unmapped/i);
|
|
361
|
+
if (unmappedTable) {
|
|
362
|
+
insertRow(unmappedTable, [tokenCell, valueCell, options.description ?? ''], unmappedTable.rows.length);
|
|
363
|
+
lines = rewriteTableRows(lines, unmappedTable);
|
|
368
364
|
unmappedAdded = true;
|
|
369
365
|
}
|
|
370
366
|
}
|
|
371
|
-
//
|
|
372
|
-
const
|
|
373
|
-
|
|
374
|
-
const
|
|
375
|
-
const
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
367
|
+
// --- Mode behavior count table: Mode | Count ---
|
|
368
|
+
const modeTable = findTableByColumns(lines, ['Mode', 'Count']);
|
|
369
|
+
if (modeTable) {
|
|
370
|
+
const modeIndex = modeTable.headers.indexOf('Mode');
|
|
371
|
+
const countIndex = modeTable.headers.indexOf('Count');
|
|
372
|
+
const existing = modeTable.rows.find((row) => stripInlineCode(row[modeIndex] ?? '') === options.mode);
|
|
373
|
+
if (existing) {
|
|
374
|
+
const oldCount = parseInt(existing[countIndex] ?? '0', 10);
|
|
375
|
+
const updated = updateCellByKey(modeTable, 'Mode', existing[modeIndex] ?? options.mode, 'Count', String((Number.isNaN(oldCount) ? 0 : oldCount) + 1));
|
|
376
|
+
if (updated) {
|
|
377
|
+
lines = rewriteTableRows(lines, modeTable);
|
|
378
|
+
countUpdated = true;
|
|
379
|
+
}
|
|
381
380
|
}
|
|
382
381
|
}
|
|
383
|
-
|
|
384
|
-
await writeText(filePath, content);
|
|
382
|
+
await writeText(filePath, lines.join('\n'));
|
|
385
383
|
return { docsAdded, unmappedAdded, countUpdated };
|
|
386
384
|
}
|
|
387
385
|
//# sourceMappingURL=token-manager.js.map
|
|
@@ -10,7 +10,7 @@ import { pathExists, readText, writeText } from '../utils/fs.js';
|
|
|
10
10
|
import { escapeRegex } from '../utils/regex.js';
|
|
11
11
|
import { detectIndent, parseScript } from './ast-utils.js';
|
|
12
12
|
import { withParserFallback } from './parser-fallback.js';
|
|
13
|
-
import { extractNameFromExpression, findMethodBody, findMethodBraceIndex, validateWireName, } from './wire-utils.js';
|
|
13
|
+
import { assertBraceBalancePreserved, extractNameFromExpression, findMethodBody, findMethodBraceIndex, validateWireName, } from './wire-utils.js';
|
|
14
14
|
const BROWSER_INIT_JS = 'browser/base/content/browser-init.js';
|
|
15
15
|
/**
|
|
16
16
|
* AST-based implementation: finds onUnload()/uninit() method body and
|
|
@@ -57,7 +57,7 @@ export function legacyAddDestroy(content, expression) {
|
|
|
57
57
|
const name = extractNameFromExpression(expression);
|
|
58
58
|
const lines = content.split('\n');
|
|
59
59
|
const destroyRegex = /\b(?:async\s+)?(onUnload|uninit)\s*[(:]/;
|
|
60
|
-
const found = findMethodBraceIndex(lines, destroyRegex);
|
|
60
|
+
const found = findMethodBraceIndex(lines, destroyRegex, { requireBrace: true });
|
|
61
61
|
if (!found) {
|
|
62
62
|
throw new GeneralError('Could not find "onUnload" or "uninit" method in browser-init.js.\n' +
|
|
63
63
|
'FireForge was looking for a signature matching: \\b(?:async\\s+)?(onUnload|uninit)\\s*[(:]');
|
|
@@ -96,7 +96,10 @@ export async function addDestroyToBrowserInit(engineDir, expression) {
|
|
|
96
96
|
if (destroyPattern.test(content)) {
|
|
97
97
|
return false;
|
|
98
98
|
}
|
|
99
|
-
const { value } = withParserFallback(() => addDestroyAST(content, expression), () => legacyAddDestroy(content, expression), BROWSER_INIT_JS);
|
|
99
|
+
const { value, usedFallback } = withParserFallback(() => addDestroyAST(content, expression), () => legacyAddDestroy(content, expression), BROWSER_INIT_JS);
|
|
100
|
+
if (usedFallback) {
|
|
101
|
+
assertBraceBalancePreserved(content, value, BROWSER_INIT_JS);
|
|
102
|
+
}
|
|
100
103
|
await writeText(filePath, value);
|
|
101
104
|
return true;
|
|
102
105
|
}
|
|
@@ -10,7 +10,7 @@ import { pathExists, readText, writeText } from '../utils/fs.js';
|
|
|
10
10
|
import { escapeRegex } from '../utils/regex.js';
|
|
11
11
|
import { detectIndent, getNodeSource, parseScript } from './ast-utils.js';
|
|
12
12
|
import { withParserFallback } from './parser-fallback.js';
|
|
13
|
-
import { extractNameFromExpression, findInsertionAfterFireforgeBlocks, findMethodBody, findMethodBraceIndex, validateWireName, walkToTryBlockEnd, } from './wire-utils.js';
|
|
13
|
+
import { assertBraceBalancePreserved, extractNameFromExpression, findInsertionAfterFireforgeBlocks, findMethodBody, findMethodBraceIndex, validateWireName, walkToTryBlockEnd, } from './wire-utils.js';
|
|
14
14
|
const BROWSER_INIT_JS = 'browser/base/content/browser-init.js';
|
|
15
15
|
/**
|
|
16
16
|
* AST-based implementation: finds onLoad() method body, locates existing
|
|
@@ -113,7 +113,7 @@ export function legacyAddInit(content, expression, after) {
|
|
|
113
113
|
const name = extractNameFromExpression(expression);
|
|
114
114
|
const lines = content.split('\n');
|
|
115
115
|
const onLoadRegex = /\b(?:async\s+)?onLoad\s*[(:]/;
|
|
116
|
-
const found = findMethodBraceIndex(lines, onLoadRegex);
|
|
116
|
+
const found = findMethodBraceIndex(lines, onLoadRegex, { requireBrace: true });
|
|
117
117
|
if (!found) {
|
|
118
118
|
throw new GeneralError('Could not find "onLoad" method in browser-init.js.\n' +
|
|
119
119
|
'FireForge was looking for a signature matching: \\b(?:async\\s+)?onLoad\\s*[(:]');
|
|
@@ -138,7 +138,10 @@ export function legacyAddInit(content, expression, after) {
|
|
|
138
138
|
break;
|
|
139
139
|
}
|
|
140
140
|
}
|
|
141
|
-
insertIndex = walkToTryBlockEnd(lines, tryStart
|
|
141
|
+
insertIndex = walkToTryBlockEnd(lines, tryStart, {
|
|
142
|
+
strict: true,
|
|
143
|
+
context: BROWSER_INIT_JS,
|
|
144
|
+
});
|
|
142
145
|
located = true;
|
|
143
146
|
break;
|
|
144
147
|
}
|
|
@@ -194,7 +197,10 @@ export async function addInitToBrowserInit(engineDir, expression, after) {
|
|
|
194
197
|
if (initPattern.test(content)) {
|
|
195
198
|
return false;
|
|
196
199
|
}
|
|
197
|
-
const { value } = withParserFallback(() => addInitAST(content, expression, after), () => legacyAddInit(content, expression, after), BROWSER_INIT_JS);
|
|
200
|
+
const { value, usedFallback } = withParserFallback(() => addInitAST(content, expression, after), () => legacyAddInit(content, expression, after), BROWSER_INIT_JS);
|
|
201
|
+
if (usedFallback) {
|
|
202
|
+
assertBraceBalancePreserved(content, value, BROWSER_INIT_JS);
|
|
203
|
+
}
|
|
198
204
|
await writeText(filePath, value);
|
|
199
205
|
return true;
|
|
200
206
|
}
|
|
@@ -9,7 +9,7 @@ import { BuildError } from '../errors/build.js';
|
|
|
9
9
|
import { pathExists, readText, writeText } from '../utils/fs.js';
|
|
10
10
|
import { detectIndent, getNodeSource, parseScript, walkAST, } from './ast-utils.js';
|
|
11
11
|
import { withParserFallback } from './parser-fallback.js';
|
|
12
|
-
import { findNearestTryLine, validateWireName, walkToTryBlockEnd } from './wire-utils.js';
|
|
12
|
+
import { assertBraceBalancePreserved, findNearestTryLine, validateWireName, walkToTryBlockEnd, } from './wire-utils.js';
|
|
13
13
|
const BROWSER_MAIN_JS = 'browser/base/content/browser-main.js';
|
|
14
14
|
/**
|
|
15
15
|
* AST-based implementation: finds the last try/catch containing
|
|
@@ -81,7 +81,10 @@ export function legacyAddSubscript(content, name) {
|
|
|
81
81
|
let insertIndex;
|
|
82
82
|
if (lastSubScriptLine !== -1) {
|
|
83
83
|
const tryStart = findNearestTryLine(lines, lastSubScriptLine - 1, -1);
|
|
84
|
-
insertIndex =
|
|
84
|
+
insertIndex =
|
|
85
|
+
tryStart !== -1
|
|
86
|
+
? walkToTryBlockEnd(lines, tryStart, { strict: true, context: BROWSER_MAIN_JS })
|
|
87
|
+
: lastSubScriptLine + 1;
|
|
85
88
|
}
|
|
86
89
|
else {
|
|
87
90
|
insertIndex = lines.length;
|
|
@@ -127,7 +130,10 @@ export async function addSubscriptToBrowserMain(engineDir, name) {
|
|
|
127
130
|
if (content.includes(`content/${name}.js"`)) {
|
|
128
131
|
return false;
|
|
129
132
|
}
|
|
130
|
-
const { value } = withParserFallback(() => addSubscriptAST(content, name), () => legacyAddSubscript(content, name), BROWSER_MAIN_JS);
|
|
133
|
+
const { value, usedFallback } = withParserFallback(() => addSubscriptAST(content, name), () => legacyAddSubscript(content, name), BROWSER_MAIN_JS);
|
|
134
|
+
if (usedFallback) {
|
|
135
|
+
assertBraceBalancePreserved(content, value, BROWSER_MAIN_JS);
|
|
136
|
+
}
|
|
131
137
|
await writeText(filePath, value);
|
|
132
138
|
return true;
|
|
133
139
|
}
|
|
@@ -51,9 +51,20 @@ export declare function tokenizeXhtml(lines: string[]): XhtmlToken[];
|
|
|
51
51
|
* Finds the line index of a method signature matching `pattern`, then
|
|
52
52
|
* advances to the line containing the opening brace.
|
|
53
53
|
*
|
|
54
|
-
*
|
|
54
|
+
* By default this helper is tolerant: when no `{` is found anywhere after
|
|
55
|
+
* the signature, it still returns `braceIndex: methodLine` — which is the
|
|
56
|
+
* correct answer when the signature and body brace live on the same line,
|
|
57
|
+
* but is ambiguous when the method is abstract or truncated. Opt into
|
|
58
|
+
* stricter behaviour by passing `requireBrace: true`; the function will
|
|
59
|
+
* return `null` instead of guessing, letting the caller surface a clean
|
|
60
|
+
* {@link ParserFallbackError} rather than inserting into a wrong offset.
|
|
61
|
+
*
|
|
62
|
+
* @returns `{ methodLine, braceIndex }`, or `null` if the pattern is not
|
|
63
|
+
* found (or, under `requireBrace`, no brace follows the signature).
|
|
55
64
|
*/
|
|
56
|
-
export declare function findMethodBraceIndex(lines: string[], pattern: RegExp
|
|
65
|
+
export declare function findMethodBraceIndex(lines: string[], pattern: RegExp, options?: {
|
|
66
|
+
requireBrace?: boolean;
|
|
67
|
+
}): {
|
|
57
68
|
methodLine: number;
|
|
58
69
|
braceIndex: number;
|
|
59
70
|
} | null;
|
|
@@ -61,10 +72,46 @@ export declare function findMethodBraceIndex(lines: string[], pattern: RegExp):
|
|
|
61
72
|
* Starting from `startLine`, walks lines using {@link countBraceDepth}
|
|
62
73
|
* until the brace depth returns to zero (i.e., the enclosing block closes).
|
|
63
74
|
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
75
|
+
* Default behaviour is defensive — if the block never closes, the helper
|
|
76
|
+
* returns `startLine + 1` so a single malformed file does not stop the
|
|
77
|
+
* entire fallback path. Pass `{ strict: true }` to opt into failing loudly
|
|
78
|
+
* with a {@link ParserFallbackError} instead; new callers should prefer
|
|
79
|
+
* strict mode so silent mis-insertions surface as the fallback refusing
|
|
80
|
+
* to touch the file.
|
|
81
|
+
*
|
|
82
|
+
* @param lines - The full file split by newline
|
|
83
|
+
* @param startLine - Line index of the `try {` (or other block opener) to walk
|
|
84
|
+
* @param options - Pass `{ strict: true }` to throw when the block never closes
|
|
85
|
+
* @returns The line index *after* the closing brace
|
|
86
|
+
*/
|
|
87
|
+
export declare function walkToTryBlockEnd(lines: string[], startLine: number, options?: {
|
|
88
|
+
strict?: boolean;
|
|
89
|
+
context?: string;
|
|
90
|
+
}): number;
|
|
91
|
+
/**
|
|
92
|
+
* Scans the entire file and returns the net brace balance so callers can
|
|
93
|
+
* assert that a legacy fallback mutation did not silently introduce or
|
|
94
|
+
* drop a `{` / `}`. The helper reuses {@link countBraceDepth} so strings,
|
|
95
|
+
* comments, and regex literals are handled consistently with the walker.
|
|
96
|
+
*
|
|
97
|
+
* @param content - Full file contents (will be split by newline)
|
|
98
|
+
* @returns The net depth across the file (`opens - closes`) and a
|
|
99
|
+
* convenience `balanced` flag equal to `depth === 0`.
|
|
100
|
+
*/
|
|
101
|
+
export declare function computeFileBraceBalance(content: string): {
|
|
102
|
+
depth: number;
|
|
103
|
+
balanced: boolean;
|
|
104
|
+
};
|
|
105
|
+
/**
|
|
106
|
+
* Round-trip guard used after a legacy fallback mutation: if the file's
|
|
107
|
+
* net brace balance drifts between `before` and `after`, something went
|
|
108
|
+
* wrong and the fallback is refusing to write a corrupted file. Expects
|
|
109
|
+
* the delta to be exactly zero — wire fallbacks only insert whole
|
|
110
|
+
* try/catch blocks, which always contribute equal opens and closes.
|
|
111
|
+
*
|
|
112
|
+
* @throws {@link ParserFallbackError} when the balance delta is non-zero.
|
|
66
113
|
*/
|
|
67
|
-
export declare function
|
|
114
|
+
export declare function assertBraceBalancePreserved(before: string, after: string, context: string): void;
|
|
68
115
|
/**
|
|
69
116
|
* Looks backward from `fromLine` (exclusive) to find the nearest `try {`
|
|
70
117
|
* line. If nothing is found searching backward, also searches forward.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { GeneralError } from '../errors/base.js';
|
|
1
|
+
import { GeneralError, ParserFallbackError } from '../errors/base.js';
|
|
2
2
|
import { walkAST } from './ast-utils.js';
|
|
3
3
|
/**
|
|
4
4
|
* Validates a name for safe interpolation into generated JavaScript string literals.
|
|
@@ -158,9 +158,18 @@ export function tokenizeXhtml(lines) {
|
|
|
158
158
|
* Finds the line index of a method signature matching `pattern`, then
|
|
159
159
|
* advances to the line containing the opening brace.
|
|
160
160
|
*
|
|
161
|
-
*
|
|
161
|
+
* By default this helper is tolerant: when no `{` is found anywhere after
|
|
162
|
+
* the signature, it still returns `braceIndex: methodLine` — which is the
|
|
163
|
+
* correct answer when the signature and body brace live on the same line,
|
|
164
|
+
* but is ambiguous when the method is abstract or truncated. Opt into
|
|
165
|
+
* stricter behaviour by passing `requireBrace: true`; the function will
|
|
166
|
+
* return `null` instead of guessing, letting the caller surface a clean
|
|
167
|
+
* {@link ParserFallbackError} rather than inserting into a wrong offset.
|
|
168
|
+
*
|
|
169
|
+
* @returns `{ methodLine, braceIndex }`, or `null` if the pattern is not
|
|
170
|
+
* found (or, under `requireBrace`, no brace follows the signature).
|
|
162
171
|
*/
|
|
163
|
-
export function findMethodBraceIndex(lines, pattern) {
|
|
172
|
+
export function findMethodBraceIndex(lines, pattern, options) {
|
|
164
173
|
let methodLine = -1;
|
|
165
174
|
for (let i = 0; i < lines.length; i++) {
|
|
166
175
|
if (pattern.test(lines[i] ?? '')) {
|
|
@@ -171,22 +180,36 @@ export function findMethodBraceIndex(lines, pattern) {
|
|
|
171
180
|
if (methodLine === -1)
|
|
172
181
|
return null;
|
|
173
182
|
let braceIndex = methodLine;
|
|
183
|
+
let braceFound = false;
|
|
174
184
|
for (let i = methodLine; i < lines.length; i++) {
|
|
175
185
|
if (lines[i]?.includes('{')) {
|
|
176
186
|
braceIndex = i;
|
|
187
|
+
braceFound = true;
|
|
177
188
|
break;
|
|
178
189
|
}
|
|
179
190
|
}
|
|
191
|
+
if (!braceFound && options?.requireBrace) {
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
180
194
|
return { methodLine, braceIndex };
|
|
181
195
|
}
|
|
182
196
|
/**
|
|
183
197
|
* Starting from `startLine`, walks lines using {@link countBraceDepth}
|
|
184
198
|
* until the brace depth returns to zero (i.e., the enclosing block closes).
|
|
185
199
|
*
|
|
186
|
-
*
|
|
187
|
-
*
|
|
200
|
+
* Default behaviour is defensive — if the block never closes, the helper
|
|
201
|
+
* returns `startLine + 1` so a single malformed file does not stop the
|
|
202
|
+
* entire fallback path. Pass `{ strict: true }` to opt into failing loudly
|
|
203
|
+
* with a {@link ParserFallbackError} instead; new callers should prefer
|
|
204
|
+
* strict mode so silent mis-insertions surface as the fallback refusing
|
|
205
|
+
* to touch the file.
|
|
206
|
+
*
|
|
207
|
+
* @param lines - The full file split by newline
|
|
208
|
+
* @param startLine - Line index of the `try {` (or other block opener) to walk
|
|
209
|
+
* @param options - Pass `{ strict: true }` to throw when the block never closes
|
|
210
|
+
* @returns The line index *after* the closing brace
|
|
188
211
|
*/
|
|
189
|
-
export function walkToTryBlockEnd(lines, startLine) {
|
|
212
|
+
export function walkToTryBlockEnd(lines, startLine, options) {
|
|
190
213
|
let depth = 0;
|
|
191
214
|
let inBlock = false;
|
|
192
215
|
for (let j = startLine; j < lines.length; j++) {
|
|
@@ -197,8 +220,48 @@ export function walkToTryBlockEnd(lines, startLine) {
|
|
|
197
220
|
return j + 1;
|
|
198
221
|
}
|
|
199
222
|
}
|
|
223
|
+
if (options?.strict) {
|
|
224
|
+
throw new ParserFallbackError(`Block starting at line ${startLine + 1} never closes — fallback parser refuses to insert`, options.context);
|
|
225
|
+
}
|
|
200
226
|
return startLine + 1;
|
|
201
227
|
}
|
|
228
|
+
/**
|
|
229
|
+
* Scans the entire file and returns the net brace balance so callers can
|
|
230
|
+
* assert that a legacy fallback mutation did not silently introduce or
|
|
231
|
+
* drop a `{` / `}`. The helper reuses {@link countBraceDepth} so strings,
|
|
232
|
+
* comments, and regex literals are handled consistently with the walker.
|
|
233
|
+
*
|
|
234
|
+
* @param content - Full file contents (will be split by newline)
|
|
235
|
+
* @returns The net depth across the file (`opens - closes`) and a
|
|
236
|
+
* convenience `balanced` flag equal to `depth === 0`.
|
|
237
|
+
*/
|
|
238
|
+
export function computeFileBraceBalance(content) {
|
|
239
|
+
const lines = content.split('\n');
|
|
240
|
+
let depth = 0;
|
|
241
|
+
let inBlock = false;
|
|
242
|
+
for (const line of lines) {
|
|
243
|
+
const r = countBraceDepth(line, inBlock);
|
|
244
|
+
depth += r.depth;
|
|
245
|
+
inBlock = r.inBlockComment;
|
|
246
|
+
}
|
|
247
|
+
return { depth, balanced: depth === 0 };
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Round-trip guard used after a legacy fallback mutation: if the file's
|
|
251
|
+
* net brace balance drifts between `before` and `after`, something went
|
|
252
|
+
* wrong and the fallback is refusing to write a corrupted file. Expects
|
|
253
|
+
* the delta to be exactly zero — wire fallbacks only insert whole
|
|
254
|
+
* try/catch blocks, which always contribute equal opens and closes.
|
|
255
|
+
*
|
|
256
|
+
* @throws {@link ParserFallbackError} when the balance delta is non-zero.
|
|
257
|
+
*/
|
|
258
|
+
export function assertBraceBalancePreserved(before, after, context) {
|
|
259
|
+
const beforeDepth = computeFileBraceBalance(before).depth;
|
|
260
|
+
const afterDepth = computeFileBraceBalance(after).depth;
|
|
261
|
+
if (beforeDepth !== afterDepth) {
|
|
262
|
+
throw new ParserFallbackError(`Brace balance drifted from ${beforeDepth} to ${afterDepth} after fallback mutation; refusing to write`, context);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
202
265
|
/**
|
|
203
266
|
* Looks backward from `fromLine` (exclusive) to find the nearest `try {`
|
|
204
267
|
* line. If nothing is found searching backward, also searches forward.
|
|
@@ -25,6 +25,26 @@ export declare abstract class FireForgeError extends Error {
|
|
|
25
25
|
export declare class GeneralError extends FireForgeError {
|
|
26
26
|
readonly code: 1;
|
|
27
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* Raised when a legacy regex/brace-depth fallback parser decides it
|
|
30
|
+
* cannot safely perform its mutation — e.g. because a block it expected
|
|
31
|
+
* to walk never closes, because the inserted result fails a round-trip
|
|
32
|
+
* brace balance check, or because an expected pattern is missing.
|
|
33
|
+
*
|
|
34
|
+
* Dedicated subclass (rather than raw GeneralError) so callers and tests
|
|
35
|
+
* can distinguish "the fallback refused to corrupt this file" from other
|
|
36
|
+
* failure modes, and so {@link withParserFallback} callers can opt into
|
|
37
|
+
* re-throwing fallback refusals instead of silently swallowing them.
|
|
38
|
+
*/
|
|
39
|
+
export declare class ParserFallbackError extends FireForgeError {
|
|
40
|
+
/** Filename or logical context where the fallback ran (e.g. `browser-init.js`). */
|
|
41
|
+
readonly context?: string | undefined;
|
|
42
|
+
readonly code: 1;
|
|
43
|
+
constructor(message: string,
|
|
44
|
+
/** Filename or logical context where the fallback ran (e.g. `browser-init.js`). */
|
|
45
|
+
context?: string | undefined, cause?: unknown);
|
|
46
|
+
get userMessage(): string;
|
|
47
|
+
}
|
|
28
48
|
/**
|
|
29
49
|
* Error thrown when a command-line argument is invalid.
|
|
30
50
|
*/
|
package/dist/src/errors/base.js
CHANGED
|
@@ -36,6 +36,30 @@ export class FireForgeError extends Error {
|
|
|
36
36
|
export class GeneralError extends FireForgeError {
|
|
37
37
|
code = ExitCode.GENERAL_ERROR;
|
|
38
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
* Raised when a legacy regex/brace-depth fallback parser decides it
|
|
41
|
+
* cannot safely perform its mutation — e.g. because a block it expected
|
|
42
|
+
* to walk never closes, because the inserted result fails a round-trip
|
|
43
|
+
* brace balance check, or because an expected pattern is missing.
|
|
44
|
+
*
|
|
45
|
+
* Dedicated subclass (rather than raw GeneralError) so callers and tests
|
|
46
|
+
* can distinguish "the fallback refused to corrupt this file" from other
|
|
47
|
+
* failure modes, and so {@link withParserFallback} callers can opt into
|
|
48
|
+
* re-throwing fallback refusals instead of silently swallowing them.
|
|
49
|
+
*/
|
|
50
|
+
export class ParserFallbackError extends FireForgeError {
|
|
51
|
+
context;
|
|
52
|
+
code = ExitCode.GENERAL_ERROR;
|
|
53
|
+
constructor(message,
|
|
54
|
+
/** Filename or logical context where the fallback ran (e.g. `browser-init.js`). */
|
|
55
|
+
context, cause) {
|
|
56
|
+
super(message, cause);
|
|
57
|
+
this.context = context;
|
|
58
|
+
}
|
|
59
|
+
get userMessage() {
|
|
60
|
+
return this.context ? `${this.message} (in ${this.context})` : this.message;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
39
63
|
/**
|
|
40
64
|
* Error thrown when a command-line argument is invalid.
|
|
41
65
|
*/
|
|
@@ -15,7 +15,13 @@ export class FurnaceError extends FireForgeError {
|
|
|
15
15
|
let msg = this.component
|
|
16
16
|
? `Furnace Error (${this.component}): ${this.message}`
|
|
17
17
|
: `Furnace Error: ${this.message}`;
|
|
18
|
-
msg += '\n\
|
|
18
|
+
msg += '\n\nTo fix this:\n';
|
|
19
|
+
msg += ' 1. Check the error message above for specifics\n';
|
|
20
|
+
// Avoid circular advice when the error is thrown during validation itself.
|
|
21
|
+
if (!this.message.includes('furnace validate')) {
|
|
22
|
+
msg += ' 2. Run "fireforge furnace validate" to diagnose issues\n';
|
|
23
|
+
}
|
|
24
|
+
msg += ` ${this.message.includes('furnace validate') ? '2' : '3'}. Use "fireforge doctor --repair-furnace" if state is inconsistent`;
|
|
19
25
|
return msg;
|
|
20
26
|
}
|
|
21
27
|
}
|
|
@@ -7,7 +7,12 @@ import { ExitCode } from './codes.js';
|
|
|
7
7
|
export class RebaseError extends FireForgeError {
|
|
8
8
|
code = ExitCode.PATCH_ERROR;
|
|
9
9
|
get userMessage() {
|
|
10
|
-
|
|
10
|
+
let msg = `Rebase Error: ${this.message}`;
|
|
11
|
+
msg += '\n\nTo fix this:\n';
|
|
12
|
+
msg += ' 1. Check the error message above for specifics\n';
|
|
13
|
+
msg += ' 2. Use "fireforge rebase --continue" to resume an interrupted rebase\n';
|
|
14
|
+
msg += ' 3. Use "fireforge rebase --abort" to cancel and restore engine state';
|
|
15
|
+
return msg;
|
|
11
16
|
}
|
|
12
17
|
}
|
|
13
18
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Re-exports all command-related types from focused sub-modules.
|
|
3
3
|
*/
|
|
4
|
-
export type { BuildOptions, DiscardOptions, DoctorOptions, DownloadOptions, ExportOptions, FurnaceApplyOptions, FurnaceCreateOptions, FurnaceDeployOptions, FurnaceOverrideOptions, FurnacePreviewOptions, FurnaceRemoveOptions, GlobalOptions, ImportOptions, PackageOptions, RebaseOptions, ReExportOptions, RegisterOptions, ResetOptions, RunOptions, SetupOptions, StatusOptions, TestOptions, TokenAddOptions, WireOptions, } from './options.js';
|
|
4
|
+
export type { BuildOptions, DiscardOptions, DoctorOptions, DownloadOptions, ExportOptions, FurnaceApplyOptions, FurnaceCreateOptions, FurnaceDeployOptions, FurnaceOverrideOptions, FurnacePreviewOptions, FurnaceRefreshOptions, FurnaceRemoveOptions, FurnaceSyncOptions, FurnaceValidateOptions, GlobalOptions, ImportOptions, PackageOptions, PatchDeleteOptions, PatchReorderOptions, RebaseOptions, ReExportOptions, RegisterOptions, ResetOptions, RunOptions, SetupOptions, StatusOptions, TestOptions, TokenAddOptions, WireOptions, } from './options.js';
|
|
5
5
|
export type { ImportSummary, PatchCategory, PatchesManifest, PatchInfo, PatchLintIssue, PatchMetadata, PatchResult, } from './patches.js';
|
|
6
6
|
export type { DoctorCheck, ProjectStatus, TokenCoverageFileEntry, TokenCoverageReport, } from './project.js';
|