@warlock.js/core 5.33.0 → 5.34.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 +26 -46
- package/esm/cli/commands/check/check-command.action.mjs +2 -1
- package/esm/cli/commands/check/check-command.action.mjs.map +1 -1
- package/esm/cli/commands/check.command.mjs +2 -2
- package/esm/cli/commands/check.command.mjs.map +1 -1
- package/esm/cli/commands/e2e.command.mjs +63 -0
- package/esm/cli/commands/e2e.command.mjs.map +1 -0
- package/esm/cli/commands/load-e2e-spec.mjs +47 -0
- package/esm/cli/commands/load-e2e-spec.mjs.map +1 -0
- package/esm/cli/framework-cli-commands.mjs +2 -0
- package/esm/cli/framework-cli-commands.mjs.map +1 -1
- package/esm/dev-server/health-checker/checkers/oxlint-health-checker.mjs +1 -1
- package/esm/dev-server/health-checker/default-health-checkers.mjs +1 -6
- package/esm/dev-server/health-checker/default-health-checkers.mjs.map +1 -1
- package/esm/dev-server/health-checker/file-health-checker.contract.d.mts +0 -2
- package/esm/dev-server/health-checker/file-health-checker.contract.d.mts.map +1 -1
- package/esm/dev-server/health-checker/file-health-result.d.mts +1 -1
- package/esm/dev-server/health-checker/file-health-result.mjs.map +1 -1
- package/esm/e2e/browser.d.mts +4 -0
- package/esm/e2e/browser.d.mts.map +1 -0
- package/esm/e2e/browser.mjs +88 -0
- package/esm/e2e/browser.mjs.map +1 -0
- package/esm/e2e/cdp.d.mts +152 -0
- package/esm/e2e/cdp.d.mts.map +1 -0
- package/esm/e2e/cdp.mjs +106 -0
- package/esm/e2e/cdp.mjs.map +1 -0
- package/esm/e2e/fixture.mjs +195 -0
- package/esm/e2e/fixture.mjs.map +1 -0
- package/esm/e2e/index.d.mts +5 -0
- package/esm/e2e/index.mjs +6 -0
- package/esm/e2e/owned-process.mjs +193 -0
- package/esm/e2e/owned-process.mjs.map +1 -0
- package/esm/e2e/page.d.mts +64 -0
- package/esm/e2e/page.d.mts.map +1 -0
- package/esm/e2e/page.mjs +376 -0
- package/esm/e2e/page.mjs.map +1 -0
- package/esm/e2e/run-e2e.d.mts +17 -0
- package/esm/e2e/run-e2e.d.mts.map +1 -0
- package/esm/e2e/run-e2e.mjs +143 -0
- package/esm/e2e/run-e2e.mjs.map +1 -0
- package/esm/e2e/types.d.mts +123 -0
- package/esm/e2e/types.d.mts.map +1 -0
- package/esm/e2e/types.mjs +24 -0
- package/esm/e2e/types.mjs.map +1 -0
- package/esm/secrets/errors.d.mts +1 -1
- package/esm/secrets/errors.d.mts.map +1 -1
- package/esm/secrets/errors.mjs +2 -0
- package/esm/secrets/errors.mjs.map +1 -1
- package/esm/secrets/resolve-driver.mjs +14 -0
- package/esm/secrets/resolve-driver.mjs.map +1 -0
- package/esm/secrets/secret-store.d.mts.map +1 -1
- package/esm/secrets/secret-store.mjs +4 -1
- package/esm/secrets/secret-store.mjs.map +1 -1
- package/esm/secrets/secrets.d.mts.map +1 -1
- package/esm/secrets/secrets.mjs +10 -1
- package/esm/secrets/secrets.mjs.map +1 -1
- package/esm/secrets/types.d.mts +4 -0
- package/esm/secrets/types.d.mts.map +1 -1
- package/esm/tooling/check/lint-step.d.mts +3 -3
- package/esm/tooling/check/lint-step.d.mts.map +1 -1
- package/esm/tooling/check/lint-step.mjs +3 -47
- package/esm/tooling/check/lint-step.mjs.map +1 -1
- package/esm/tooling/check/run-check.d.mts +2 -2
- package/esm/tooling/check/run-check.mjs +4 -2
- package/esm/tooling/check/run-check.mjs.map +1 -1
- package/esm/tooling/problem.d.mts +1 -1
- package/esm/tooling/problem.d.mts.map +1 -1
- package/esm/tooling/problem.mjs.map +1 -1
- package/esm/updater/package-manager.mjs +5 -1
- package/esm/updater/package-manager.mjs.map +1 -1
- package/esm/upgrade/codemods/index.mjs +2 -1
- package/esm/upgrade/codemods/index.mjs.map +1 -1
- package/esm/upgrade/codemods/oxc-toolchain.mjs +59 -10
- package/esm/upgrade/codemods/oxc-toolchain.mjs.map +1 -1
- package/esm/upgrade/codemods/oxlint-rule-schemas.mjs +6 -0
- package/esm/upgrade/codemods/oxlint-rule-schemas.mjs.map +1 -0
- package/esm/upgrade/codemods/port-eslint-rules.mjs +343 -0
- package/esm/upgrade/codemods/port-eslint-rules.mjs.map +1 -0
- package/esm/upgrade/codemods/toolchain-templates.mjs +1 -1
- package/esm/upgrade/codemods/toolchain-templates.mjs.map +1 -1
- package/esm/upgrade/codemods/validate-oxlint-rule.mjs +60 -0
- package/esm/upgrade/codemods/validate-oxlint-rule.mjs.map +1 -0
- package/esm/upgrade/notes.mjs +14 -7
- package/esm/upgrade/notes.mjs.map +1 -1
- package/esm/warlock-config/types.d.mts +0 -1
- package/esm/warlock-config/types.d.mts.map +1 -1
- package/llms-full.txt +243 -41
- package/llms.txt +2 -1
- package/package.json +19 -20
- package/skills/create-module/SKILL.md +2 -2
- package/skills/run-app/SKILL.md +3 -3
- package/skills/store-secrets/SKILL.md +40 -1
- package/skills/test-browser/SKILL.md +119 -0
- package/skills/upgrade-from-5-29/SKILL.md +70 -29
- package/skills/warlock-check/SKILL.md +3 -3
- package/skills/warlock-doctor/SKILL.md +2 -3
- package/esm/dev-server/health-checker/checkers/eslint-health-checker.mjs +0 -152
- package/esm/dev-server/health-checker/checkers/eslint-health-checker.mjs.map +0 -1
- package/esm/dev-server/health-checker/eslint-support.mjs +0 -27
- package/esm/dev-server/health-checker/eslint-support.mjs.map +0 -1
- package/esm/dev-server/health-checker/workers/eslint-health.worker.d.mts +0 -1
- package/esm/dev-server/health-checker/workers/eslint-health.worker.mjs +0 -183
- package/esm/dev-server/health-checker/workers/eslint-health.worker.mjs.map +0 -1
package/esm/secrets/types.d.mts
CHANGED
|
@@ -6,6 +6,10 @@ export interface SecretBackend {
|
|
|
6
6
|
remove(namespace: string, name: string): Promise<boolean>;
|
|
7
7
|
}
|
|
8
8
|
export type SecretsConfigurations = {
|
|
9
|
+
/** auto selects keychain/environment/files; memory is isolated to this process. */
|
|
10
|
+
driver?: "auto" | "memory";
|
|
11
|
+
/** Explicitly permit the volatile memory driver under NODE_ENV=production. */
|
|
12
|
+
allowMemoryInProduction?: boolean;
|
|
9
13
|
/** Stable identity shared only by processes belonging to this app installation. */
|
|
10
14
|
namespace?: string;
|
|
11
15
|
/** Trusted parent location; defaults to storage/secrets. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.mts","names":[],"sources":["../../../../../../../../packages/core/src/secrets/types.ts"],"mappings":";;iBACiB;EACf,IAAI,mBAAmB,eAAe;EACtC,IAAI,mBAAmB,cAAc,gBAAgB;EACrD,OAAO,mBAAmB,eAAe;;YAG/B;;EAEV;;EAEA;;YAGU,qBAAqB;EAC/B;;EAEA,UAAU;;EAEV"}
|
|
1
|
+
{"version":3,"file":"types.d.mts","names":[],"sources":["../../../../../../../../packages/core/src/secrets/types.ts"],"mappings":";;iBACiB;EACf,IAAI,mBAAmB,eAAe;EACtC,IAAI,mBAAmB,cAAc,gBAAgB;EACrD,OAAO,mBAAmB,eAAe;;YAG/B;;EAEV;;EAEA;;EAEA;;EAEA;;YAGU,qBAAqB;EAC/B;;EAEA,UAAU;;EAEV"}
|
|
@@ -3,10 +3,10 @@ import { ToolingProblem } from "../problem.mjs";
|
|
|
3
3
|
/** What the lint step found, and which linters ran. */
|
|
4
4
|
export type LintOutcome = {
|
|
5
5
|
problems: ToolingProblem[];
|
|
6
|
-
/** The linters that ran (`
|
|
6
|
+
/** The linters that ran (`oxlint`); empty when the app configures none. */
|
|
7
7
|
linters: string[];
|
|
8
8
|
};
|
|
9
|
-
/**
|
|
10
|
-
export declare function runLint(cwd: string, files: readonly string[]
|
|
9
|
+
/** Run configured Oxlint over lintable source files. */
|
|
10
|
+
export declare function runLint(cwd: string, files: readonly string[]): Promise<LintOutcome>;
|
|
11
11
|
//#endregion
|
|
12
12
|
//# sourceMappingURL=lint-step.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lint-step.d.mts","names":[],"sources":["../../../../../../../../../packages/core/src/tooling/check/lint-step.ts"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"lint-step.d.mts","names":[],"sources":["../../../../../../../../../packages/core/src/tooling/check/lint-step.ts"],"mappings":";;;YASY;EACV,UAAU;;EAEV;;;wBAmDoB,QAAQ,aAAa,2BAA2B,QAAQ"}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import { hasEslint, warnEslintDeprecation } from "../../dev-server/health-checker/eslint-support.mjs";
|
|
2
1
|
import { OxlintRunner, findOxlint, hasOxlintConfig } from "../../dev-server/health-checker/oxlint-runner.mjs";
|
|
3
2
|
import { createProblem } from "../problem.mjs";
|
|
4
3
|
import path from "node:path";
|
|
5
|
-
import { ESLint } from "eslint";
|
|
6
4
|
|
|
7
5
|
//#region ../../packages/core/src/tooling/check/lint-step.ts
|
|
8
6
|
const LINTABLE = /\.[cm]?[jt]sx?$/i;
|
|
@@ -19,31 +17,6 @@ function toolFailure(tool, error) {
|
|
|
19
17
|
message: `${tool} could not run: ${message.split("\n")[0]}`
|
|
20
18
|
});
|
|
21
19
|
}
|
|
22
|
-
async function runEslint(cwd, files) {
|
|
23
|
-
const results = await new ESLint({
|
|
24
|
-
cwd,
|
|
25
|
-
errorOnUnmatchedPattern: false,
|
|
26
|
-
warnIgnored: false
|
|
27
|
-
}).lintFiles([...files]);
|
|
28
|
-
const problems = [];
|
|
29
|
-
for (const result of results) {
|
|
30
|
-
const file = path.relative(cwd, result.filePath).split(path.sep).join("/");
|
|
31
|
-
for (const message of result.messages) {
|
|
32
|
-
const error = message.severity === 2 || message.fatal === true;
|
|
33
|
-
problems.push(createProblem({
|
|
34
|
-
code: error ? "WL7201" : "WL7202",
|
|
35
|
-
source: "eslint",
|
|
36
|
-
severity: error ? "error" : "warning",
|
|
37
|
-
message: message.message,
|
|
38
|
-
file,
|
|
39
|
-
line: message.line || null,
|
|
40
|
-
column: message.column || null,
|
|
41
|
-
rule: message.ruleId ?? null
|
|
42
|
-
}));
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
return problems;
|
|
46
|
-
}
|
|
47
20
|
async function runOxlint(cwd, files) {
|
|
48
21
|
const runner = new OxlintRunner();
|
|
49
22
|
runner.initialize(cwd);
|
|
@@ -65,8 +38,8 @@ async function runOxlint(cwd, files) {
|
|
|
65
38
|
await runner.shutdown();
|
|
66
39
|
}
|
|
67
40
|
}
|
|
68
|
-
/**
|
|
69
|
-
async function runLint(cwd, files
|
|
41
|
+
/** Run configured Oxlint over lintable source files. */
|
|
42
|
+
async function runLint(cwd, files) {
|
|
70
43
|
const lintable = files.filter((file) => LINTABLE.test(file));
|
|
71
44
|
const problems = [];
|
|
72
45
|
const linters = [];
|
|
@@ -74,24 +47,7 @@ async function runLint(cwd, files, selection = "oxlint") {
|
|
|
74
47
|
problems,
|
|
75
48
|
linters
|
|
76
49
|
};
|
|
77
|
-
if (
|
|
78
|
-
warnEslintDeprecation();
|
|
79
|
-
if (!hasEslint(cwd)) return {
|
|
80
|
-
linters: ["eslint"],
|
|
81
|
-
problems: [createProblem({
|
|
82
|
-
code: "WL8002",
|
|
83
|
-
source: "environment",
|
|
84
|
-
message: "Cannot find ESLint flat config in the app."
|
|
85
|
-
})]
|
|
86
|
-
};
|
|
87
|
-
linters.push("eslint");
|
|
88
|
-
try {
|
|
89
|
-
problems.push(...await runEslint(cwd, lintable));
|
|
90
|
-
} catch (error) {
|
|
91
|
-
problems.push(toolFailure("ESLint", error));
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
if (selection === "oxlint" && hasOxlintConfig(cwd)) {
|
|
50
|
+
if (hasOxlintConfig(cwd)) {
|
|
95
51
|
linters.push("oxlint");
|
|
96
52
|
if (!findOxlint(cwd)) problems.push(createProblem({
|
|
97
53
|
code: "WL8002",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lint-step.mjs","names":[],"sources":["../../../../../../../../../packages/core/src/tooling/check/lint-step.ts"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"file":"lint-step.mjs","names":[],"sources":["../../../../../../../../../packages/core/src/tooling/check/lint-step.ts"],"sourcesContent":["import path from \"node:path\";\nimport {\n findOxlint,\n hasOxlintConfig,\n OxlintRunner,\n} from \"../../dev-server/health-checker/oxlint-runner\";\nimport { createProblem, type ToolingProblem } from \"../problem\";\n\n/** What the lint step found, and which linters ran. */\nexport type LintOutcome = {\n problems: ToolingProblem[];\n /** The linters that ran (`oxlint`); empty when the app configures none. */\n linters: string[];\n};\n\nconst LINTABLE = /\\.[cm]?[jt]sx?$/i;\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\n/** A missing package/plugin is the machine's install; anything else is the tool crashing. */\nfunction toolFailure(tool: string, error: unknown): ToolingProblem {\n const message = errorMessage(error);\n const missing = /cannot find (?:module|package)|ERR_MODULE_NOT_FOUND/i.test(message);\n\n return createProblem({\n code: missing ? \"WL8002\" : \"WL8007\",\n source: \"environment\",\n message: `${tool} could not run: ${message.split(\"\\n\")[0]}`,\n });\n}\n\nasync function runOxlint(cwd: string, files: readonly string[]): Promise<ToolingProblem[]> {\n const runner = new OxlintRunner();\n\n runner.initialize(cwd);\n\n try {\n const results = await runner.checkFiles(\n files.map((file) => ({ path: path.join(cwd, file), relativePath: file })),\n );\n\n return results.flatMap((result) =>\n [...result.errors, ...result.warnings].map((message) =>\n createProblem({\n code: message.type === \"error\" ? \"WL7201\" : \"WL7202\",\n source: \"oxlint\",\n severity: message.type,\n message: message.message,\n file: message.relativePath,\n line: message.lineNumber,\n column: message.columnNumber,\n rule: message.ruleId ?? null,\n }),\n ),\n );\n } finally {\n await runner.shutdown();\n }\n}\n\n/** Run configured Oxlint over lintable source files. */\nexport async function runLint(cwd: string, files: readonly string[]): Promise<LintOutcome> {\n const lintable = files.filter((file) => LINTABLE.test(file));\n const problems: ToolingProblem[] = [];\n const linters: string[] = [];\n\n if (lintable.length === 0) return { problems, linters };\n\n if (hasOxlintConfig(cwd)) {\n linters.push(\"oxlint\");\n\n if (!findOxlint(cwd)) {\n problems.push(\n createProblem({\n code: \"WL8002\",\n source: \"environment\",\n message: \"An oxlint config exists but the oxlint package is not installed in the app.\",\n }),\n );\n } else {\n try {\n problems.push(...(await runOxlint(cwd, lintable)));\n } catch (error) {\n problems.push(toolFailure(\"oxlint\", error));\n }\n }\n }\n\n return { problems, linters };\n}\n"],"mappings":";;;;;AAeA,MAAM,WAAW;AAEjB,SAAS,aAAa,OAAwB;CAC5C,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAC9D;;AAGA,SAAS,YAAY,MAAc,OAAgC;CACjE,MAAM,UAAU,aAAa,KAAK;CAClC,MAAM,UAAU,uDAAuD,KAAK,OAAO;CAEnF,OAAO,cAAc;EACnB,MAAM,UAAU,WAAW;EAC3B,QAAQ;EACR,SAAS,GAAG,KAAK,kBAAkB,QAAQ,MAAM,IAAI,CAAC,CAAC;CACzD,CAAC;AACH;AAEA,eAAe,UAAU,KAAa,OAAqD;CACzF,MAAM,SAAS,IAAI,aAAa;CAEhC,OAAO,WAAW,GAAG;CAErB,IAAI;EAKF,QAAO,MAJe,OAAO,WAC3B,MAAM,KAAK,UAAU;GAAE,MAAM,KAAK,KAAK,KAAK,IAAI;GAAG,cAAc;EAAK,EAAE,CAC1E,EAEc,CAAC,SAAS,WACtB,CAAC,GAAG,OAAO,QAAQ,GAAG,OAAO,QAAQ,CAAC,CAAC,KAAK,YAC1C,cAAc;GACZ,MAAM,QAAQ,SAAS,UAAU,WAAW;GAC5C,QAAQ;GACR,UAAU,QAAQ;GAClB,SAAS,QAAQ;GACjB,MAAM,QAAQ;GACd,MAAM,QAAQ;GACd,QAAQ,QAAQ;GAChB,MAAM,QAAQ,UAAU;EAC1B,CAAC,CACH,CACF;CACF,UAAU;EACR,MAAM,OAAO,SAAS;CACxB;AACF;;AAGA,eAAsB,QAAQ,KAAa,OAAgD;CACzF,MAAM,WAAW,MAAM,QAAQ,SAAS,SAAS,KAAK,IAAI,CAAC;CAC3D,MAAM,WAA6B,CAAC;CACpC,MAAM,UAAoB,CAAC;CAE3B,IAAI,SAAS,WAAW,GAAG,OAAO;EAAE;EAAU;CAAQ;CAEtD,IAAI,gBAAgB,GAAG,GAAG;EACxB,QAAQ,KAAK,QAAQ;EAErB,IAAI,CAAC,WAAW,GAAG,GACjB,SAAS,KACP,cAAc;GACZ,MAAM;GACN,QAAQ;GACR,SAAS;EACX,CAAC,CACH;OAEA,IAAI;GACF,SAAS,KAAK,GAAI,MAAM,UAAU,KAAK,QAAQ,CAAE;EACnD,SAAS,OAAO;GACd,SAAS,KAAK,YAAY,UAAU,KAAK,CAAC;EAC5C;CAEJ;CAEA,OAAO;EAAE;EAAU;CAAQ;AAC7B"}
|
|
@@ -9,8 +9,8 @@ export type TypecheckRunner = (options: TypecheckOptions) => Promise<TypecheckRe
|
|
|
9
9
|
export type CheckOptions = {
|
|
10
10
|
/** Project root. Default: `process.cwd()`. */
|
|
11
11
|
cwd?: string;
|
|
12
|
-
/** Oxlint
|
|
13
|
-
lint?: "oxlint"
|
|
12
|
+
/** Oxlint is the only supported linter. */
|
|
13
|
+
lint?: "oxlint";
|
|
14
14
|
/** Limit every step to the files changed against `base` (default HEAD) plus untracked files. */
|
|
15
15
|
changed?: boolean;
|
|
16
16
|
/** Compare with `git merge-base <base> HEAD` instead of HEAD. Implies `changed`. */
|
|
@@ -29,6 +29,8 @@ function statusOf(problems) {
|
|
|
29
29
|
* list, and every step after `environment` is `blocked`.
|
|
30
30
|
*/
|
|
31
31
|
async function runCheck(options = {}) {
|
|
32
|
+
const selection = options.lint;
|
|
33
|
+
if (selection !== void 0 && selection !== "oxlint") throw new Error("ESLint support was removed in 5.34.0. Oxlint/Oxfmt is the default; run npx warlock upgrade --from 5.33 --to 5.34.0.");
|
|
32
34
|
const cwd = path.resolve(options.cwd ?? process.cwd());
|
|
33
35
|
const changed = options.changed === true || options.base !== void 0;
|
|
34
36
|
const skip = new Set(options.skip ?? []);
|
|
@@ -119,10 +121,10 @@ async function runCheck(options = {}) {
|
|
|
119
121
|
detail: "no files to lint",
|
|
120
122
|
problems: []
|
|
121
123
|
};
|
|
122
|
-
const { linters, problems: found } = await runLint(cwd, lintFiles
|
|
124
|
+
const { linters, problems: found } = await runLint(cwd, lintFiles);
|
|
123
125
|
if (linters.length === 0) return {
|
|
124
126
|
status: "skipped",
|
|
125
|
-
detail: "no Oxlint config
|
|
127
|
+
detail: "no Oxlint config",
|
|
126
128
|
problems: []
|
|
127
129
|
};
|
|
128
130
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-check.mjs","names":[],"sources":["../../../../../../../../../packages/core/src/tooling/check/run-check.ts"],"sourcesContent":["import path from \"node:path\";\nimport { createProblem, type ToolingProblem } from \"../problem\";\nimport {\n runTypecheck,\n type TypecheckOptions,\n type TypecheckResult,\n} from \"../typecheck/run-typecheck\";\nimport { type GitRunner, listChangedFiles } from \"./changed-files\";\nimport {\n CHECK_STEPS,\n type CheckReport,\n type CheckStep,\n type CheckStepName,\n type CheckStepStatus,\n checkExitCode,\n} from \"./check-report.types\";\nimport { runConventions } from \"./conventions-step\";\nimport { checkNodeVersion } from \"./environment-step\";\nimport { runLint } from \"./lint-step\";\nimport { listSourceFiles, listTestFiles } from \"./source-files\";\nimport {\n findVitest,\n parseVitestReport,\n runVitest,\n type VitestRunner,\n vitestArguments,\n vitestRunFailure,\n} from \"./tests-step\";\n\n/** Runs the typecheck step. The CLI swaps in a child process so a heap overflow cannot end `check`. */\nexport type TypecheckRunner = (\n options: TypecheckOptions,\n) => Promise<TypecheckResult> | TypecheckResult;\n\n/** Inputs of {@link runCheck}. */\nexport type CheckOptions = {\n /** Project root. Default: `process.cwd()`. */\n cwd?: string;\n /** Oxlint by default; ESLint is deprecated and requires explicit selection. */\n lint?: \"oxlint\" | \"eslint\";\n /** Limit every step to the files changed against `base` (default HEAD) plus untracked files. */\n changed?: boolean;\n /** Compare with `git merge-base <base> HEAD` instead of HEAD. Implies `changed`. */\n base?: string;\n /** Steps not to run. */\n skip?: readonly CheckStepName[];\n /** tsconfig path, relative to `cwd`. Default: `tsconfig.json`. */\n project?: string;\n /** How git is run. */\n git?: GitRunner;\n /** How the typecheck runs. Default: in this process. */\n typecheck?: TypecheckRunner;\n /** How vitest runs. */\n vitest?: VitestRunner;\n /** Where the app's vitest CLI is. Default: resolved from the app root. */\n vitestBinary?: string | null;\n /** The Node.js version to check. Default: the running one. */\n nodeVersion?: string;\n};\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nfunction statusOf(problems: readonly ToolingProblem[]): CheckStepStatus {\n const errors = problems.filter((problem) => problem.severity === \"error\");\n\n if (errors.some((problem) => problem.category === \"environment\")) return \"blocked\";\n\n return errors.length > 0 ? \"failed\" : \"passed\";\n}\n\n/** Bundles one step's timing, status and problems. */\ntype StepOutcome = { status?: CheckStepStatus; detail: string | null; problems: ToolingProblem[] };\n\n/**\n * The single verify command: typecheck, lint, the tests affected by the\n * change, and the framework's convention checks, as one report with one entry\n * per problem and an exit code that tells \"your code\" (1) from \"this machine\"\n * (2).\n *\n * Every step runs even when an earlier one failed, so one run lists every\n * problem. The only exception: with `changed`, a git failure leaves no file\n * list, and every step after `environment` is `blocked`.\n */\nexport async function runCheck(options: CheckOptions = {}): Promise<CheckReport> {\n const cwd = path.resolve(options.cwd ?? process.cwd());\n const changed = options.changed === true || options.base !== undefined;\n const skip = new Set(options.skip ?? []);\n const steps: CheckStep[] = [];\n const problems: ToolingProblem[] = [];\n let files: string[] | null = null;\n let filesBlocked = false;\n\n const run = async (name: CheckStepName, body: () => Promise<StepOutcome> | StepOutcome) => {\n const startedAt = Date.now();\n\n if (skip.has(name)) {\n steps.push({ name, status: \"skipped\", durationMs: 0, detail: \"skipped with --skip\" });\n return;\n }\n\n if (filesBlocked && name !== \"environment\") {\n steps.push({\n name,\n status: \"blocked\",\n durationMs: 0,\n detail: \"the changed files could not be listed\",\n });\n return;\n }\n\n let outcome: StepOutcome;\n\n try {\n outcome = await body();\n } catch (error) {\n outcome = {\n detail: null,\n problems: [\n createProblem({\n code: \"WL8007\",\n source: \"environment\",\n message: `The ${name} step crashed: ${errorMessage(error)}`,\n }),\n ],\n };\n }\n\n problems.push(...outcome.problems);\n steps.push({\n name,\n status: outcome.status ?? statusOf(outcome.problems),\n durationMs: Date.now() - startedAt,\n detail: outcome.detail,\n });\n };\n\n await run(\"environment\", async () => {\n const found = checkNodeVersion(cwd, options.nodeVersion);\n\n if (changed) {\n const listed = await listChangedFiles({ cwd, base: options.base, git: options.git });\n\n if (\"problem\" in listed) {\n filesBlocked = true;\n found.push(listed.problem);\n } else {\n files = listed.files;\n }\n }\n\n return {\n detail: `Node ${options.nodeVersion ?? process.versions.node}${files ? `, ${files.length} changed file(s)` : \"\"}`,\n problems: found,\n };\n });\n\n const targets = async (): Promise<string[]> => files ?? (await listSourceFiles(cwd));\n\n await run(\"typecheck\", async () => {\n if (files !== null && files.length === 0) {\n return { status: \"skipped\", detail: \"no changed files\", problems: [] };\n }\n\n const typecheck = options.typecheck ?? runTypecheck;\n const result = await typecheck({\n cwd,\n project: options.project,\n ...(files !== null ? { files } : {}),\n });\n\n return {\n detail: `${result.checkedFiles} file(s) checked in ${result.durationMs}ms`,\n problems: result.problems,\n };\n });\n\n await run(\"lint\", async () => {\n const lintFiles = await targets();\n\n if (lintFiles.length === 0) {\n return { status: \"skipped\", detail: \"no files to lint\", problems: [] };\n }\n\n const { linters, problems: found } = await runLint(cwd, lintFiles, options.lint);\n\n if (linters.length === 0) {\n return {\n status: \"skipped\",\n detail: \"no Oxlint config (ESLint requires --lint eslint)\",\n problems: [],\n };\n }\n\n return { detail: `${linters.join(\" + \")} over ${lintFiles.length} file(s)`, problems: found };\n });\n\n await run(\"tests\", async () => {\n if (files !== null && files.length === 0) {\n return { status: \"skipped\", detail: \"no changed files\", problems: [] };\n }\n\n const binary = options.vitestBinary === undefined ? findVitest(cwd) : options.vitestBinary;\n\n if (!binary) {\n if ((await listTestFiles(cwd)).length === 0) {\n return { status: \"skipped\", detail: \"no test files\", problems: [] };\n }\n\n return {\n detail: null,\n problems: [\n createProblem({\n code: \"WL8002\",\n source: \"environment\",\n message: \"The project has test files but vitest is not installed in the app.\",\n }),\n ],\n };\n }\n\n const vitest = options.vitest ?? runVitest;\n const outcome = await vitest(binary, vitestArguments(files), cwd);\n const found =\n outcome.report === undefined\n ? vitestRunFailure(outcome)\n : parseVitestReport(outcome.report, cwd);\n const total =\n typeof outcome.report === \"object\" && outcome.report !== null\n ? Reflect.get(outcome.report, \"numTotalTests\")\n : undefined;\n\n return {\n detail: typeof total === \"number\" ? `${total} test(s) ran` : null,\n problems: found,\n };\n });\n\n await run(\"conventions\", async () => {\n const conventionFiles = await targets();\n\n return {\n detail: `${conventionFiles.length} file(s) checked`,\n problems: runConventions(cwd, conventionFiles, options.project),\n };\n });\n\n // Keep the declared order even if a future step is added out of sequence.\n steps.sort((first, second) => CHECK_STEPS.indexOf(first.name) - CHECK_STEPS.indexOf(second.name));\n\n const exitCode = checkExitCode(problems);\n const errors = problems.filter((problem) => problem.severity === \"error\");\n\n return {\n schemaVersion: 1,\n ok: exitCode === 0,\n exitCode,\n changed,\n files,\n steps,\n problems,\n summary: {\n errors: errors.length,\n warnings: problems.length - errors.length,\n code: errors.filter((problem) => problem.category === \"code\").length,\n environment: errors.filter((problem) => problem.category === \"environment\").length,\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;AA4DA,SAAS,aAAa,OAAwB;CAC5C,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAC9D;AAEA,SAAS,SAAS,UAAsD;CACtE,MAAM,SAAS,SAAS,QAAQ,YAAY,QAAQ,aAAa,OAAO;CAExE,IAAI,OAAO,MAAM,YAAY,QAAQ,aAAa,aAAa,GAAG,OAAO;CAEzE,OAAO,OAAO,SAAS,IAAI,WAAW;AACxC;;;;;;;;;;;AAeA,eAAsB,SAAS,UAAwB,CAAC,GAAyB;CAC/E,MAAM,MAAM,KAAK,QAAQ,QAAQ,OAAO,QAAQ,IAAI,CAAC;CACrD,MAAM,UAAU,QAAQ,YAAY,QAAQ,QAAQ,SAAS;CAC7D,MAAM,OAAO,IAAI,IAAI,QAAQ,QAAQ,CAAC,CAAC;CACvC,MAAM,QAAqB,CAAC;CAC5B,MAAM,WAA6B,CAAC;CACpC,IAAI,QAAyB;CAC7B,IAAI,eAAe;CAEnB,MAAM,MAAM,OAAO,MAAqB,SAAmD;EACzF,MAAM,YAAY,KAAK,IAAI;EAE3B,IAAI,KAAK,IAAI,IAAI,GAAG;GAClB,MAAM,KAAK;IAAE;IAAM,QAAQ;IAAW,YAAY;IAAG,QAAQ;GAAsB,CAAC;GACpF;EACF;EAEA,IAAI,gBAAgB,SAAS,eAAe;GAC1C,MAAM,KAAK;IACT;IACA,QAAQ;IACR,YAAY;IACZ,QAAQ;GACV,CAAC;GACD;EACF;EAEA,IAAI;EAEJ,IAAI;GACF,UAAU,MAAM,KAAK;EACvB,SAAS,OAAO;GACd,UAAU;IACR,QAAQ;IACR,UAAU,CACR,cAAc;KACZ,MAAM;KACN,QAAQ;KACR,SAAS,OAAO,KAAK,iBAAiB,aAAa,KAAK;IAC1D,CAAC,CACH;GACF;EACF;EAEA,SAAS,KAAK,GAAG,QAAQ,QAAQ;EACjC,MAAM,KAAK;GACT;GACA,QAAQ,QAAQ,UAAU,SAAS,QAAQ,QAAQ;GACnD,YAAY,KAAK,IAAI,IAAI;GACzB,QAAQ,QAAQ;EAClB,CAAC;CACH;CAEA,MAAM,IAAI,eAAe,YAAY;EACnC,MAAM,QAAQ,iBAAiB,KAAK,QAAQ,WAAW;EAEvD,IAAI,SAAS;GACX,MAAM,SAAS,MAAM,iBAAiB;IAAE;IAAK,MAAM,QAAQ;IAAM,KAAK,QAAQ;GAAI,CAAC;GAEnF,IAAI,aAAa,QAAQ;IACvB,eAAe;IACf,MAAM,KAAK,OAAO,OAAO;GAC3B,OACE,QAAQ,OAAO;EAEnB;EAEA,OAAO;GACL,QAAQ,QAAQ,QAAQ,eAAe,QAAQ,SAAS,OAAO,QAAQ,KAAK,MAAM,OAAO,oBAAoB;GAC7G,UAAU;EACZ;CACF,CAAC;CAED,MAAM,UAAU,YAA+B,SAAU,MAAM,gBAAgB,GAAG;CAElF,MAAM,IAAI,aAAa,YAAY;EACjC,IAAI,UAAU,QAAQ,MAAM,WAAW,GACrC,OAAO;GAAE,QAAQ;GAAW,QAAQ;GAAoB,UAAU,CAAC;EAAE;EAIvE,MAAM,SAAS,OADG,QAAQ,aAAa,aACT,CAAC;GAC7B;GACA,SAAS,QAAQ;GACjB,GAAI,UAAU,OAAO,EAAE,MAAM,IAAI,CAAC;EACpC,CAAC;EAED,OAAO;GACL,QAAQ,GAAG,OAAO,aAAa,sBAAsB,OAAO,WAAW;GACvE,UAAU,OAAO;EACnB;CACF,CAAC;CAED,MAAM,IAAI,QAAQ,YAAY;EAC5B,MAAM,YAAY,MAAM,QAAQ;EAEhC,IAAI,UAAU,WAAW,GACvB,OAAO;GAAE,QAAQ;GAAW,QAAQ;GAAoB,UAAU,CAAC;EAAE;EAGvE,MAAM,EAAE,SAAS,UAAU,UAAU,MAAM,QAAQ,KAAK,WAAW,QAAQ,IAAI;EAE/E,IAAI,QAAQ,WAAW,GACrB,OAAO;GACL,QAAQ;GACR,QAAQ;GACR,UAAU,CAAC;EACb;EAGF,OAAO;GAAE,QAAQ,GAAG,QAAQ,KAAK,KAAK,EAAE,QAAQ,UAAU,OAAO;GAAW,UAAU;EAAM;CAC9F,CAAC;CAED,MAAM,IAAI,SAAS,YAAY;EAC7B,IAAI,UAAU,QAAQ,MAAM,WAAW,GACrC,OAAO;GAAE,QAAQ;GAAW,QAAQ;GAAoB,UAAU,CAAC;EAAE;EAGvE,MAAM,SAAS,QAAQ,iBAAiB,SAAY,WAAW,GAAG,IAAI,QAAQ;EAE9E,IAAI,CAAC,QAAQ;GACX,KAAK,MAAM,cAAc,GAAG,EAAC,CAAE,WAAW,GACxC,OAAO;IAAE,QAAQ;IAAW,QAAQ;IAAiB,UAAU,CAAC;GAAE;GAGpE,OAAO;IACL,QAAQ;IACR,UAAU,CACR,cAAc;KACZ,MAAM;KACN,QAAQ;KACR,SAAS;IACX,CAAC,CACH;GACF;EACF;EAGA,MAAM,UAAU,OADD,QAAQ,UAAU,UACL,CAAC,QAAQ,gBAAgB,KAAK,GAAG,GAAG;EAChE,MAAM,QACJ,QAAQ,WAAW,SACf,iBAAiB,OAAO,IACxB,kBAAkB,QAAQ,QAAQ,GAAG;EAC3C,MAAM,QACJ,OAAO,QAAQ,WAAW,YAAY,QAAQ,WAAW,OACrD,QAAQ,IAAI,QAAQ,QAAQ,eAAe,IAC3C;EAEN,OAAO;GACL,QAAQ,OAAO,UAAU,WAAW,GAAG,MAAM,gBAAgB;GAC7D,UAAU;EACZ;CACF,CAAC;CAED,MAAM,IAAI,eAAe,YAAY;EACnC,MAAM,kBAAkB,MAAM,QAAQ;EAEtC,OAAO;GACL,QAAQ,GAAG,gBAAgB,OAAO;GAClC,UAAU,eAAe,KAAK,iBAAiB,QAAQ,OAAO;EAChE;CACF,CAAC;CAGD,MAAM,MAAM,OAAO,WAAW,YAAY,QAAQ,MAAM,IAAI,IAAI,YAAY,QAAQ,OAAO,IAAI,CAAC;CAEhG,MAAM,WAAW,cAAc,QAAQ;CACvC,MAAM,SAAS,SAAS,QAAQ,YAAY,QAAQ,aAAa,OAAO;CAExE,OAAO;EACL,eAAe;EACf,IAAI,aAAa;EACjB;EACA;EACA;EACA;EACA;EACA,SAAS;GACP,QAAQ,OAAO;GACf,UAAU,SAAS,SAAS,OAAO;GACnC,MAAM,OAAO,QAAQ,YAAY,QAAQ,aAAa,MAAM,CAAC,CAAC;GAC9D,aAAa,OAAO,QAAQ,YAAY,QAAQ,aAAa,aAAa,CAAC,CAAC;EAC9E;CACF;AACF"}
|
|
1
|
+
{"version":3,"file":"run-check.mjs","names":[],"sources":["../../../../../../../../../packages/core/src/tooling/check/run-check.ts"],"sourcesContent":["import path from \"node:path\";\nimport { createProblem, type ToolingProblem } from \"../problem\";\nimport {\n runTypecheck,\n type TypecheckOptions,\n type TypecheckResult,\n} from \"../typecheck/run-typecheck\";\nimport { type GitRunner, listChangedFiles } from \"./changed-files\";\nimport {\n CHECK_STEPS,\n type CheckReport,\n type CheckStep,\n type CheckStepName,\n type CheckStepStatus,\n checkExitCode,\n} from \"./check-report.types\";\nimport { runConventions } from \"./conventions-step\";\nimport { checkNodeVersion } from \"./environment-step\";\nimport { runLint } from \"./lint-step\";\nimport { listSourceFiles, listTestFiles } from \"./source-files\";\nimport {\n findVitest,\n parseVitestReport,\n runVitest,\n type VitestRunner,\n vitestArguments,\n vitestRunFailure,\n} from \"./tests-step\";\n\n/** Runs the typecheck step. The CLI swaps in a child process so a heap overflow cannot end `check`. */\nexport type TypecheckRunner = (\n options: TypecheckOptions,\n) => Promise<TypecheckResult> | TypecheckResult;\n\n/** Inputs of {@link runCheck}. */\nexport type CheckOptions = {\n /** Project root. Default: `process.cwd()`. */\n cwd?: string;\n /** Oxlint is the only supported linter. */\n lint?: \"oxlint\";\n /** Limit every step to the files changed against `base` (default HEAD) plus untracked files. */\n changed?: boolean;\n /** Compare with `git merge-base <base> HEAD` instead of HEAD. Implies `changed`. */\n base?: string;\n /** Steps not to run. */\n skip?: readonly CheckStepName[];\n /** tsconfig path, relative to `cwd`. Default: `tsconfig.json`. */\n project?: string;\n /** How git is run. */\n git?: GitRunner;\n /** How the typecheck runs. Default: in this process. */\n typecheck?: TypecheckRunner;\n /** How vitest runs. */\n vitest?: VitestRunner;\n /** Where the app's vitest CLI is. Default: resolved from the app root. */\n vitestBinary?: string | null;\n /** The Node.js version to check. Default: the running one. */\n nodeVersion?: string;\n};\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nfunction statusOf(problems: readonly ToolingProblem[]): CheckStepStatus {\n const errors = problems.filter((problem) => problem.severity === \"error\");\n\n if (errors.some((problem) => problem.category === \"environment\")) return \"blocked\";\n\n return errors.length > 0 ? \"failed\" : \"passed\";\n}\n\n/** Bundles one step's timing, status and problems. */\ntype StepOutcome = { status?: CheckStepStatus; detail: string | null; problems: ToolingProblem[] };\n\n/**\n * The single verify command: typecheck, lint, the tests affected by the\n * change, and the framework's convention checks, as one report with one entry\n * per problem and an exit code that tells \"your code\" (1) from \"this machine\"\n * (2).\n *\n * Every step runs even when an earlier one failed, so one run lists every\n * problem. The only exception: with `changed`, a git failure leaves no file\n * list, and every step after `environment` is `blocked`.\n */\nexport async function runCheck(options: CheckOptions = {}): Promise<CheckReport> {\n const selection: unknown = options.lint;\n if (selection !== undefined && selection !== \"oxlint\")\n throw new Error(\n \"ESLint support was removed in 5.34.0. Oxlint/Oxfmt is the default; run npx warlock upgrade --from 5.33 --to 5.34.0.\",\n );\n const cwd = path.resolve(options.cwd ?? process.cwd());\n const changed = options.changed === true || options.base !== undefined;\n const skip = new Set(options.skip ?? []);\n const steps: CheckStep[] = [];\n const problems: ToolingProblem[] = [];\n let files: string[] | null = null;\n let filesBlocked = false;\n\n const run = async (name: CheckStepName, body: () => Promise<StepOutcome> | StepOutcome) => {\n const startedAt = Date.now();\n\n if (skip.has(name)) {\n steps.push({ name, status: \"skipped\", durationMs: 0, detail: \"skipped with --skip\" });\n return;\n }\n\n if (filesBlocked && name !== \"environment\") {\n steps.push({\n name,\n status: \"blocked\",\n durationMs: 0,\n detail: \"the changed files could not be listed\",\n });\n return;\n }\n\n let outcome: StepOutcome;\n\n try {\n outcome = await body();\n } catch (error) {\n outcome = {\n detail: null,\n problems: [\n createProblem({\n code: \"WL8007\",\n source: \"environment\",\n message: `The ${name} step crashed: ${errorMessage(error)}`,\n }),\n ],\n };\n }\n\n problems.push(...outcome.problems);\n steps.push({\n name,\n status: outcome.status ?? statusOf(outcome.problems),\n durationMs: Date.now() - startedAt,\n detail: outcome.detail,\n });\n };\n\n await run(\"environment\", async () => {\n const found = checkNodeVersion(cwd, options.nodeVersion);\n\n if (changed) {\n const listed = await listChangedFiles({ cwd, base: options.base, git: options.git });\n\n if (\"problem\" in listed) {\n filesBlocked = true;\n found.push(listed.problem);\n } else {\n files = listed.files;\n }\n }\n\n return {\n detail: `Node ${options.nodeVersion ?? process.versions.node}${files ? `, ${files.length} changed file(s)` : \"\"}`,\n problems: found,\n };\n });\n\n const targets = async (): Promise<string[]> => files ?? (await listSourceFiles(cwd));\n\n await run(\"typecheck\", async () => {\n if (files !== null && files.length === 0) {\n return { status: \"skipped\", detail: \"no changed files\", problems: [] };\n }\n\n const typecheck = options.typecheck ?? runTypecheck;\n const result = await typecheck({\n cwd,\n project: options.project,\n ...(files !== null ? { files } : {}),\n });\n\n return {\n detail: `${result.checkedFiles} file(s) checked in ${result.durationMs}ms`,\n problems: result.problems,\n };\n });\n\n await run(\"lint\", async () => {\n const lintFiles = await targets();\n\n if (lintFiles.length === 0) {\n return { status: \"skipped\", detail: \"no files to lint\", problems: [] };\n }\n\n const { linters, problems: found } = await runLint(cwd, lintFiles);\n\n if (linters.length === 0) {\n return {\n status: \"skipped\",\n detail: \"no Oxlint config\",\n problems: [],\n };\n }\n\n return { detail: `${linters.join(\" + \")} over ${lintFiles.length} file(s)`, problems: found };\n });\n\n await run(\"tests\", async () => {\n if (files !== null && files.length === 0) {\n return { status: \"skipped\", detail: \"no changed files\", problems: [] };\n }\n\n const binary = options.vitestBinary === undefined ? findVitest(cwd) : options.vitestBinary;\n\n if (!binary) {\n if ((await listTestFiles(cwd)).length === 0) {\n return { status: \"skipped\", detail: \"no test files\", problems: [] };\n }\n\n return {\n detail: null,\n problems: [\n createProblem({\n code: \"WL8002\",\n source: \"environment\",\n message: \"The project has test files but vitest is not installed in the app.\",\n }),\n ],\n };\n }\n\n const vitest = options.vitest ?? runVitest;\n const outcome = await vitest(binary, vitestArguments(files), cwd);\n const found =\n outcome.report === undefined\n ? vitestRunFailure(outcome)\n : parseVitestReport(outcome.report, cwd);\n const total =\n typeof outcome.report === \"object\" && outcome.report !== null\n ? Reflect.get(outcome.report, \"numTotalTests\")\n : undefined;\n\n return {\n detail: typeof total === \"number\" ? `${total} test(s) ran` : null,\n problems: found,\n };\n });\n\n await run(\"conventions\", async () => {\n const conventionFiles = await targets();\n\n return {\n detail: `${conventionFiles.length} file(s) checked`,\n problems: runConventions(cwd, conventionFiles, options.project),\n };\n });\n\n // Keep the declared order even if a future step is added out of sequence.\n steps.sort((first, second) => CHECK_STEPS.indexOf(first.name) - CHECK_STEPS.indexOf(second.name));\n\n const exitCode = checkExitCode(problems);\n const errors = problems.filter((problem) => problem.severity === \"error\");\n\n return {\n schemaVersion: 1,\n ok: exitCode === 0,\n exitCode,\n changed,\n files,\n steps,\n problems,\n summary: {\n errors: errors.length,\n warnings: problems.length - errors.length,\n code: errors.filter((problem) => problem.category === \"code\").length,\n environment: errors.filter((problem) => problem.category === \"environment\").length,\n },\n };\n}\n"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ErrorCodeCategory, WarlockErrorCode } from "../errors/error-codes.mjs";
|
|
2
2
|
//#region ../../packages/core/src/tooling/problem.d.ts
|
|
3
3
|
/** The tool that found a problem. */
|
|
4
|
-
export type ProblemSource = "typescript" | "
|
|
4
|
+
export type ProblemSource = "typescript" | "oxlint" | "vitest" | "convention" | "environment" | "doctor";
|
|
5
5
|
/**
|
|
6
6
|
* One problem, in the shape every machine-readable command prints
|
|
7
7
|
* (`warlock check --json`, `warlock typecheck --json`, `warlock doctor --json`).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"problem.d.mts","names":[],"sources":["../../../../../../../../packages/core/src/tooling/problem.ts"],"mappings":";;;YAQY;;;;;;;;
|
|
1
|
+
{"version":3,"file":"problem.d.mts","names":[],"sources":["../../../../../../../../packages/core/src/tooling/problem.ts"],"mappings":";;;YAQY;;;;;;;;YAeA;;EAEV,MAAM;;EAEN,UAAU;;EAEV;;EAEA,QAAQ;;EAER;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;;YAIU;EACV,MAAM;EACN,QAAQ;EACR;EACA;EACA;EACA;EACA;EACA;;;;;;wBAOc,cAAc,OAAO,eAAe"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"problem.mjs","names":[],"sources":["../../../../../../../../packages/core/src/tooling/problem.ts"],"sourcesContent":["import {\n ERROR_CODES,\n errorCodeDocsUrl,\n type ErrorCodeCategory,\n type WarlockErrorCode,\n} from \"../errors/error-codes\";\n\n/** The tool that found a problem. */\nexport type ProblemSource =\n | \"typescript\"\n | \"
|
|
1
|
+
{"version":3,"file":"problem.mjs","names":[],"sources":["../../../../../../../../packages/core/src/tooling/problem.ts"],"sourcesContent":["import {\n ERROR_CODES,\n errorCodeDocsUrl,\n type ErrorCodeCategory,\n type WarlockErrorCode,\n} from \"../errors/error-codes\";\n\n/** The tool that found a problem. */\nexport type ProblemSource =\n | \"typescript\"\n | \"oxlint\"\n | \"vitest\"\n | \"convention\"\n | \"environment\"\n | \"doctor\";\n\n/**\n * One problem, in the shape every machine-readable command prints\n * (`warlock check --json`, `warlock typecheck --json`, `warlock doctor --json`).\n *\n * Every key is always present, so a consumer never has to test for one:\n * `file`, `line` and `column` are `null` when the problem has no position.\n */\nexport type ToolingProblem = {\n /** Stable Warlock error code; `warlock explain <code>` prints the fix. */\n code: WarlockErrorCode;\n /** `code` = fix the project; `environment` = fix this machine. */\n category: ErrorCodeCategory;\n /** `error` fails the run; `warning` is reported and does not. */\n severity: \"error\" | \"warning\";\n /** The tool that reported it. */\n source: ProblemSource;\n /** Project-relative POSIX path, or `null`. */\n file: string | null;\n /** 1-based line, or `null`. */\n line: number | null;\n /** 1-based column, or `null`. */\n column: number | null;\n /** What is wrong, in the reporting tool's words. */\n message: string;\n /** One line on what to do, from the code registry. */\n hint: string;\n /** Slug of the skill that explains the fix. */\n skill: string;\n /** Docs URL of the code. */\n docs: string;\n /** The tool's own rule or code (`TS2345`, `no-unused-vars`, a test name), or `null`. */\n rule: string | null;\n};\n\n/** The fields a reporter supplies; the rest come from the registry. */\nexport type ProblemInput = {\n code: WarlockErrorCode;\n source: ProblemSource;\n message: string;\n severity?: \"error\" | \"warning\";\n file?: string | null;\n line?: number | null;\n column?: number | null;\n rule?: string | null;\n};\n\n/**\n * Build a {@link ToolingProblem}, filling `category`, `hint`, `skill` and `docs`\n * from the code registry so every reporter describes a code the same way.\n */\nexport function createProblem(input: ProblemInput): ToolingProblem {\n const definition = ERROR_CODES[input.code];\n\n return {\n code: input.code,\n category: definition.category,\n severity: input.severity ?? \"error\",\n source: input.source,\n file: input.file ?? null,\n line: input.line ?? null,\n column: input.column ?? null,\n message: input.message,\n hint: definition.fix,\n skill: definition.skill,\n docs: errorCodeDocsUrl(input.code),\n rule: input.rule ?? null,\n };\n}\n"],"mappings":";;;;;;;AAkEA,SAAgB,cAAc,OAAqC;CACjE,MAAM,aAAa,YAAY,MAAM;CAErC,OAAO;EACL,MAAM,MAAM;EACZ,UAAU,WAAW;EACrB,UAAU,MAAM,YAAY;EAC5B,QAAQ,MAAM;EACd,MAAM,MAAM,QAAQ;EACpB,MAAM,MAAM,QAAQ;EACpB,QAAQ,MAAM,UAAU;EACxB,SAAS,MAAM;EACf,MAAM,WAAW;EACjB,OAAO,WAAW;EAClB,MAAM,iBAAiB,MAAM,IAAI;EACjC,MAAM,MAAM,QAAQ;CACtB;AACF"}
|
|
@@ -48,7 +48,11 @@ async function detectPackageManager(startDir = rootPath()) {
|
|
|
48
48
|
const declared = await readDeclaredPackageManager(dir);
|
|
49
49
|
if (declared) return declared;
|
|
50
50
|
}
|
|
51
|
-
for (const dir of dirs) if (await fileExistsAsync(path.join(dir, "pnpm-workspace.yaml")))
|
|
51
|
+
for (const dir of dirs) if (await fileExistsAsync(path.join(dir, "pnpm-workspace.yaml"))) {
|
|
52
|
+
if (await fileExistsAsync(path.join(dir, "pnpm-lock.yaml"))) return "pnpm";
|
|
53
|
+
for (const { file, packageManager } of LOCKFILES) if (await fileExistsAsync(path.join(dir, file))) return packageManager;
|
|
54
|
+
return "pnpm";
|
|
55
|
+
}
|
|
52
56
|
for (const dir of dirs) for (const { file, packageManager } of LOCKFILES) if (await fileExistsAsync(path.join(dir, file))) return packageManager;
|
|
53
57
|
const agent = process.env.npm_config_user_agent?.split("/")[0];
|
|
54
58
|
if (agent === "pnpm" || agent === "yarn" || agent === "bun") return agent;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"package-manager.mjs","names":[],"sources":["../../../../../../../../packages/core/src/updater/package-manager.ts"],"sourcesContent":["import { fileExistsAsync } from \"@warlock.js/fs\";\nimport { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { rootPath } from \"../utils\";\n\n/** Package managers the framework knows how to drive. */\nexport type PackageManager = \"npm\" | \"yarn\" | \"pnpm\" | \"bun\";\n\n/**\n * The lockfile that identifies each package manager, in detection order.\n * Bun is checked first because a Bun project may also carry a `yarn.lock`\n * (Bun writes one for tooling compatibility) — matching yarn there would run\n * the wrong installer against the wrong lockfile.\n */\nconst LOCKFILES: ReadonlyArray<{ file: string; packageManager: PackageManager }> = [\n { file: \"bun.lock\", packageManager: \"bun\" },\n { file: \"bun.lockb\", packageManager: \"bun\" },\n { file: \"pnpm-lock.yaml\", packageManager: \"pnpm\" },\n { file: \"yarn.lock\", packageManager: \"yarn\" },\n { file: \"package-lock.json\", packageManager: \"npm\" },\n];\n\n/**\n * Detect the project's package manager from its lockfile, falling back to\n * npm when none is present. Shared by `warlock update` and `warlock add` so\n * both agree on a project that happens to carry more than one lockfile.\n */\nexport async function detectPackageManager(startDir: string = rootPath()): Promise<PackageManager> {\n const dirs: string[] = [];\n\n for (let dir = path.resolve(startDir); ; dir = path.dirname(dir)) {\n dirs.push(dir);\n\n if (path.dirname(dir) === dir) break;\n }\n\n // 1. nearest declared `packageManager` field\n for (const dir of dirs) {\n const declared = await readDeclaredPackageManager(dir);\n\n if (declared) return declared;\n }\n\n // 2. a
|
|
1
|
+
{"version":3,"file":"package-manager.mjs","names":[],"sources":["../../../../../../../../packages/core/src/updater/package-manager.ts"],"sourcesContent":["import { fileExistsAsync } from \"@warlock.js/fs\";\nimport { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { rootPath } from \"../utils\";\n\n/** Package managers the framework knows how to drive. */\nexport type PackageManager = \"npm\" | \"yarn\" | \"pnpm\" | \"bun\";\n\n/**\n * The lockfile that identifies each package manager, in detection order.\n * Bun is checked first because a Bun project may also carry a `yarn.lock`\n * (Bun writes one for tooling compatibility) — matching yarn there would run\n * the wrong installer against the wrong lockfile.\n */\nconst LOCKFILES: ReadonlyArray<{ file: string; packageManager: PackageManager }> = [\n { file: \"bun.lock\", packageManager: \"bun\" },\n { file: \"bun.lockb\", packageManager: \"bun\" },\n { file: \"pnpm-lock.yaml\", packageManager: \"pnpm\" },\n { file: \"yarn.lock\", packageManager: \"yarn\" },\n { file: \"package-lock.json\", packageManager: \"npm\" },\n];\n\n/**\n * Detect the project's package manager from its lockfile, falling back to\n * npm when none is present. Shared by `warlock update` and `warlock add` so\n * both agree on a project that happens to carry more than one lockfile.\n */\nexport async function detectPackageManager(startDir: string = rootPath()): Promise<PackageManager> {\n const dirs: string[] = [];\n\n for (let dir = path.resolve(startDir); ; dir = path.dirname(dir)) {\n dirs.push(dir);\n\n if (path.dirname(dir) === dir) break;\n }\n\n // 1. nearest declared `packageManager` field\n for (const dir of dirs) {\n const declared = await readDeclaredPackageManager(dir);\n\n if (declared) return declared;\n }\n\n // 2. a workspace governs descendants, but its own real lockfile wins over a marker\n for (const dir of dirs) {\n if (await fileExistsAsync(path.join(dir, \"pnpm-workspace.yaml\"))) {\n if (await fileExistsAsync(path.join(dir, \"pnpm-lock.yaml\"))) return \"pnpm\";\n for (const { file, packageManager } of LOCKFILES) {\n if (await fileExistsAsync(path.join(dir, file))) return packageManager;\n }\n return \"pnpm\";\n }\n }\n\n // 3. lockfiles, nearest level first\n for (const dir of dirs) {\n for (const { file, packageManager } of LOCKFILES) {\n if (await fileExistsAsync(path.join(dir, file))) return packageManager;\n }\n }\n\n const agent = process.env.npm_config_user_agent?.split(\"/\")[0];\n\n if (agent === \"pnpm\" || agent === \"yarn\" || agent === \"bun\") return agent;\n\n return \"npm\";\n}\n\n/** The manager named by the app's `packageManager` field, if any. */\nasync function readDeclaredPackageManager(dir: string): Promise<PackageManager | undefined> {\n try {\n const json = JSON.parse(await readFile(path.join(dir, \"package.json\"), \"utf8\"));\n const name = String(json.packageManager ?? \"\").split(\"@\")[0];\n\n if (name === \"pnpm\" || name === \"yarn\" || name === \"bun\" || name === \"npm\") return name;\n } catch {\n // no readable package.json — fall through to lockfiles\n }\n\n return undefined;\n}\n\n/**\n * The lockfile-syncing install command for the given manager. No package\n * arguments — `warlock update` rewrites the versions in package.json first,\n * then a plain install reconciles `node_modules` to match.\n */\nexport function getInstallCommand(packageManager: PackageManager): string {\n switch (packageManager) {\n case \"yarn\":\n return \"yarn install\";\n\n case \"pnpm\":\n return \"pnpm install\";\n\n case \"bun\":\n return \"bun install\";\n\n default:\n return \"npm install\";\n }\n}\n\n/**\n * The command that installs *specific* packages — what `warlock add` needs.\n * Distinct from {@link getInstallCommand}, which only reconciles what is\n * already written into package.json.\n */\nexport function getAddCommand(packageManager: PackageManager): string {\n switch (packageManager) {\n case \"yarn\":\n return \"yarn add\";\n\n case \"pnpm\":\n return \"pnpm add\";\n\n case \"bun\":\n return \"bun add\";\n\n default:\n return \"npm install\";\n }\n}\n\n/**\n * The package-manager command that saves an exact version. Warlock family\n * dependencies use this path so the version selected by the executing Core is\n * preserved verbatim in package.json instead of being widened by a manager's\n * default save prefix.\n */\nexport function getExactAddCommand(packageManager: PackageManager): string {\n switch (packageManager) {\n case \"yarn\":\n return \"yarn add --exact\";\n\n case \"pnpm\":\n return \"pnpm add --save-exact\";\n\n case \"bun\":\n return \"bun add --exact\";\n\n default:\n return \"npm install --save-exact\";\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAcA,MAAM,YAA6E;CACjF;EAAE,MAAM;EAAY,gBAAgB;CAAM;CAC1C;EAAE,MAAM;EAAa,gBAAgB;CAAM;CAC3C;EAAE,MAAM;EAAkB,gBAAgB;CAAO;CACjD;EAAE,MAAM;EAAa,gBAAgB;CAAO;CAC5C;EAAE,MAAM;EAAqB,gBAAgB;CAAM;AACrD;;;;;;AAOA,eAAsB,qBAAqB,WAAmB,SAAS,GAA4B;CACjG,MAAM,OAAiB,CAAC;CAExB,KAAK,IAAI,MAAM,KAAK,QAAQ,QAAQ,IAAK,MAAM,KAAK,QAAQ,GAAG,GAAG;EAChE,KAAK,KAAK,GAAG;EAEb,IAAI,KAAK,QAAQ,GAAG,MAAM,KAAK;CACjC;CAGA,KAAK,MAAM,OAAO,MAAM;EACtB,MAAM,WAAW,MAAM,2BAA2B,GAAG;EAErD,IAAI,UAAU,OAAO;CACvB;CAGA,KAAK,MAAM,OAAO,MAChB,IAAI,MAAM,gBAAgB,KAAK,KAAK,KAAK,qBAAqB,CAAC,GAAG;EAChE,IAAI,MAAM,gBAAgB,KAAK,KAAK,KAAK,gBAAgB,CAAC,GAAG,OAAO;EACpE,KAAK,MAAM,EAAE,MAAM,oBAAoB,WACrC,IAAI,MAAM,gBAAgB,KAAK,KAAK,KAAK,IAAI,CAAC,GAAG,OAAO;EAE1D,OAAO;CACT;CAIF,KAAK,MAAM,OAAO,MAChB,KAAK,MAAM,EAAE,MAAM,oBAAoB,WACrC,IAAI,MAAM,gBAAgB,KAAK,KAAK,KAAK,IAAI,CAAC,GAAG,OAAO;CAI5D,MAAM,QAAQ,QAAQ,IAAI,uBAAuB,MAAM,GAAG,CAAC,CAAC;CAE5D,IAAI,UAAU,UAAU,UAAU,UAAU,UAAU,OAAO,OAAO;CAEpE,OAAO;AACT;;AAGA,eAAe,2BAA2B,KAAkD;CAC1F,IAAI;EACF,MAAM,OAAO,KAAK,MAAM,MAAM,SAAS,KAAK,KAAK,KAAK,cAAc,GAAG,MAAM,CAAC;EAC9E,MAAM,OAAO,OAAO,KAAK,kBAAkB,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;EAE1D,IAAI,SAAS,UAAU,SAAS,UAAU,SAAS,SAAS,SAAS,OAAO,OAAO;CACrF,QAAQ,CAER;AAGF;;;;;;AAOA,SAAgB,kBAAkB,gBAAwC;CACxE,QAAQ,gBAAR;EACE,KAAK,QACH,OAAO;EAET,KAAK,QACH,OAAO;EAET,KAAK,OACH,OAAO;EAET,SACE,OAAO;CACX;AACF;;;;;;AAOA,SAAgB,cAAc,gBAAwC;CACpE,QAAQ,gBAAR;EACE,KAAK,QACH,OAAO;EAET,KAAK,QACH,OAAO;EAET,KAAK,OACH,OAAO;EAET,SACE,OAAO;CACX;AACF;;;;;;;AAQA,SAAgB,mBAAmB,gBAAwC;CACzE,QAAQ,gBAAR;EACE,KAAK,QACH,OAAO;EAET,KAAK,QACH,OAAO;EAET,KAAK,OACH,OAAO;EAET,SACE,OAAO;CACX;AACF"}
|
|
@@ -2,7 +2,7 @@ import { importedLocalNames, importsFrom, manualAt, objectProperty, objectProper
|
|
|
2
2
|
import { headViewport } from "./head-viewport.mjs";
|
|
3
3
|
import { loggerSyncCalls } from "./logger-sync-calls.mjs";
|
|
4
4
|
import { node2215, warlockVersions } from "./package-json.mjs";
|
|
5
|
-
import { oxcToolchain } from "./oxc-toolchain.mjs";
|
|
5
|
+
import { oxcToolchain, oxcToolchainRemoval } from "./oxc-toolchain.mjs";
|
|
6
6
|
import { requestLogSnapshot } from "./request-log-snapshot.mjs";
|
|
7
7
|
import { aiAnthropicBody, aiCompactionOptIn, aiFinishReason, aiToolDispatch, rateLimitDefaults, sealContainerCatch, sealRefineOutput, sealUnionOutput, sealValidateResult } from "./review-sites.mjs";
|
|
8
8
|
|
|
@@ -28,6 +28,7 @@ const CODEMODS = [
|
|
|
28
28
|
sealUnionOutput,
|
|
29
29
|
aiCompactionOptIn,
|
|
30
30
|
oxcToolchain,
|
|
31
|
+
oxcToolchainRemoval,
|
|
31
32
|
warlockVersions
|
|
32
33
|
];
|
|
33
34
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../../../../../../../../packages/core/src/upgrade/codemods/index.ts"],"sourcesContent":["import type { Codemod } from \"../types\";\nimport { headViewport } from \"./head-viewport\";\nimport { loggerSyncCalls } from \"./logger-sync-calls\";\nimport { node2215, warlockVersions } from \"./package-json\";\nimport { oxcToolchain } from \"./oxc-toolchain\";\nimport { requestLogSnapshot } from \"./request-log-snapshot\";\nimport {\n aiAnthropicBody,\n aiCompactionOptIn,\n aiFinishReason,\n aiToolDispatch,\n rateLimitDefaults,\n sealContainerCatch,\n sealRefineOutput,\n sealUnionOutput,\n sealValidateResult,\n} from \"./review-sites\";\n\n/**\n * Every codemod, oldest release first. A codemod runs when the app upgrades\n * across its `version` (`from < version <= to`); `\"target\"` ones run on every\n * upgrade. Add one here for each breaking change, and name its id next to the\n * `**BREAKING**` entry in the package changelog.\n */\nexport const CODEMODS: readonly Codemod[] = [\n loggerSyncCalls,\n requestLogSnapshot,\n headViewport,\n sealValidateResult,\n aiToolDispatch,\n aiAnthropicBody,\n aiFinishReason,\n node2215,\n rateLimitDefaults,\n sealRefineOutput,\n sealContainerCatch,\n sealUnionOutput,\n aiCompactionOptIn,\n oxcToolchain,\n warlockVersions,\n];\n\nexport * from \"./helpers\";\n"],"mappings":";;;;;;;;;;;;;;;AAwBA,MAAa,WAA+B;CAC1C;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../../../../../../../../packages/core/src/upgrade/codemods/index.ts"],"sourcesContent":["import type { Codemod } from \"../types\";\nimport { headViewport } from \"./head-viewport\";\nimport { loggerSyncCalls } from \"./logger-sync-calls\";\nimport { node2215, warlockVersions } from \"./package-json\";\nimport { oxcToolchain, oxcToolchainRemoval } from \"./oxc-toolchain\";\nimport { requestLogSnapshot } from \"./request-log-snapshot\";\nimport {\n aiAnthropicBody,\n aiCompactionOptIn,\n aiFinishReason,\n aiToolDispatch,\n rateLimitDefaults,\n sealContainerCatch,\n sealRefineOutput,\n sealUnionOutput,\n sealValidateResult,\n} from \"./review-sites\";\n\n/**\n * Every codemod, oldest release first. A codemod runs when the app upgrades\n * across its `version` (`from < version <= to`); `\"target\"` ones run on every\n * upgrade. Add one here for each breaking change, and name its id next to the\n * `**BREAKING**` entry in the package changelog.\n */\nexport const CODEMODS: readonly Codemod[] = [\n loggerSyncCalls,\n requestLogSnapshot,\n headViewport,\n sealValidateResult,\n aiToolDispatch,\n aiAnthropicBody,\n aiFinishReason,\n node2215,\n rateLimitDefaults,\n sealRefineOutput,\n sealContainerCatch,\n sealUnionOutput,\n aiCompactionOptIn,\n oxcToolchain,\n oxcToolchainRemoval,\n warlockVersions,\n];\n\nexport * from \"./helpers\";\n"],"mappings":";;;;;;;;;;;;;;;AAwBA,MAAa,WAA+B;CAC1C;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF"}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { isRecord } from "./validate-oxlint-rule.mjs";
|
|
2
|
+
import { portEslintRules } from "./port-eslint-rules.mjs";
|
|
1
3
|
import { TOOLCHAIN_TEMPLATES } from "./toolchain-templates.mjs";
|
|
2
4
|
|
|
3
5
|
//#region ../../packages/core/src/upgrade/codemods/oxc-toolchain.ts
|
|
@@ -19,7 +21,7 @@ const OXC_SCRIPTS = {
|
|
|
19
21
|
"format:check": "oxfmt --ignore-path .gitignore --ignore-path .oxfmtignore --check ./src"
|
|
20
22
|
};
|
|
21
23
|
function legacyDependency(name) {
|
|
22
|
-
return /^(eslint|prettier|@types\/prettier
|
|
24
|
+
return /^(eslint|prettier|typescript-eslint|@types\/prettier)$/.test(name) || name.startsWith("@typescript-eslint/") || /(?:^|\/)eslint-config-/.test(name) || /(?:^|\/)eslint-plugin-/.test(name) || /(?:^|\/)prettier-plugin-/.test(name) || name.startsWith("@prettier/plugin-");
|
|
23
25
|
}
|
|
24
26
|
function sameGenerated(source, expected) {
|
|
25
27
|
try {
|
|
@@ -48,8 +50,14 @@ function migrateHealthSwitches(context, output) {
|
|
|
48
50
|
if (value?.getText() !== "false") review(output, file, "Review custom healthCheckers; remove ESLint checkers and enable Oxlint. ESLint support is removed in 5.34.0.", property.getStartLineNumber());
|
|
49
51
|
continue;
|
|
50
52
|
}
|
|
51
|
-
for (const spread of value.getProperties().filter(context.tsMorph.Node.isSpreadAssignment)) review(output, file, "Review spread healthCheckers options;
|
|
52
|
-
|
|
53
|
+
for (const spread of value.getProperties().filter(context.tsMorph.Node.isSpreadAssignment)) review(output, file, "Review spread healthCheckers options; remove eslint and enable oxlint after the spread.", spread.getStartLineNumber());
|
|
54
|
+
const eslint = value.getProperty("eslint");
|
|
55
|
+
if (!eslint) continue;
|
|
56
|
+
if (eslint) {
|
|
57
|
+
eslint.remove();
|
|
58
|
+
changed = true;
|
|
59
|
+
}
|
|
60
|
+
for (const [name, next] of [["oxlint", "true"]]) {
|
|
53
61
|
const option = value.getProperty(name);
|
|
54
62
|
if (!option) continue;
|
|
55
63
|
if (!context.tsMorph.Node.isPropertyAssignment(option) || !["true", "false"].includes(option.getInitializer()?.getText() ?? "")) {
|
|
@@ -81,10 +89,13 @@ const oxcToolchain = {
|
|
|
81
89
|
const source = context.text.read("package.json");
|
|
82
90
|
if (source === void 0) return output;
|
|
83
91
|
const pkg = JSON.parse(source);
|
|
84
|
-
const legacyFiles = context.text.list().filter((file) => /^(eslint\.config\..+|\.eslintrc(?:\..+)?|\.prettierrc(?:\..+)?|prettier\.config\..+|\.prettierignore)$/.test(file));
|
|
92
|
+
const legacyFiles = context.text.list().filter((file) => /^(eslint\.config\..+|\.eslintrc(?:\..+)?|\.prettierrc(?:\..+)?|prettier\.config\..+|\.prettierignore|\.eslintignore)$/.test(file));
|
|
85
93
|
const dependencies = [pkg.dependencies, pkg.devDependencies];
|
|
86
94
|
const legacyScripts = Object.values(pkg.scripts ?? {}).some((script) => /\b(?:eslint|prettier)\b/.test(script));
|
|
87
|
-
if (!legacyFiles.length && !legacyScripts && !dependencies.some((deps) => Object.keys(deps ?? {}).some(legacyDependency)))
|
|
95
|
+
if (!legacyFiles.length && !legacyScripts && pkg.eslintConfig === void 0 && pkg.prettier === void 0 && !dependencies.some((deps) => Object.keys(deps ?? {}).some(legacyDependency))) {
|
|
96
|
+
if (/\beslint\b|EslintHealthChecker|ESLint/.test(context.text.read("warlock.config.ts") ?? "")) migrateHealthSwitches(context, output);
|
|
97
|
+
return output;
|
|
98
|
+
}
|
|
88
99
|
const change = {
|
|
89
100
|
line: 1,
|
|
90
101
|
description: "Replace ESLint/Prettier with the default Oxlint/Oxfmt toolchain"
|
|
@@ -100,23 +111,52 @@ const oxcToolchain = {
|
|
|
100
111
|
};
|
|
101
112
|
if (/\beslint\b/.test(pkg.scripts.fix ?? "")) pkg.scripts.fix = OXC_SCRIPTS.lint;
|
|
102
113
|
for (const [name, command] of Object.entries(pkg.scripts)) if (/\b(?:eslint|prettier)\b/.test(command)) review(output, "package.json", `Replace the custom ${name} script (${command}) with oxlint or oxfmt; the legacy tools have been removed from dependencies.`);
|
|
103
|
-
context.text.
|
|
114
|
+
const hadOxlint = context.text.read(".oxlintrc.json") !== void 0;
|
|
104
115
|
for (const file of [".oxlintrc.json", ".oxfmtrc.json"]) if (context.text.read(file) === void 0) context.text.write(file, asset(file.slice(1)), change);
|
|
116
|
+
if (pkg.eslintConfig !== void 0) {
|
|
117
|
+
const findings = output.manual.length;
|
|
118
|
+
if (portEslintRules(context, output, "package.json", source, hadOxlint, "eslintConfig")) pkg.devDependencies["oxlint-tsgolint"] = "7.0.2004";
|
|
119
|
+
if (output.manual.length === findings) delete pkg.eslintConfig;
|
|
120
|
+
}
|
|
121
|
+
if (pkg.prettier !== void 0) {
|
|
122
|
+
if (sameGenerated(JSON.stringify(pkg.prettier), asset("legacy-prettierrc.json"))) delete pkg.prettier;
|
|
123
|
+
else review(output, "package.json", "Port the custom prettier field to .oxfmtrc.json, then remove it. Prettier support is gone in 5.34.0.");
|
|
124
|
+
}
|
|
105
125
|
for (const file of legacyFiles) {
|
|
106
126
|
const content = context.text.read(file);
|
|
127
|
+
if (file === ".eslintignore" && content !== void 0) {
|
|
128
|
+
try {
|
|
129
|
+
const config = JSON.parse(context.text.read(".oxlintrc.json") ?? "{}");
|
|
130
|
+
if (!isRecord(config) || config.ignorePatterns !== void 0 && (!Array.isArray(config.ignorePatterns) || !config.ignorePatterns.every((pattern) => typeof pattern === "string"))) throw new Error("Invalid ignore patterns");
|
|
131
|
+
config.ignorePatterns = [.../* @__PURE__ */ new Set([...Array.isArray(config.ignorePatterns) ? config.ignorePatterns : [], ...content.split(/\r?\n/).filter((line) => line.trim() && !line.trimStart().startsWith("#"))])];
|
|
132
|
+
context.text.write(".oxlintrc.json", `${JSON.stringify(config, null, 2)}\n`, change);
|
|
133
|
+
} catch {
|
|
134
|
+
review(output, file, "Port these ignore patterns after repairing .oxlintrc.json; ESLint support is gone in 5.34.0.");
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
context.text.remove(file, change);
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
107
140
|
const known = [
|
|
108
141
|
"eslint.config.js",
|
|
109
142
|
".prettierrc.json",
|
|
110
143
|
".prettierignore"
|
|
111
144
|
].includes(file);
|
|
112
145
|
if (content === void 0) continue;
|
|
113
|
-
|
|
114
|
-
|
|
146
|
+
const generated = known && sameGenerated(content, asset(`legacy-${file.replace(/^\./, "")}`));
|
|
147
|
+
if (!generated && /^(eslint\.config\..+|\.eslintrc(?:\..+)?)$/.test(file)) {
|
|
148
|
+
const findings = output.manual.length;
|
|
149
|
+
if (portEslintRules(context, output, file, content, hadOxlint)) pkg.devDependencies["oxlint-tsgolint"] = "7.0.2004";
|
|
150
|
+
if (output.manual.length === findings) context.text.remove(file, change);
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
if (!generated) {
|
|
154
|
+
review(output, file, "Port customized formatting or ignore options to .oxfmtrc.json / .oxfmtignore, then remove this file. Legacy support is gone in 5.34.0.");
|
|
115
155
|
continue;
|
|
116
156
|
}
|
|
117
157
|
if (file === ".prettierignore") {
|
|
118
158
|
const existing = context.text.read(".oxfmtignore");
|
|
119
|
-
if (existing === void 0) context.text.write(".oxfmtignore", content
|
|
159
|
+
if (existing === void 0) context.text.write(".oxfmtignore", `${content.trimEnd()}\n`, change);
|
|
120
160
|
else if (existing.trim() !== content.trim()) {
|
|
121
161
|
review(output, file, "Merge these ignore patterns into the existing .oxfmtignore, then remove .prettierignore.");
|
|
122
162
|
continue;
|
|
@@ -129,14 +169,23 @@ const oxcToolchain = {
|
|
|
129
169
|
const file = `.vscode/${name}`;
|
|
130
170
|
const content = context.text.read(file);
|
|
131
171
|
if (content === void 0) continue;
|
|
172
|
+
if (name === "settings.json" && sameGenerated(content, asset(`oxc-vscode-${name}`))) continue;
|
|
132
173
|
if (name === "settings.json" && sameGenerated(content, asset(`legacy-vscode-${name}`))) context.text.write(file, asset(`oxc-vscode-${name}`), change);
|
|
133
174
|
else review(output, file, "Review editor settings: select oxc.oxc-vscode as the formatter, enable source.fixAll.oxc and remove ESLint/Prettier extension recommendations.");
|
|
134
175
|
}
|
|
135
176
|
migrateHealthSwitches(context, output);
|
|
177
|
+
context.text.write("package.json", `${JSON.stringify(pkg, null, 2)}\n`, change);
|
|
136
178
|
return output;
|
|
137
179
|
}
|
|
138
180
|
};
|
|
181
|
+
/** Run again for apps that skipped or partially completed the 5.33 migration. */
|
|
182
|
+
const oxcToolchainRemoval = {
|
|
183
|
+
...oxcToolchain,
|
|
184
|
+
id: "oxc-toolchain-removal",
|
|
185
|
+
version: "5.34.0",
|
|
186
|
+
title: "ESLint/Prettier support is gone in 5.34.0; migrate to the Oxlint/Oxfmt default"
|
|
187
|
+
};
|
|
139
188
|
|
|
140
189
|
//#endregion
|
|
141
|
-
export { OXC_SCRIPTS, OXC_VERSIONS, oxcToolchain };
|
|
190
|
+
export { OXC_SCRIPTS, OXC_VERSIONS, oxcToolchain, oxcToolchainRemoval };
|
|
142
191
|
//# sourceMappingURL=oxc-toolchain.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oxc-toolchain.mjs","names":[],"sources":["../../../../../../../../../packages/core/src/upgrade/codemods/oxc-toolchain.ts"],"sourcesContent":["import type { Codemod, CodemodContext, CodemodOutput } from \"../types\";\nimport { TOOLCHAIN_TEMPLATES } from \"./toolchain-templates\";\n\n/** Snapshots ship with core; parity specs keep them aligned with create-warlock. */\nfunction asset(name: string): string {\n const content = TOOLCHAIN_TEMPLATES[name];\n if (content === undefined) throw new Error(`Unknown toolchain template: ${name}`);\n return content;\n}\n\nexport const OXC_VERSIONS = { oxlint: \"1.88.0\", oxfmt: \"0.73.0\", typescript: \"7.0.2\" };\nexport const OXC_SCRIPTS = {\n lint: \"oxlint --fix ./src --max-warnings=0\",\n \"lint:check\": \"oxlint ./src --max-warnings=0\",\n format: \"oxfmt --ignore-path .gitignore --ignore-path .oxfmtignore --write ./src\",\n \"format:check\": \"oxfmt --ignore-path .gitignore --ignore-path .oxfmtignore --check ./src\",\n};\n\nfunction legacyDependency(name: string): boolean {\n return (\n /^(eslint|prettier|@types\\/prettier|eslint-config-prettier)$/.test(name) ||\n name.startsWith(\"@typescript-eslint/\") ||\n /(?:^|\\/)eslint-plugin-/.test(name) ||\n /(?:^|\\/)prettier-plugin-/.test(name) ||\n name.startsWith(\"@prettier/plugin-\")\n );\n}\n\nfunction sameGenerated(source: string, expected: string): boolean {\n // JSON may have been reformatted by the app; compare its data. Executable\n // configs are deliberately exact (apart from line endings/trailing space).\n try {\n return JSON.stringify(JSON.parse(source)) === JSON.stringify(JSON.parse(expected));\n } catch {\n return source.replace(/\\r\\n/g, \"\\n\").trim() === expected.replace(/\\r\\n/g, \"\\n\").trim();\n }\n}\n\nfunction review(output: CodemodOutput, file: string, hint: string, line = 1): void {\n output.manual.push({ file, line, hint });\n}\n\nfunction migrateHealthSwitches(context: CodemodContext, output: CodemodOutput): void {\n const file = \"warlock.config.ts\";\n const source = context.text.read(file);\n if (source === undefined) return;\n const project = new context.tsMorph.Project({ useInMemoryFileSystem: true });\n const config = project.createSourceFile(file, source);\n const switches = config\n .getDescendantsOfKind(context.tsMorph.SyntaxKind.PropertyAssignment)\n .filter((property) => property.getName() === \"healthCheckers\");\n let changed = false;\n for (const property of switches) {\n const value = property.getInitializer();\n if (!value || !context.tsMorph.Node.isObjectLiteralExpression(value)) {\n if (value?.getText() !== \"false\")\n review(\n output,\n file,\n \"Review custom healthCheckers; remove ESLint checkers and enable Oxlint. ESLint support is removed in 5.34.0.\",\n property.getStartLineNumber(),\n );\n continue;\n }\n for (const spread of value.getProperties().filter(context.tsMorph.Node.isSpreadAssignment)) {\n review(\n output,\n file,\n \"Review spread healthCheckers options; set eslint: false and oxlint: true explicitly after the spread.\",\n spread.getStartLineNumber(),\n );\n }\n for (const [name, next] of [\n [\"eslint\", \"false\"],\n [\"oxlint\", \"true\"],\n ] as const) {\n const option = value.getProperty(name);\n if (!option) continue;\n if (\n !context.tsMorph.Node.isPropertyAssignment(option) ||\n ![\"true\", \"false\"].includes(option.getInitializer()?.getText() ?? \"\")\n ) {\n review(\n output,\n file,\n `Set healthCheckers.${name} to ${next} after reviewing this computed option.`,\n option.getStartLineNumber(),\n );\n continue;\n }\n if (option.getInitializer()?.getText() !== next) {\n option.setInitializer(next);\n changed = true;\n }\n }\n }\n if (changed)\n context.text.write(file, config.getFullText(), {\n line: 1,\n description: \"Select Oxlint instead of ESLint for background health checks\",\n });\n}\n\nexport const oxcToolchain: Codemod = {\n id: \"oxc-toolchain\",\n version: \"5.33.0\",\n package: \"@warlock.js/core\",\n title: \"Migrate ESLint and Prettier to Oxlint and Oxfmt\",\n skill: \"upgrade-from-5-29\",\n run(context) {\n const output: CodemodOutput = { edits: [], manual: [] };\n const source = context.text.read(\"package.json\");\n if (source === undefined) return output;\n const pkg = JSON.parse(source) as {\n scripts?: Record<string, string>;\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n };\n const legacyFiles = context.text\n .list()\n .filter((file) =>\n /^(eslint\\.config\\..+|\\.eslintrc(?:\\..+)?|\\.prettierrc(?:\\..+)?|prettier\\.config\\..+|\\.prettierignore)$/.test(\n file,\n ),\n );\n const dependencies = [pkg.dependencies, pkg.devDependencies];\n const legacyScripts = Object.values(pkg.scripts ?? {}).some((script) =>\n /\\b(?:eslint|prettier)\\b/.test(script),\n );\n if (\n !legacyFiles.length &&\n !legacyScripts &&\n !dependencies.some((deps) => Object.keys(deps ?? {}).some(legacyDependency))\n )\n return output;\n\n const change = {\n line: 1,\n description: \"Replace ESLint/Prettier with the default Oxlint/Oxfmt toolchain\",\n };\n for (const deps of dependencies) {\n for (const name of Object.keys(deps ?? {})) {\n if (deps && (legacyDependency(name) || name in OXC_VERSIONS)) delete deps[name];\n }\n }\n pkg.devDependencies = { ...pkg.devDependencies, ...OXC_VERSIONS };\n pkg.scripts = { ...pkg.scripts, ...OXC_SCRIPTS };\n if (/\\beslint\\b/.test(pkg.scripts.fix ?? \"\")) pkg.scripts.fix = OXC_SCRIPTS.lint;\n for (const [name, command] of Object.entries(pkg.scripts)) {\n if (/\\b(?:eslint|prettier)\\b/.test(command))\n review(\n output,\n \"package.json\",\n `Replace the custom ${name} script (${command}) with oxlint or oxfmt; the legacy tools have been removed from dependencies.`,\n );\n }\n context.text.write(\"package.json\", `${JSON.stringify(pkg, null, 2)}\\n`, change);\n\n for (const file of [\".oxlintrc.json\", \".oxfmtrc.json\"]) {\n if (context.text.read(file) === undefined)\n context.text.write(file, asset(file.slice(1)), change);\n }\n for (const file of legacyFiles) {\n const content = context.text.read(file);\n const known = [\"eslint.config.js\", \".prettierrc.json\", \".prettierignore\"].includes(file);\n if (content === undefined) continue;\n if (!known || !sameGenerated(content, asset(`legacy-${file.replace(/^\\./, \"\")}`))) {\n review(\n output,\n file,\n \"Customized legacy config retained. Port its rules, plugins, formatting or ignore patterns to .oxlintrc.json / .oxfmtrc.json / .oxfmtignore, then remove this file. Legacy support is removed in 5.34.0.\",\n );\n continue;\n }\n if (file === \".prettierignore\") {\n const existing = context.text.read(\".oxfmtignore\");\n if (existing === undefined) context.text.write(\".oxfmtignore\", content, change);\n else if (existing.trim() !== content.trim()) {\n review(\n output,\n file,\n \"Merge these ignore patterns into the existing .oxfmtignore, then remove .prettierignore.\",\n );\n continue;\n }\n }\n context.text.remove(file, change);\n }\n // Oxfmt 0.73 uses .prettierignore by default (verified with --help).\n // Explicit script ignore paths make the migrated .oxfmtignore effective.\n if (context.text.read(\".oxfmtignore\") === undefined) {\n context.text.write(\".oxfmtignore\", \"node_modules\\ndist\\n\", change);\n }\n for (const name of [\"settings.json\", \"extensions.json\"]) {\n const file = `.vscode/${name}`;\n const content = context.text.read(file);\n if (content === undefined) continue;\n if (name === \"settings.json\" && sameGenerated(content, asset(`legacy-vscode-${name}`)))\n context.text.write(file, asset(`oxc-vscode-${name}`), change);\n else\n review(\n output,\n file,\n \"Review editor settings: select oxc.oxc-vscode as the formatter, enable source.fixAll.oxc and remove ESLint/Prettier extension recommendations.\",\n );\n }\n migrateHealthSwitches(context, output);\n return output;\n },\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"oxc-toolchain.mjs","names":[],"sources":["../../../../../../../../../packages/core/src/upgrade/codemods/oxc-toolchain.ts"],"sourcesContent":["import type { Codemod, CodemodContext, CodemodOutput } from \"../types\";\nimport { isRecord } from \"./validate-oxlint-rule\";\nimport { portEslintRules } from \"./port-eslint-rules\";\nimport { TOOLCHAIN_TEMPLATES } from \"./toolchain-templates\";\n\n/** Snapshots ship with core; parity specs keep them aligned with create-warlock. */\nfunction asset(name: string): string {\n const content = TOOLCHAIN_TEMPLATES[name];\n if (content === undefined) throw new Error(`Unknown toolchain template: ${name}`);\n return content;\n}\n\nexport const OXC_VERSIONS = { oxlint: \"1.88.0\", oxfmt: \"0.73.0\", typescript: \"7.0.2\" };\nexport const OXC_SCRIPTS = {\n lint: \"oxlint --fix ./src --max-warnings=0\",\n \"lint:check\": \"oxlint ./src --max-warnings=0\",\n format: \"oxfmt --ignore-path .gitignore --ignore-path .oxfmtignore --write ./src\",\n \"format:check\": \"oxfmt --ignore-path .gitignore --ignore-path .oxfmtignore --check ./src\",\n};\n\nfunction legacyDependency(name: string): boolean {\n return (\n /^(eslint|prettier|typescript-eslint|@types\\/prettier)$/.test(name) ||\n name.startsWith(\"@typescript-eslint/\") ||\n /(?:^|\\/)eslint-config-/.test(name) ||\n /(?:^|\\/)eslint-plugin-/.test(name) ||\n /(?:^|\\/)prettier-plugin-/.test(name) ||\n name.startsWith(\"@prettier/plugin-\")\n );\n}\n\nfunction sameGenerated(source: string, expected: string): boolean {\n // JSON may have been reformatted by the app; compare its data. Executable\n // configs are deliberately exact (apart from line endings/trailing space).\n try {\n return JSON.stringify(JSON.parse(source)) === JSON.stringify(JSON.parse(expected));\n } catch {\n return source.replace(/\\r\\n/g, \"\\n\").trim() === expected.replace(/\\r\\n/g, \"\\n\").trim();\n }\n}\n\nfunction review(output: CodemodOutput, file: string, hint: string, line = 1): void {\n output.manual.push({ file, line, hint });\n}\n\nfunction migrateHealthSwitches(context: CodemodContext, output: CodemodOutput): void {\n const file = \"warlock.config.ts\";\n const source = context.text.read(file);\n if (source === undefined) return;\n const project = new context.tsMorph.Project({ useInMemoryFileSystem: true });\n const config = project.createSourceFile(file, source);\n const switches = config\n .getDescendantsOfKind(context.tsMorph.SyntaxKind.PropertyAssignment)\n .filter((property) => property.getName() === \"healthCheckers\");\n let changed = false;\n for (const property of switches) {\n const value = property.getInitializer();\n if (!value || !context.tsMorph.Node.isObjectLiteralExpression(value)) {\n if (value?.getText() !== \"false\")\n review(\n output,\n file,\n \"Review custom healthCheckers; remove ESLint checkers and enable Oxlint. ESLint support is removed in 5.34.0.\",\n property.getStartLineNumber(),\n );\n continue;\n }\n for (const spread of value.getProperties().filter(context.tsMorph.Node.isSpreadAssignment)) {\n review(\n output,\n file,\n \"Review spread healthCheckers options; remove eslint and enable oxlint after the spread.\",\n spread.getStartLineNumber(),\n );\n }\n const eslint = value.getProperty(\"eslint\");\n if (!eslint) continue;\n if (eslint) {\n eslint.remove();\n changed = true;\n }\n for (const [name, next] of [[\"oxlint\", \"true\"]] as const) {\n const option = value.getProperty(name);\n if (!option) continue;\n if (\n !context.tsMorph.Node.isPropertyAssignment(option) ||\n ![\"true\", \"false\"].includes(option.getInitializer()?.getText() ?? \"\")\n ) {\n review(\n output,\n file,\n `Set healthCheckers.${name} to ${next} after reviewing this computed option.`,\n option.getStartLineNumber(),\n );\n continue;\n }\n if (option.getInitializer()?.getText() !== next) {\n option.setInitializer(next);\n changed = true;\n }\n }\n }\n if (changed)\n context.text.write(file, config.getFullText(), {\n line: 1,\n description: \"Select Oxlint instead of ESLint for background health checks\",\n });\n}\n\nexport const oxcToolchain: Codemod = {\n id: \"oxc-toolchain\",\n version: \"5.33.0\",\n package: \"@warlock.js/core\",\n title: \"Migrate ESLint and Prettier to Oxlint and Oxfmt\",\n skill: \"upgrade-from-5-29\",\n run(context) {\n const output: CodemodOutput = { edits: [], manual: [] };\n const source = context.text.read(\"package.json\");\n if (source === undefined) return output;\n const pkg = JSON.parse(source) as {\n scripts?: Record<string, string>;\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n eslintConfig?: unknown;\n prettier?: unknown;\n };\n const legacyFiles = context.text\n .list()\n .filter((file) =>\n /^(eslint\\.config\\..+|\\.eslintrc(?:\\..+)?|\\.prettierrc(?:\\..+)?|prettier\\.config\\..+|\\.prettierignore|\\.eslintignore)$/.test(\n file,\n ),\n );\n const dependencies = [pkg.dependencies, pkg.devDependencies];\n const legacyScripts = Object.values(pkg.scripts ?? {}).some((script) =>\n /\\b(?:eslint|prettier)\\b/.test(script),\n );\n if (\n !legacyFiles.length &&\n !legacyScripts &&\n pkg.eslintConfig === undefined &&\n pkg.prettier === undefined &&\n !dependencies.some((deps) => Object.keys(deps ?? {}).some(legacyDependency))\n ) {\n if (\n /\\beslint\\b|EslintHealthChecker|ESLint/.test(context.text.read(\"warlock.config.ts\") ?? \"\")\n )\n migrateHealthSwitches(context, output);\n return output;\n }\n\n const change = {\n line: 1,\n description: \"Replace ESLint/Prettier with the default Oxlint/Oxfmt toolchain\",\n };\n for (const deps of dependencies) {\n for (const name of Object.keys(deps ?? {})) {\n if (deps && (legacyDependency(name) || name in OXC_VERSIONS)) delete deps[name];\n }\n }\n pkg.devDependencies = { ...pkg.devDependencies, ...OXC_VERSIONS };\n pkg.scripts = { ...pkg.scripts, ...OXC_SCRIPTS };\n if (/\\beslint\\b/.test(pkg.scripts.fix ?? \"\")) pkg.scripts.fix = OXC_SCRIPTS.lint;\n for (const [name, command] of Object.entries(pkg.scripts)) {\n if (/\\b(?:eslint|prettier)\\b/.test(command))\n review(\n output,\n \"package.json\",\n `Replace the custom ${name} script (${command}) with oxlint or oxfmt; the legacy tools have been removed from dependencies.`,\n );\n }\n\n const hadOxlint = context.text.read(\".oxlintrc.json\") !== undefined;\n for (const file of [\".oxlintrc.json\", \".oxfmtrc.json\"]) {\n if (context.text.read(file) === undefined)\n context.text.write(file, asset(file.slice(1)), change);\n }\n if (pkg.eslintConfig !== undefined) {\n const findings = output.manual.length;\n if (portEslintRules(context, output, \"package.json\", source, hadOxlint, \"eslintConfig\"))\n pkg.devDependencies[\"oxlint-tsgolint\"] = \"7.0.2004\";\n if (output.manual.length === findings) delete pkg.eslintConfig;\n }\n if (pkg.prettier !== undefined) {\n if (sameGenerated(JSON.stringify(pkg.prettier), asset(\"legacy-prettierrc.json\")))\n delete pkg.prettier;\n else\n review(\n output,\n \"package.json\",\n \"Port the custom prettier field to .oxfmtrc.json, then remove it. Prettier support is gone in 5.34.0.\",\n );\n }\n for (const file of legacyFiles) {\n const content = context.text.read(file);\n if (file === \".eslintignore\" && content !== undefined) {\n try {\n const config: unknown = JSON.parse(context.text.read(\".oxlintrc.json\") ?? \"{}\");\n if (\n !isRecord(config) ||\n (config.ignorePatterns !== undefined &&\n (!Array.isArray(config.ignorePatterns) ||\n !config.ignorePatterns.every((pattern) => typeof pattern === \"string\")))\n )\n throw new Error(\"Invalid ignore patterns\");\n config.ignorePatterns = [\n ...new Set([\n ...(Array.isArray(config.ignorePatterns) ? config.ignorePatterns : []),\n ...content\n .split(/\\r?\\n/)\n .filter((line) => line.trim() && !line.trimStart().startsWith(\"#\")),\n ]),\n ];\n context.text.write(\".oxlintrc.json\", `${JSON.stringify(config, null, 2)}\\n`, change);\n } catch {\n review(\n output,\n file,\n \"Port these ignore patterns after repairing .oxlintrc.json; ESLint support is gone in 5.34.0.\",\n );\n continue;\n }\n context.text.remove(file, change);\n continue;\n }\n const known = [\"eslint.config.js\", \".prettierrc.json\", \".prettierignore\"].includes(file);\n if (content === undefined) continue;\n const generated = known && sameGenerated(content, asset(`legacy-${file.replace(/^\\./, \"\")}`));\n if (!generated && /^(eslint\\.config\\..+|\\.eslintrc(?:\\..+)?)$/.test(file)) {\n const findings = output.manual.length;\n if (portEslintRules(context, output, file, content, hadOxlint))\n pkg.devDependencies[\"oxlint-tsgolint\"] = \"7.0.2004\";\n // Keep the source only when there is still something a person must translate.\n if (output.manual.length === findings) context.text.remove(file, change);\n continue;\n }\n if (!generated) {\n review(\n output,\n file,\n \"Port customized formatting or ignore options to .oxfmtrc.json / .oxfmtignore, then remove this file. Legacy support is gone in 5.34.0.\",\n );\n continue;\n }\n if (file === \".prettierignore\") {\n const existing = context.text.read(\".oxfmtignore\");\n if (existing === undefined)\n context.text.write(\".oxfmtignore\", `${content.trimEnd()}\\n`, change);\n else if (existing.trim() !== content.trim()) {\n review(\n output,\n file,\n \"Merge these ignore patterns into the existing .oxfmtignore, then remove .prettierignore.\",\n );\n continue;\n }\n }\n context.text.remove(file, change);\n }\n // Oxfmt 0.73 uses .prettierignore by default (verified with --help).\n // Explicit script ignore paths make the migrated .oxfmtignore effective.\n if (context.text.read(\".oxfmtignore\") === undefined) {\n context.text.write(\".oxfmtignore\", \"node_modules\\ndist\\n\", change);\n }\n for (const name of [\"settings.json\", \"extensions.json\"]) {\n const file = `.vscode/${name}`;\n const content = context.text.read(file);\n if (content === undefined) continue;\n if (name === \"settings.json\" && sameGenerated(content, asset(`oxc-vscode-${name}`))) continue;\n if (name === \"settings.json\" && sameGenerated(content, asset(`legacy-vscode-${name}`)))\n context.text.write(file, asset(`oxc-vscode-${name}`), change);\n else\n review(\n output,\n file,\n \"Review editor settings: select oxc.oxc-vscode as the formatter, enable source.fixAll.oxc and remove ESLint/Prettier extension recommendations.\",\n );\n }\n migrateHealthSwitches(context, output);\n context.text.write(\"package.json\", `${JSON.stringify(pkg, null, 2)}\\n`, change);\n return output;\n },\n};\n\n/** Run again for apps that skipped or partially completed the 5.33 migration. */\nexport const oxcToolchainRemoval: Codemod = {\n ...oxcToolchain,\n id: \"oxc-toolchain-removal\",\n version: \"5.34.0\",\n title: \"ESLint/Prettier support is gone in 5.34.0; migrate to the Oxlint/Oxfmt default\",\n};\n"],"mappings":"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"}
|