@hominis/fireforge 0.18.10 → 0.18.11
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/README.md +20 -7
- package/dist/src/commands/doctor.js +1 -1
- package/dist/src/commands/furnace/index.js +1 -1
- package/dist/src/commands/manifest.js +2 -0
- package/dist/src/commands/package.js +1 -1
- package/dist/src/commands/test.js +8 -8
- package/dist/src/commands/typecheck.d.ts +52 -0
- package/dist/src/commands/typecheck.js +115 -0
- package/dist/src/core/config-paths.d.ts +2 -2
- package/dist/src/core/config-paths.js +5 -0
- package/dist/src/core/config-validate.js +64 -0
- package/dist/src/core/mach-build-artifacts.d.ts +2 -2
- package/dist/src/core/mach-build-artifacts.js +2 -2
- package/dist/src/core/mach-error-hints.js +7 -8
- package/dist/src/core/marionette-port.js +4 -4
- package/dist/src/core/patch-lint-checkjs.d.ts +14 -2
- package/dist/src/core/patch-lint-checkjs.js +40 -73
- package/dist/src/core/patch-lint.js +6 -4
- package/dist/src/core/typecheck-shim.d.ts +70 -0
- package/dist/src/core/typecheck-shim.js +112 -0
- package/dist/src/core/typecheck.d.ts +65 -0
- package/dist/src/core/typecheck.js +302 -0
- package/dist/src/core/xpcshell-appdir.d.ts +2 -2
- package/dist/src/core/xpcshell-appdir.js +2 -2
- package/dist/src/types/commands/options.d.ts +1 -1
- package/dist/src/types/config.d.ts +33 -0
- package/dist/src/types/furnace.d.ts +1 -1
- package/dist/src/types/typecheck.d.ts +51 -0
- package/dist/src/types/typecheck.js +15 -0
- package/package.json +1 -1
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
+
/**
|
|
3
|
+
* Whole-project TypeScript type checking driven by user-supplied
|
|
4
|
+
* `jsconfig.json` paths. The engine behind the `fireforge typecheck`
|
|
5
|
+
* command.
|
|
6
|
+
*
|
|
7
|
+
* Distinct from `patch-lint-checkjs.ts` (patch-hygiene): patchLint is
|
|
8
|
+
* scoped, fireforge-controlled, and runs as part of `fireforge lint`;
|
|
9
|
+
* this command runs whole projects with user-controlled compiler
|
|
10
|
+
* options and is intended as a CI gate. The two share the Firefox
|
|
11
|
+
* globals shim and suppressed-code list (via `typecheck-shim.ts`) so
|
|
12
|
+
* a file that lints clean cannot fail typecheck for a reason the
|
|
13
|
+
* operator could not have inferred from the docs.
|
|
14
|
+
*
|
|
15
|
+
* Loads the TypeScript compiler API via dynamic import so it is only
|
|
16
|
+
* required when `typecheck.projects` is configured. TypeScript
|
|
17
|
+
* remains a dev-dependency — if a user invokes `fireforge typecheck`
|
|
18
|
+
* without installing it, the function returns a clear error pointing
|
|
19
|
+
* at `npm install typescript`.
|
|
20
|
+
*/
|
|
21
|
+
import { dirname, isAbsolute, relative, resolve } from 'node:path';
|
|
22
|
+
import { pathExists } from '../utils/fs.js';
|
|
23
|
+
import { verbose } from '../utils/logger.js';
|
|
24
|
+
import { composeShimSource, SHIM_FILENAME, SUPPRESSED_DIAGNOSTIC_CODES } from './typecheck-shim.js';
|
|
25
|
+
/**
|
|
26
|
+
* Sentinel string surfaced as a `TypecheckIssue.message` when the
|
|
27
|
+
* project's jsconfig sets `checkJs: false`. Exported so tests can
|
|
28
|
+
* pin the contract — operators rely on it to spot opted-out projects
|
|
29
|
+
* in CI logs.
|
|
30
|
+
*/
|
|
31
|
+
export const CHECK_JS_DISABLED_NOTICE = 'Project sets "checkJs: false" — skipping (override the jsconfig to enable typecheck).';
|
|
32
|
+
/**
|
|
33
|
+
* Runs `fireforge typecheck` against every project listed in `cfg.projects`.
|
|
34
|
+
*
|
|
35
|
+
* Per-project flow:
|
|
36
|
+
* 1. Read the jsconfig via the TS API. JSON parse / config-spec
|
|
37
|
+
* errors are surfaced as issues, not thrown — a single broken
|
|
38
|
+
* project must not abort the rest of the run.
|
|
39
|
+
* 2. Compute final compiler options from the user's options. We
|
|
40
|
+
* only force `noEmit: true` (this is a typecheck, not a build);
|
|
41
|
+
* we honour `strict`, `target`, `lib`, `module`, `paths`,
|
|
42
|
+
* `include`, `exclude`. `allowJs` and `checkJs` default to
|
|
43
|
+
* `true` only when the user has not set them — if the user set
|
|
44
|
+
* `checkJs: false` we treat that as an explicit opt-out and
|
|
45
|
+
* skip the project with a single notice (see {@link CHECK_JS_DISABLED_NOTICE}).
|
|
46
|
+
* 3. Inject the synthetic shim (built-in + optional extraShim) as
|
|
47
|
+
* a virtual root file that the custom CompilerHost serves.
|
|
48
|
+
* 4. Build the program; collect semantic, syntactic, options, and
|
|
49
|
+
* global diagnostics. The patchLint flow only reads semantic +
|
|
50
|
+
* syntactic — fine for hygiene, but a CI gate needs the full
|
|
51
|
+
* set so misconfigured `lib`/`paths` entries fail loudly.
|
|
52
|
+
* 5. Drop diagnostics whose code is in `SUPPRESSED_DIAGNOSTIC_CODES`
|
|
53
|
+
* and any diagnostic originating in the synthetic shim itself.
|
|
54
|
+
*
|
|
55
|
+
* @param projectRoot - Absolute project root. All paths in `cfg` are resolved against it.
|
|
56
|
+
* @param cfg - Validated `typecheck` block from `fireforge.json`.
|
|
57
|
+
* @returns One {@link TypecheckProjectResult} per entry in `cfg.projects`,
|
|
58
|
+
* in declared order. The CLI is responsible for printing the issues
|
|
59
|
+
* and computing the exit code.
|
|
60
|
+
*/
|
|
61
|
+
export async function runTypecheck(projectRoot, cfg) {
|
|
62
|
+
// Dynamic import — typescript stays a dev dependency. Same pattern
|
|
63
|
+
// as `patch-lint-checkjs.ts`; the empty-projects-array case is
|
|
64
|
+
// already rejected by config-validate, so we don't gate the import
|
|
65
|
+
// on `cfg.projects.length`.
|
|
66
|
+
let ts;
|
|
67
|
+
try {
|
|
68
|
+
ts = await import('typescript');
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
return cfg.projects.map((project) => ({
|
|
72
|
+
project,
|
|
73
|
+
issues: [
|
|
74
|
+
{
|
|
75
|
+
file: '(typecheck)',
|
|
76
|
+
line: 1,
|
|
77
|
+
column: 1,
|
|
78
|
+
code: 0,
|
|
79
|
+
category: 'error',
|
|
80
|
+
message: 'fireforge typecheck requires the "typescript" package. Run "npm install typescript" to enable type checking.',
|
|
81
|
+
project,
|
|
82
|
+
},
|
|
83
|
+
],
|
|
84
|
+
filesChecked: 0,
|
|
85
|
+
}));
|
|
86
|
+
}
|
|
87
|
+
// Compose the shim once — extraShim is shared across all projects.
|
|
88
|
+
// A missing or unreadable shim is a project-wide failure, so we
|
|
89
|
+
// surface it as one issue per project rather than letting one
|
|
90
|
+
// project's read failure silently affect the others' results.
|
|
91
|
+
let shimSource;
|
|
92
|
+
try {
|
|
93
|
+
const composed = await composeShimSource(projectRoot, cfg.extraShim);
|
|
94
|
+
shimSource = composed.source;
|
|
95
|
+
if (composed.extraShimAppended) {
|
|
96
|
+
verbose(`typecheck: extra shim ${cfg.extraShim ?? ''} appended to Firefox globals shim`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
catch (err) {
|
|
100
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
101
|
+
return cfg.projects.map((project) => ({
|
|
102
|
+
project,
|
|
103
|
+
issues: [
|
|
104
|
+
{
|
|
105
|
+
file: cfg.extraShim ?? '(typecheck)',
|
|
106
|
+
line: 1,
|
|
107
|
+
column: 1,
|
|
108
|
+
code: 0,
|
|
109
|
+
category: 'error',
|
|
110
|
+
message,
|
|
111
|
+
project,
|
|
112
|
+
},
|
|
113
|
+
],
|
|
114
|
+
filesChecked: 0,
|
|
115
|
+
}));
|
|
116
|
+
}
|
|
117
|
+
const results = [];
|
|
118
|
+
for (const projectPath of cfg.projects) {
|
|
119
|
+
results.push(await runTypecheckForProject(ts, projectRoot, projectPath, shimSource));
|
|
120
|
+
}
|
|
121
|
+
return results;
|
|
122
|
+
}
|
|
123
|
+
/** Runs typecheck for a single jsconfig path, isolating its failures. */
|
|
124
|
+
async function runTypecheckForProject(ts, projectRoot, projectPath, shimSource) {
|
|
125
|
+
const absConfig = resolve(projectRoot, projectPath);
|
|
126
|
+
if (!(await pathExists(absConfig))) {
|
|
127
|
+
return {
|
|
128
|
+
project: projectPath,
|
|
129
|
+
issues: [
|
|
130
|
+
{
|
|
131
|
+
file: projectPath,
|
|
132
|
+
line: 1,
|
|
133
|
+
column: 1,
|
|
134
|
+
code: 0,
|
|
135
|
+
category: 'error',
|
|
136
|
+
message: `jsconfig.json not found: ${projectPath} (resolved to ${absConfig})`,
|
|
137
|
+
project: projectPath,
|
|
138
|
+
},
|
|
139
|
+
],
|
|
140
|
+
filesChecked: 0,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
// 1) Read the JSON config. ts.readConfigFile reports JSON-shape
|
|
144
|
+
// errors via the returned diagnostic; missing files fall back to
|
|
145
|
+
// pathExists above, which gives a more directly actionable message.
|
|
146
|
+
const readResult = ts.readConfigFile(absConfig, (path) => ts.sys.readFile(path));
|
|
147
|
+
if (readResult.error) {
|
|
148
|
+
return {
|
|
149
|
+
project: projectPath,
|
|
150
|
+
issues: [diagnosticToIssue(ts, readResult.error, projectPath, projectPath)],
|
|
151
|
+
filesChecked: 0,
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
// 2) Parse the config content. This is what surfaces config-spec
|
|
155
|
+
// errors (unknown options, mismatched types in `compilerOptions`,
|
|
156
|
+
// bad `include` patterns, etc.) — TS5xxx codes. We surface them
|
|
157
|
+
// alongside semantic diagnostics so the operator sees the same
|
|
158
|
+
// output `tsc -p` would have produced.
|
|
159
|
+
const parsed = ts.parseJsonConfigFileContent(readResult.config, ts.sys, dirname(absConfig),
|
|
160
|
+
/* existingOptions */ undefined, absConfig);
|
|
161
|
+
const issues = [];
|
|
162
|
+
for (const diag of parsed.errors) {
|
|
163
|
+
if (SUPPRESSED_DIAGNOSTIC_CODES.has(diag.code))
|
|
164
|
+
continue;
|
|
165
|
+
issues.push(diagnosticToIssue(ts, diag, absConfig, projectPath));
|
|
166
|
+
}
|
|
167
|
+
// 3) Honour explicit `checkJs: false`. The user has opted out for
|
|
168
|
+
// an IDE reason (likely "checkJs floods my workflow with non-actionable
|
|
169
|
+
// notes"); flipping it on here would surface ~hundreds of issues that
|
|
170
|
+
// the operator already evaluated and rejected. Surface a single
|
|
171
|
+
// notice so it is visible in CI logs rather than silently passing.
|
|
172
|
+
const rawConfig = readResult.config;
|
|
173
|
+
if (rawConfig?.compilerOptions?.['checkJs'] === false) {
|
|
174
|
+
issues.push({
|
|
175
|
+
file: projectPath,
|
|
176
|
+
line: 1,
|
|
177
|
+
column: 1,
|
|
178
|
+
code: 0,
|
|
179
|
+
category: 'warning',
|
|
180
|
+
message: CHECK_JS_DISABLED_NOTICE,
|
|
181
|
+
project: projectPath,
|
|
182
|
+
});
|
|
183
|
+
return { project: projectPath, issues, filesChecked: parsed.fileNames.length };
|
|
184
|
+
}
|
|
185
|
+
// 4) Compute final compiler options. `noEmit: true` is forced — we
|
|
186
|
+
// never write artifacts. `allowJs` / `checkJs` default to true
|
|
187
|
+
// *only* when unset (so a user can flip them off without us
|
|
188
|
+
// overriding); if the user set `allowJs: false` they're saying
|
|
189
|
+
// "don't even include JS in this typecheck", which is rare but
|
|
190
|
+
// legitimate (e.g. an isolated `.d.ts`-only project).
|
|
191
|
+
const options = {
|
|
192
|
+
...parsed.options,
|
|
193
|
+
noEmit: true,
|
|
194
|
+
allowJs: parsed.options.allowJs ?? true,
|
|
195
|
+
checkJs: parsed.options.checkJs ?? true,
|
|
196
|
+
// skipLibCheck is not forced; the user owns it via their jsconfig.
|
|
197
|
+
};
|
|
198
|
+
// 5) The synthetic shim file. Use a project-rooted path with a
|
|
199
|
+
// hidden-style prefix so it is unlikely to collide with any real
|
|
200
|
+
// file — and never write it to disk. The CompilerHost below serves
|
|
201
|
+
// it from `shimSource` for `fileExists`/`readFile`/`getSourceFile`.
|
|
202
|
+
const projectDir = dirname(absConfig);
|
|
203
|
+
const shimPath = resolve(projectDir, `.fireforge-${SHIM_FILENAME}`);
|
|
204
|
+
const rootFiles = [...parsed.fileNames, shimPath];
|
|
205
|
+
const defaultHost = ts.createCompilerHost(options);
|
|
206
|
+
const host = {
|
|
207
|
+
...defaultHost,
|
|
208
|
+
getSourceFile(fileName, languageVersion, onError, shouldCreate) {
|
|
209
|
+
if (fileName === shimPath) {
|
|
210
|
+
return ts.createSourceFile(fileName, shimSource, languageVersion, true);
|
|
211
|
+
}
|
|
212
|
+
return defaultHost.getSourceFile(fileName, languageVersion, onError, shouldCreate);
|
|
213
|
+
},
|
|
214
|
+
fileExists(fileName) {
|
|
215
|
+
if (fileName === shimPath)
|
|
216
|
+
return true;
|
|
217
|
+
return defaultHost.fileExists(fileName);
|
|
218
|
+
},
|
|
219
|
+
readFile(fileName) {
|
|
220
|
+
if (fileName === shimPath)
|
|
221
|
+
return shimSource;
|
|
222
|
+
return defaultHost.readFile(fileName);
|
|
223
|
+
},
|
|
224
|
+
};
|
|
225
|
+
const program = ts.createProgram(rootFiles, options, host);
|
|
226
|
+
// Collect the full diagnostic set. patchLint reads only semantic +
|
|
227
|
+
// syntactic — fine for hygiene, wrong for CI: a misconfigured
|
|
228
|
+
// `lib: ["es2015"]` or a missing `paths` target should fail
|
|
229
|
+
// typecheck loudly via getOptionsDiagnostics / getGlobalDiagnostics.
|
|
230
|
+
const allDiagnostics = [
|
|
231
|
+
...program.getOptionsDiagnostics(),
|
|
232
|
+
...program.getGlobalDiagnostics(),
|
|
233
|
+
...program.getSyntacticDiagnostics(),
|
|
234
|
+
...program.getSemanticDiagnostics(),
|
|
235
|
+
];
|
|
236
|
+
for (const diag of allDiagnostics) {
|
|
237
|
+
if (SUPPRESSED_DIAGNOSTIC_CODES.has(diag.code))
|
|
238
|
+
continue;
|
|
239
|
+
// Drop diagnostics that originate in the synthetic shim — operators
|
|
240
|
+
// can't act on them and they would clutter CI logs.
|
|
241
|
+
if (diag.file?.fileName === shimPath)
|
|
242
|
+
continue;
|
|
243
|
+
issues.push(diagnosticToIssue(ts, diag, absConfig, projectPath));
|
|
244
|
+
}
|
|
245
|
+
verbose(`typecheck: ${projectPath} — analyzed ${String(parsed.fileNames.length)} file(s), found ${String(issues.length)} issue(s)`);
|
|
246
|
+
return {
|
|
247
|
+
project: projectPath,
|
|
248
|
+
issues,
|
|
249
|
+
filesChecked: parsed.fileNames.length,
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Converts a TS Diagnostic to a TypecheckIssue. The `fallbackFile`
|
|
254
|
+
* is used when the diagnostic carries no source file (typical for
|
|
255
|
+
* options diagnostics) — typically the absolute jsconfig path or
|
|
256
|
+
* the project-relative form for surface-level errors. `project` is
|
|
257
|
+
* threaded through so the CLI can group issues by project without
|
|
258
|
+
* a second pass.
|
|
259
|
+
*/
|
|
260
|
+
function diagnosticToIssue(ts, diag, fallbackFile, project) {
|
|
261
|
+
let file = fallbackFile;
|
|
262
|
+
let line = 1;
|
|
263
|
+
let column = 1;
|
|
264
|
+
if (diag.file) {
|
|
265
|
+
file = diag.file.fileName;
|
|
266
|
+
if (typeof diag.start === 'number') {
|
|
267
|
+
const lc = diag.file.getLineAndCharacterOfPosition(diag.start);
|
|
268
|
+
line = lc.line + 1;
|
|
269
|
+
column = lc.character + 1;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
const message = typeof diag.messageText === 'string'
|
|
273
|
+
? diag.messageText
|
|
274
|
+
: ts.flattenDiagnosticMessageText(diag.messageText, '\n');
|
|
275
|
+
// Suggestion + Message categories collapse to 'warning'; only
|
|
276
|
+
// Error stays an error. This matches what the CLI then displays.
|
|
277
|
+
const category = diag.category === ts.DiagnosticCategory.Error ? 'error' : 'warning';
|
|
278
|
+
return {
|
|
279
|
+
file,
|
|
280
|
+
line,
|
|
281
|
+
column,
|
|
282
|
+
code: diag.code,
|
|
283
|
+
category,
|
|
284
|
+
message,
|
|
285
|
+
project,
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Converts an absolute path to a path relative to the project root,
|
|
290
|
+
* for display in CLI output. Falls back to the absolute path when
|
|
291
|
+
* the path lies outside the root (e.g. a `node_modules` symlinked
|
|
292
|
+
* from elsewhere). Exposed for tests and the CLI.
|
|
293
|
+
*/
|
|
294
|
+
export function relativeForDisplay(projectRoot, absoluteFile) {
|
|
295
|
+
if (!isAbsolute(absoluteFile))
|
|
296
|
+
return absoluteFile;
|
|
297
|
+
const rel = relative(projectRoot, absoluteFile);
|
|
298
|
+
if (rel === '' || rel.startsWith('..'))
|
|
299
|
+
return absoluteFile;
|
|
300
|
+
return rel;
|
|
301
|
+
}
|
|
302
|
+
//# sourceMappingURL=typecheck.js.map
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
* The upstream xpcshell harness computes the manifest key for the appdir
|
|
9
9
|
* override as `mozInfo["appname"] + "-appdir"`. On a stock Firefox build the
|
|
10
10
|
* key is `firefox-appdir`, so the very common `firefox-appdir = "browser"`
|
|
11
|
-
* directive is honoured. On a rebranded fork (appname=`
|
|
12
|
-
*
|
|
11
|
+
* directive is honoured. On a rebranded fork (appname=`mybrowser`, …) the
|
|
12
|
+
* harness looks for `mybrowser-appdir`
|
|
13
13
|
* — the literal `firefox-appdir` line is silently ignored, `appPath` falls
|
|
14
14
|
* back to `xrePath`, and every `resource:///modules/…` import throws
|
|
15
15
|
* `Failed to load resource:///modules/<name>.sys.mjs` because xpcshell now
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
* The upstream xpcshell harness computes the manifest key for the appdir
|
|
10
10
|
* override as `mozInfo["appname"] + "-appdir"`. On a stock Firefox build the
|
|
11
11
|
* key is `firefox-appdir`, so the very common `firefox-appdir = "browser"`
|
|
12
|
-
* directive is honoured. On a rebranded fork (appname=`
|
|
13
|
-
*
|
|
12
|
+
* directive is honoured. On a rebranded fork (appname=`mybrowser`, …) the
|
|
13
|
+
* harness looks for `mybrowser-appdir`
|
|
14
14
|
* — the literal `firefox-appdir` line is silently ignored, `appPath` falls
|
|
15
15
|
* back to `xrePath`, and every `resource:///modules/…` import throws
|
|
16
16
|
* `Failed to load resource:///modules/<name>.sys.mjs` because xpcshell now
|
|
@@ -440,7 +440,7 @@ export interface FurnaceCreateOptions {
|
|
|
440
440
|
compose?: string[];
|
|
441
441
|
/**
|
|
442
442
|
* Participate in a pre-existing feature-scoped Fluent bundle at this
|
|
443
|
-
* path (as used by `insertFTLIfNeeded`, e.g. `browser/
|
|
443
|
+
* path (as used by `insertFTLIfNeeded`, e.g. `browser/mybrowser-dock.ftl`)
|
|
444
444
|
* instead of scaffolding a per-component `.ftl`. Implies `localized`.
|
|
445
445
|
* Persists onto the furnace.json entry so validation and apply skip the
|
|
446
446
|
* per-component paths.
|
|
@@ -44,6 +44,8 @@ export interface FireForgeConfig {
|
|
|
44
44
|
wire?: WireConfig;
|
|
45
45
|
/** Patch lint configuration */
|
|
46
46
|
patchLint?: PatchLintConfig;
|
|
47
|
+
/** Typecheck command configuration (CI-grade, whole-project) */
|
|
48
|
+
typecheck?: TypecheckConfig;
|
|
47
49
|
/**
|
|
48
50
|
* Project marker prefix appended to lines FireForge writes into
|
|
49
51
|
* upstream Firefox source files (e.g. the `customElements.js` tag list).
|
|
@@ -52,6 +54,29 @@ export interface FireForgeConfig {
|
|
|
52
54
|
*/
|
|
53
55
|
markerComment?: string;
|
|
54
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* Configuration for the `fireforge typecheck` command. Distinct from
|
|
59
|
+
* `patchLint.checkJs`: patch-lint runs every time `fireforge lint` runs
|
|
60
|
+
* and is scoped to patch-owned `.sys.mjs`; typecheck runs whole projects
|
|
61
|
+
* the operator points at via `projects` and is intended as a CI gate.
|
|
62
|
+
*/
|
|
63
|
+
export interface TypecheckConfig {
|
|
64
|
+
/**
|
|
65
|
+
* Project-relative paths to jsconfig.json (or tsconfig.json) files
|
|
66
|
+
* the typecheck command should run. Must be non-empty when the
|
|
67
|
+
* `typecheck` block is present — an empty array would silently turn
|
|
68
|
+
* the command into a no-op.
|
|
69
|
+
*/
|
|
70
|
+
projects: string[];
|
|
71
|
+
/**
|
|
72
|
+
* Optional project-relative path to an additional `.d.ts` file whose
|
|
73
|
+
* contents are concatenated to the built-in `FIREFOX_GLOBALS_SHIM`.
|
|
74
|
+
* Lets projects declare component patterns like `MozLitElement` /
|
|
75
|
+
* `MozXULElement` once instead of per-file. Concat order is
|
|
76
|
+
* built-in shim first, extraShim second — augment, don't redeclare.
|
|
77
|
+
*/
|
|
78
|
+
extraShim?: string;
|
|
79
|
+
}
|
|
55
80
|
/**
|
|
56
81
|
* Wire command configuration.
|
|
57
82
|
*/
|
|
@@ -70,6 +95,14 @@ export type PatchLintSeverityGate = 'off' | 'warning' | 'error';
|
|
|
70
95
|
export interface PatchLintConfig {
|
|
71
96
|
/** Enable TypeScript checkJs pass on patch-owned .sys.mjs files */
|
|
72
97
|
checkJs?: boolean;
|
|
98
|
+
/**
|
|
99
|
+
* Project-relative path to an additional `.d.ts` file whose contents
|
|
100
|
+
* are concatenated to the built-in `FIREFOX_GLOBALS_SHIM` for the
|
|
101
|
+
* `patchLint.checkJs` pass. Same semantics as `typecheck.extraShim`
|
|
102
|
+
* but scoped to the patch-hygiene flow. Default unset = current
|
|
103
|
+
* behaviour (built-in shim only).
|
|
104
|
+
*/
|
|
105
|
+
checkJsExtraShim?: string;
|
|
73
106
|
/** File paths exempt from the raw-color-value check (exact or basename match) */
|
|
74
107
|
rawColorAllowlist?: string[];
|
|
75
108
|
/** Enforce JSDoc on class-method exports in patch-owned .sys.mjs files. Default: 'off'. */
|
|
@@ -70,7 +70,7 @@ export interface CustomComponentConfig {
|
|
|
70
70
|
/**
|
|
71
71
|
* Path of a pre-existing feature-scoped Fluent bundle this component
|
|
72
72
|
* participates in, in the same form used by `insertFTLIfNeeded` (for
|
|
73
|
-
* example `browser/
|
|
73
|
+
* example `browser/mybrowser-dock.ftl`). When set:
|
|
74
74
|
*
|
|
75
75
|
* - `furnace create --localized` does NOT scaffold a per-component
|
|
76
76
|
* `.ftl` stub — the component shares the feature bundle.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types for the `fireforge typecheck` command.
|
|
3
|
+
*
|
|
4
|
+
* Kept separate from `PatchLintIssue` because the two flows model
|
|
5
|
+
* different things: patch-lint issues are keyed on a stable `check`
|
|
6
|
+
* rule ID (consumed by `lintIgnore`, severity gates, and the
|
|
7
|
+
* cross-patch tagger), while typecheck issues carry a raw TypeScript
|
|
8
|
+
* diagnostic code that should never enter the patch-lint vocabulary.
|
|
9
|
+
* Conflating them would let `lintIgnore` accidentally suppress TS
|
|
10
|
+
* errors and would force `PatchLintIssue` to grow line / column /
|
|
11
|
+
* code fields that have no meaning for patch-hygiene rules.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* A single diagnostic produced by `runTypecheck` for one source file.
|
|
15
|
+
*/
|
|
16
|
+
export interface TypecheckIssue {
|
|
17
|
+
/** Absolute path to the source file the diagnostic originated in. */
|
|
18
|
+
file: string;
|
|
19
|
+
/** 1-based line number. */
|
|
20
|
+
line: number;
|
|
21
|
+
/** 1-based column number. */
|
|
22
|
+
column: number;
|
|
23
|
+
/** Raw TypeScript diagnostic code (e.g. 2322 for a type mismatch). */
|
|
24
|
+
code: number;
|
|
25
|
+
/**
|
|
26
|
+
* Severity bucket — TS reports `Suggestion` and `Message` categories
|
|
27
|
+
* too, but `runTypecheck` collapses both into `'warning'` so the CLI
|
|
28
|
+
* has only two visible levels.
|
|
29
|
+
*/
|
|
30
|
+
category: 'error' | 'warning';
|
|
31
|
+
/** Human-readable message text (already flattened from chains). */
|
|
32
|
+
message: string;
|
|
33
|
+
/**
|
|
34
|
+
* Project-relative path of the originating jsconfig.json. Useful
|
|
35
|
+
* when typecheck.projects names multiple projects and the operator
|
|
36
|
+
* needs to know which one fired.
|
|
37
|
+
*/
|
|
38
|
+
project: string;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Per-project typecheck output. One entry per `typecheck.projects`
|
|
42
|
+
* jsconfig path, in the order the projects were declared.
|
|
43
|
+
*/
|
|
44
|
+
export interface TypecheckProjectResult {
|
|
45
|
+
/** Project-relative path of the jsconfig.json. */
|
|
46
|
+
project: string;
|
|
47
|
+
/** All issues from this project (errors + warnings). */
|
|
48
|
+
issues: TypecheckIssue[];
|
|
49
|
+
/** How many root files the program was built against (excludes the synthetic shim). */
|
|
50
|
+
filesChecked: number;
|
|
51
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
+
/**
|
|
3
|
+
* Types for the `fireforge typecheck` command.
|
|
4
|
+
*
|
|
5
|
+
* Kept separate from `PatchLintIssue` because the two flows model
|
|
6
|
+
* different things: patch-lint issues are keyed on a stable `check`
|
|
7
|
+
* rule ID (consumed by `lintIgnore`, severity gates, and the
|
|
8
|
+
* cross-patch tagger), while typecheck issues carry a raw TypeScript
|
|
9
|
+
* diagnostic code that should never enter the patch-lint vocabulary.
|
|
10
|
+
* Conflating them would let `lintIgnore` accidentally suppress TS
|
|
11
|
+
* errors and would force `PatchLintIssue` to grow line / column /
|
|
12
|
+
* code fields that have no meaning for patch-hygiene rules.
|
|
13
|
+
*/
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=typecheck.js.map
|