@hominis/fireforge 0.11.2 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -0
- package/README.md +54 -1
- package/dist/src/commands/export-shared.d.ts +2 -1
- package/dist/src/commands/export-shared.js +3 -2
- package/dist/src/commands/furnace/create.js +1 -1
- package/dist/src/commands/furnace/deploy.js +1 -1
- package/dist/src/commands/furnace/override.js +1 -1
- package/dist/src/commands/furnace/refresh.js +1 -1
- package/dist/src/commands/furnace/remove.js +1 -1
- package/dist/src/commands/furnace/rename.js +1 -1
- package/dist/src/commands/furnace/scan.js +1 -1
- package/dist/src/commands/lint.js +8 -3
- package/dist/src/core/ast-utils.d.ts +10 -0
- package/dist/src/core/ast-utils.js +18 -0
- package/dist/src/core/config-paths.d.ts +2 -2
- package/dist/src/core/config-paths.js +3 -0
- package/dist/src/core/config-validate.js +21 -3
- package/dist/src/core/file-lock.js +39 -2
- package/dist/src/core/furnace-apply.js +2 -1
- package/dist/src/core/furnace-config.js +6 -2
- package/dist/src/core/patch-apply.js +26 -4
- package/dist/src/core/patch-lint-checkjs.d.ts +21 -0
- package/dist/src/core/patch-lint-checkjs.js +225 -0
- package/dist/src/core/patch-lint-cross.d.ts +1 -0
- package/dist/src/core/patch-lint-cross.js +7 -0
- package/dist/src/core/patch-lint-jsdoc.d.ts +21 -0
- package/dist/src/core/patch-lint-jsdoc.js +259 -0
- package/dist/src/core/patch-lint-ownership.d.ts +25 -0
- package/dist/src/core/patch-lint-ownership.js +43 -0
- package/dist/src/core/patch-lint.d.ts +7 -2
- package/dist/src/core/patch-lint.js +30 -30
- package/dist/src/types/config.d.ts +9 -0
- package/dist/src/utils/paths.js +3 -1
- package/package.json +1 -1
|
@@ -6,7 +6,10 @@ import { verbose } from '../utils/logger.js';
|
|
|
6
6
|
import { hasRawCssColors, stripJsComments } from '../utils/regex.js';
|
|
7
7
|
import { loadFurnaceConfig } from './furnace-config.js';
|
|
8
8
|
import { getLicenseHeader, hasAnyLicenseHeader } from './license-headers.js';
|
|
9
|
+
import { runCheckJs } from './patch-lint-checkjs.js';
|
|
9
10
|
import { detectNewFilesInDiff, extractAddedLinesPerFile } from './patch-lint-diff.js';
|
|
11
|
+
import { validateExportJsDoc } from './patch-lint-jsdoc.js';
|
|
12
|
+
import { resolvePatchOwnedSysMjs } from './patch-lint-ownership.js';
|
|
10
13
|
// ---------------------------------------------------------------------------
|
|
11
14
|
// Cross-patch lint re-exports
|
|
12
15
|
// ---------------------------------------------------------------------------
|
|
@@ -16,8 +19,11 @@ import { detectNewFilesInDiff, extractAddedLinesPerFile } from './patch-lint-dif
|
|
|
16
19
|
// `patch-lint-cross.ts` so the per-patch and cross-patch rule bodies can
|
|
17
20
|
// each stay within the project's per-file line budget. Re-export the
|
|
18
21
|
// public surface so callers continue to import from a single module.
|
|
22
|
+
export { runCheckJs } from './patch-lint-checkjs.js';
|
|
19
23
|
export { buildPatchQueueContext, collectNewFileCreatorsByPath, extractImportSpecifiers, extractImportSpecifiersWithLines, findForwardImportIgnoreLines, FORWARD_IMPORT_IGNORE_MARKER, isForwardImportableFile, lintPatchQueue, lintPatchQueueDuplicateCreations, lintPatchQueueForwardImports, } from './patch-lint-cross.js';
|
|
20
24
|
export { buildModifiedFileAdditionsFromDiff, detectNewFilesInDiff } from './patch-lint-diff.js';
|
|
25
|
+
export { validateExportJsDoc } from './patch-lint-jsdoc.js';
|
|
26
|
+
export { resolvePatchOwnedSysMjs } from './patch-lint-ownership.js';
|
|
21
27
|
// ---------------------------------------------------------------------------
|
|
22
28
|
// Helpers
|
|
23
29
|
// ---------------------------------------------------------------------------
|
|
@@ -156,9 +162,10 @@ export async function lintNewFileHeaders(repoDir, newFiles, config) {
|
|
|
156
162
|
* @param affectedFiles - File paths (relative to repoDir)
|
|
157
163
|
* @param newFiles - Set of files that are newly created in this patch
|
|
158
164
|
* @param config - Project configuration
|
|
165
|
+
* @param patchOwnedFiles - Optional set of patch-owned `.sys.mjs` paths for scoped JSDoc enforcement
|
|
159
166
|
* @returns Array of lint issues
|
|
160
167
|
*/
|
|
161
|
-
export async function lintPatchedJs(repoDir, affectedFiles, newFiles, config) {
|
|
168
|
+
export async function lintPatchedJs(repoDir, affectedFiles, newFiles, config, patchOwnedFiles) {
|
|
162
169
|
const jsFiles = affectedFiles.filter(isJsFile);
|
|
163
170
|
if (jsFiles.length === 0)
|
|
164
171
|
return [];
|
|
@@ -195,32 +202,17 @@ export async function lintPatchedJs(repoDir, affectedFiles, newFiles, config) {
|
|
|
195
202
|
});
|
|
196
203
|
}
|
|
197
204
|
}
|
|
198
|
-
// 3. JSDoc on exports (
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
continue;
|
|
210
|
-
if (prev.endsWith('*/')) {
|
|
211
|
-
hasJsDoc = true;
|
|
212
|
-
}
|
|
213
|
-
break;
|
|
214
|
-
}
|
|
215
|
-
if (!hasJsDoc) {
|
|
216
|
-
issues.push({
|
|
217
|
-
file,
|
|
218
|
-
check: 'missing-jsdoc',
|
|
219
|
-
message: `Export at line ${i + 1} is missing a JSDoc comment with @param/@returns.`,
|
|
220
|
-
severity: 'warning',
|
|
221
|
-
});
|
|
222
|
-
}
|
|
223
|
-
}
|
|
205
|
+
// 3. JSDoc on exports (patch-owned .sys.mjs files)
|
|
206
|
+
const isOwned = patchOwnedFiles ? patchOwnedFiles.has(file) : isNew;
|
|
207
|
+
if (isOwned && isSysMjs) {
|
|
208
|
+
const jsdocIssues = validateExportJsDoc(content);
|
|
209
|
+
for (const jsdocIssue of jsdocIssues) {
|
|
210
|
+
issues.push({
|
|
211
|
+
file,
|
|
212
|
+
check: jsdocIssue.check,
|
|
213
|
+
message: jsdocIssue.message,
|
|
214
|
+
severity: 'error',
|
|
215
|
+
});
|
|
224
216
|
}
|
|
225
217
|
}
|
|
226
218
|
// 4. Observer topic naming
|
|
@@ -346,20 +338,22 @@ export async function lintModifiedFileHeaders(repoDir, affectedFiles, newFiles)
|
|
|
346
338
|
* @param affectedFiles - File paths (relative to repoDir) affected by the patch
|
|
347
339
|
* @param diffContent - Raw unified diff string
|
|
348
340
|
* @param config - Project configuration
|
|
341
|
+
* @param patchQueueCtx - Optional cross-patch context for ownership resolution
|
|
349
342
|
* @returns Array of all lint issues found
|
|
350
343
|
*/
|
|
351
|
-
export async function lintExportedPatch(repoDir, affectedFiles, diffContent, config) {
|
|
344
|
+
export async function lintExportedPatch(repoDir, affectedFiles, diffContent, config, patchQueueCtx) {
|
|
352
345
|
const newFiles = detectNewFilesInDiff(diffContent);
|
|
353
346
|
const lineCount = diffContent.split('\n').length;
|
|
347
|
+
const patchOwnedFiles = resolvePatchOwnedSysMjs(newFiles, patchQueueCtx);
|
|
354
348
|
const [cssIssues, headerIssues, jsIssues, modifiedHeaderIssues] = await Promise.all([
|
|
355
349
|
lintPatchedCss(repoDir, affectedFiles, diffContent),
|
|
356
350
|
lintNewFileHeaders(repoDir, [...newFiles], config),
|
|
357
|
-
lintPatchedJs(repoDir, affectedFiles, newFiles, config),
|
|
351
|
+
lintPatchedJs(repoDir, affectedFiles, newFiles, config, patchOwnedFiles),
|
|
358
352
|
lintModifiedFileHeaders(repoDir, affectedFiles, newFiles),
|
|
359
353
|
]);
|
|
360
354
|
const modCommentIssues = lintModificationComments(diffContent, config);
|
|
361
355
|
const sizeIssues = lintPatchSize(affectedFiles, lineCount);
|
|
362
|
-
|
|
356
|
+
const issues = [
|
|
363
357
|
...sizeIssues,
|
|
364
358
|
...cssIssues,
|
|
365
359
|
...headerIssues,
|
|
@@ -367,5 +361,11 @@ export async function lintExportedPatch(repoDir, affectedFiles, diffContent, con
|
|
|
367
361
|
...jsIssues,
|
|
368
362
|
...modCommentIssues,
|
|
369
363
|
];
|
|
364
|
+
// Optional checkJs pass — only when explicitly enabled in config
|
|
365
|
+
if (config.patchLint?.checkJs) {
|
|
366
|
+
const checkJsIssues = await runCheckJs(repoDir, patchOwnedFiles);
|
|
367
|
+
issues.push(...checkJsIssues);
|
|
368
|
+
}
|
|
369
|
+
return issues;
|
|
370
370
|
}
|
|
371
371
|
//# sourceMappingURL=patch-lint.js.map
|
|
@@ -42,6 +42,8 @@ export interface FireForgeConfig {
|
|
|
42
42
|
license?: ProjectLicense;
|
|
43
43
|
/** Wire command configuration */
|
|
44
44
|
wire?: WireConfig;
|
|
45
|
+
/** Patch lint configuration */
|
|
46
|
+
patchLint?: PatchLintConfig;
|
|
45
47
|
}
|
|
46
48
|
/**
|
|
47
49
|
* Wire command configuration.
|
|
@@ -50,6 +52,13 @@ export interface WireConfig {
|
|
|
50
52
|
/** Subscript directory relative to engine/. Default: "browser/base/content" */
|
|
51
53
|
subscriptDir?: string;
|
|
52
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* Configuration for patch lint rules.
|
|
57
|
+
*/
|
|
58
|
+
export interface PatchLintConfig {
|
|
59
|
+
/** Enable TypeScript checkJs pass on patch-owned .sys.mjs files */
|
|
60
|
+
checkJs?: boolean;
|
|
61
|
+
}
|
|
53
62
|
/**
|
|
54
63
|
* Build mode for mach.
|
|
55
64
|
*/
|
package/dist/src/utils/paths.js
CHANGED
|
@@ -12,6 +12,8 @@ export function isExplicitAbsolutePath(path) {
|
|
|
12
12
|
}
|
|
13
13
|
/** Resolves a candidate path and returns whether it stays within the given root. */
|
|
14
14
|
export function isPathInsideRoot(root, candidate) {
|
|
15
|
+
if (candidate.includes('\0'))
|
|
16
|
+
return false;
|
|
15
17
|
const resolvedRoot = resolve(root);
|
|
16
18
|
const resolvedCandidate = isExplicitAbsolutePath(candidate)
|
|
17
19
|
? resolve(candidate)
|
|
@@ -24,7 +26,7 @@ export function isPathInsideRoot(root, candidate) {
|
|
|
24
26
|
}
|
|
25
27
|
/** Checks whether a relative path stays contained within an arbitrary root. */
|
|
26
28
|
export function isContainedRelativePath(path) {
|
|
27
|
-
if (isExplicitAbsolutePath(path)) {
|
|
29
|
+
if (isExplicitAbsolutePath(path) || path.includes('\0')) {
|
|
28
30
|
return false;
|
|
29
31
|
}
|
|
30
32
|
return isPathInsideRoot(RELATIVE_PATH_ROOT, path);
|