@warlock.js/core 5.32.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 +64 -46
- package/esm/application/application-config-types.d.mts +8 -0
- package/esm/application/application-config-types.d.mts.map +1 -1
- package/esm/application/boot-signal.d.mts +8 -8
- package/esm/application/boot-signal.d.mts.map +1 -1
- package/esm/application/boot-signal.mjs +15 -9
- package/esm/application/boot-signal.mjs.map +1 -1
- package/esm/cli/commands/ai/ai-command.action.mjs +140 -0
- package/esm/cli/commands/ai/ai-command.action.mjs.map +1 -0
- package/esm/cli/commands/ai.command.mjs +50 -0
- package/esm/cli/commands/ai.command.mjs.map +1 -0
- package/esm/cli/commands/check/check-command.action.mjs +4 -0
- package/esm/cli/commands/check/check-command.action.mjs.map +1 -1
- package/esm/cli/commands/check.command.mjs +6 -1
- 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/commands/pm2/pm2-command.action.mjs +91 -0
- package/esm/cli/commands/pm2/pm2-command.action.mjs.map +1 -0
- package/esm/cli/commands/pm2/pm2-config.mjs +115 -0
- package/esm/cli/commands/pm2/pm2-config.mjs.map +1 -0
- package/esm/cli/commands/pm2.command.mjs +53 -0
- package/esm/cli/commands/pm2.command.mjs.map +1 -0
- package/esm/cli/framework-cli-commands.mjs +6 -0
- package/esm/cli/framework-cli-commands.mjs.map +1 -1
- package/esm/connectors/connectors-manager.d.mts.map +1 -1
- package/esm/connectors/connectors-manager.mjs +1 -4
- package/esm/connectors/connectors-manager.mjs.map +1 -1
- package/esm/connectors/shutdown-timeout.mjs +7 -0
- package/esm/connectors/shutdown-timeout.mjs.map +1 -0
- package/esm/connectors/socket-connector.d.mts.map +1 -1
- package/esm/connectors/socket-connector.mjs +8 -1
- package/esm/connectors/socket-connector.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 +2 -16
- 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 +1 -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/generations/features/index.mjs +2 -0
- package/esm/generations/features/index.mjs.map +1 -1
- package/esm/generations/features/process.feature.mjs +65 -0
- package/esm/generations/features/process.feature.mjs.map +1 -0
- package/esm/http/port-preflight.d.mts.map +1 -1
- package/esm/http/port-preflight.mjs +2 -0
- package/esm/http/port-preflight.mjs.map +1 -1
- package/esm/index.d.mts +7 -2
- package/esm/index.mjs +7 -2
- package/esm/secrets/errors.d.mts +9 -0
- package/esm/secrets/errors.d.mts.map +1 -0
- package/esm/secrets/errors.mjs +24 -0
- package/esm/secrets/errors.mjs.map +1 -0
- package/esm/secrets/file-backend.mjs +167 -0
- package/esm/secrets/file-backend.mjs.map +1 -0
- package/esm/secrets/index.d.mts +6 -0
- package/esm/secrets/index.mjs +6 -0
- package/esm/secrets/keyring-backend.mjs +50 -0
- package/esm/secrets/keyring-backend.mjs.map +1 -0
- package/esm/secrets/memory-backend.d.mts +12 -0
- package/esm/secrets/memory-backend.d.mts.map +1 -0
- package/esm/secrets/memory-backend.mjs +28 -0
- package/esm/secrets/memory-backend.mjs.map +1 -0
- package/esm/secrets/resolve-driver.mjs +14 -0
- package/esm/secrets/resolve-driver.mjs.map +1 -0
- package/esm/secrets/secret-store.d.mts +25 -0
- package/esm/secrets/secret-store.d.mts.map +1 -0
- package/esm/secrets/secret-store.mjs +120 -0
- package/esm/secrets/secret-store.mjs.map +1 -0
- package/esm/secrets/secrets.d.mts +11 -0
- package/esm/secrets/secrets.d.mts.map +1 -0
- package/esm/secrets/secrets.mjs +72 -0
- package/esm/secrets/secrets.mjs.map +1 -0
- package/esm/secrets/types.d.mts +26 -0
- package/esm/secrets/types.d.mts.map +1 -0
- package/esm/socket/index.d.mts +2 -2
- package/esm/socket/index.mjs +2 -2
- package/esm/socket/utils.d.mts +7 -0
- package/esm/socket/utils.d.mts.map +1 -1
- package/esm/socket/utils.mjs +12 -1
- package/esm/socket/utils.mjs.map +1 -1
- package/esm/tests/fakes/index.d.mts +2 -1
- package/esm/tests/fakes/index.mjs +2 -1
- package/esm/tests/fakes/secrets-fake.d.mts +13 -0
- package/esm/tests/fakes/secrets-fake.d.mts.map +1 -0
- package/esm/tests/fakes/secrets-fake.mjs +50 -0
- package/esm/tests/fakes/secrets-fake.mjs.map +1 -0
- package/esm/tests/fakes/test-fakes.d.mts +2 -2
- package/esm/tests/fakes/test-fakes.d.mts.map +1 -1
- package/esm/tests/fakes/test-fakes.mjs +5 -2
- package/esm/tests/fakes/test-fakes.mjs.map +1 -1
- package/esm/tests/index.d.mts +2 -1
- package/esm/tests/index.mjs +2 -1
- package/esm/tests/vitest-setup.d.mts +1 -1
- package/esm/tests/vitest-setup.mjs.map +1 -1
- package/esm/tooling/check/lint-step.d.mts +2 -8
- package/esm/tooling/check/lint-step.d.mts.map +1 -1
- package/esm/tooling/check/lint-step.mjs +1 -42
- package/esm/tooling/check/lint-step.mjs.map +1 -1
- package/esm/tooling/check/run-check.d.mts +2 -0
- package/esm/tooling/check/run-check.d.mts.map +1 -1
- package/esm/tooling/check/run-check.mjs +3 -1
- 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 +3 -0
- package/esm/upgrade/codemods/index.mjs.map +1 -1
- package/esm/upgrade/codemods/oxc-toolchain.mjs +191 -0
- package/esm/upgrade/codemods/oxc-toolchain.mjs.map +1 -0
- 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 +244 -0
- package/esm/upgrade/codemods/toolchain-templates.mjs.map +1 -0
- 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/upgrade/run-upgrade.mjs +25 -6
- package/esm/upgrade/run-upgrade.mjs.map +1 -1
- package/esm/warlock-config/types.d.mts +1 -1
- package/llms-full.txt +538 -29
- package/llms.txt +5 -3
- package/package.json +29 -20
- package/skills/README.md +2 -1
- package/skills/create-module/SKILL.md +2 -2
- package/skills/index.md +1 -1
- package/skills/run-app/SKILL.md +115 -6
- package/skills/store-secrets/SKILL.md +141 -0
- package/skills/test-browser/SKILL.md +119 -0
- package/skills/test-fakes/SKILL.md +13 -11
- package/skills/upgrade-from-5-29/SKILL.md +85 -7
- package/skills/warlock-check/SKILL.md +7 -3
- package/skills/warlock-doctor/SKILL.md +8 -0
- package/skills/wire-socket/SKILL.md +19 -0
- package/skills/write-cli-command/SKILL.md +21 -0
- package/esm/dev-server/health-checker/checkers/eslint-health-checker.mjs +0 -154
- package/esm/dev-server/health-checker/checkers/eslint-health-checker.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 -192
- package/esm/dev-server/health-checker/workers/eslint-health.worker.mjs.map +0 -1
|
@@ -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 /** 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);\n\n if (linters.length === 0) {\n return { status: \"skipped\", detail: \"no ESLint or oxlint config\", problems: [] };\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":";;;;;;;;;;;;AA0DA,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,SAAS;EAEjE,IAAI,QAAQ,WAAW,GACrB,OAAO;GAAE,QAAQ;GAAW,QAAQ;GAA8B,UAAU,CAAC;EAAE;EAGjF,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,6 +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, oxcToolchainRemoval } from "./oxc-toolchain.mjs";
|
|
5
6
|
import { requestLogSnapshot } from "./request-log-snapshot.mjs";
|
|
6
7
|
import { aiAnthropicBody, aiCompactionOptIn, aiFinishReason, aiToolDispatch, rateLimitDefaults, sealContainerCatch, sealRefineOutput, sealUnionOutput, sealValidateResult } from "./review-sites.mjs";
|
|
7
8
|
|
|
@@ -26,6 +27,8 @@ const CODEMODS = [
|
|
|
26
27
|
sealContainerCatch,
|
|
27
28
|
sealUnionOutput,
|
|
28
29
|
aiCompactionOptIn,
|
|
30
|
+
oxcToolchain,
|
|
31
|
+
oxcToolchainRemoval,
|
|
29
32
|
warlockVersions
|
|
30
33
|
];
|
|
31
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 { 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 warlockVersions,\n];\n\nexport * from \"./helpers\";\n"],"mappings":"
|
|
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"}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { isRecord } from "./validate-oxlint-rule.mjs";
|
|
2
|
+
import { portEslintRules } from "./port-eslint-rules.mjs";
|
|
3
|
+
import { TOOLCHAIN_TEMPLATES } from "./toolchain-templates.mjs";
|
|
4
|
+
|
|
5
|
+
//#region ../../packages/core/src/upgrade/codemods/oxc-toolchain.ts
|
|
6
|
+
/** Snapshots ship with core; parity specs keep them aligned with create-warlock. */
|
|
7
|
+
function asset(name) {
|
|
8
|
+
const content = TOOLCHAIN_TEMPLATES[name];
|
|
9
|
+
if (content === void 0) throw new Error(`Unknown toolchain template: ${name}`);
|
|
10
|
+
return content;
|
|
11
|
+
}
|
|
12
|
+
const OXC_VERSIONS = {
|
|
13
|
+
oxlint: "1.88.0",
|
|
14
|
+
oxfmt: "0.73.0",
|
|
15
|
+
typescript: "7.0.2"
|
|
16
|
+
};
|
|
17
|
+
const OXC_SCRIPTS = {
|
|
18
|
+
lint: "oxlint --fix ./src --max-warnings=0",
|
|
19
|
+
"lint:check": "oxlint ./src --max-warnings=0",
|
|
20
|
+
format: "oxfmt --ignore-path .gitignore --ignore-path .oxfmtignore --write ./src",
|
|
21
|
+
"format:check": "oxfmt --ignore-path .gitignore --ignore-path .oxfmtignore --check ./src"
|
|
22
|
+
};
|
|
23
|
+
function legacyDependency(name) {
|
|
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-");
|
|
25
|
+
}
|
|
26
|
+
function sameGenerated(source, expected) {
|
|
27
|
+
try {
|
|
28
|
+
return JSON.stringify(JSON.parse(source)) === JSON.stringify(JSON.parse(expected));
|
|
29
|
+
} catch {
|
|
30
|
+
return source.replace(/\r\n/g, "\n").trim() === expected.replace(/\r\n/g, "\n").trim();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function review(output, file, hint, line = 1) {
|
|
34
|
+
output.manual.push({
|
|
35
|
+
file,
|
|
36
|
+
line,
|
|
37
|
+
hint
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
function migrateHealthSwitches(context, output) {
|
|
41
|
+
const file = "warlock.config.ts";
|
|
42
|
+
const source = context.text.read(file);
|
|
43
|
+
if (source === void 0) return;
|
|
44
|
+
const config = new context.tsMorph.Project({ useInMemoryFileSystem: true }).createSourceFile(file, source);
|
|
45
|
+
const switches = config.getDescendantsOfKind(context.tsMorph.SyntaxKind.PropertyAssignment).filter((property) => property.getName() === "healthCheckers");
|
|
46
|
+
let changed = false;
|
|
47
|
+
for (const property of switches) {
|
|
48
|
+
const value = property.getInitializer();
|
|
49
|
+
if (!value || !context.tsMorph.Node.isObjectLiteralExpression(value)) {
|
|
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());
|
|
51
|
+
continue;
|
|
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"]]) {
|
|
61
|
+
const option = value.getProperty(name);
|
|
62
|
+
if (!option) continue;
|
|
63
|
+
if (!context.tsMorph.Node.isPropertyAssignment(option) || !["true", "false"].includes(option.getInitializer()?.getText() ?? "")) {
|
|
64
|
+
review(output, file, `Set healthCheckers.${name} to ${next} after reviewing this computed option.`, option.getStartLineNumber());
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
if (option.getInitializer()?.getText() !== next) {
|
|
68
|
+
option.setInitializer(next);
|
|
69
|
+
changed = true;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (changed) context.text.write(file, config.getFullText(), {
|
|
74
|
+
line: 1,
|
|
75
|
+
description: "Select Oxlint instead of ESLint for background health checks"
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
const oxcToolchain = {
|
|
79
|
+
id: "oxc-toolchain",
|
|
80
|
+
version: "5.33.0",
|
|
81
|
+
package: "@warlock.js/core",
|
|
82
|
+
title: "Migrate ESLint and Prettier to Oxlint and Oxfmt",
|
|
83
|
+
skill: "upgrade-from-5-29",
|
|
84
|
+
run(context) {
|
|
85
|
+
const output = {
|
|
86
|
+
edits: [],
|
|
87
|
+
manual: []
|
|
88
|
+
};
|
|
89
|
+
const source = context.text.read("package.json");
|
|
90
|
+
if (source === void 0) return output;
|
|
91
|
+
const pkg = JSON.parse(source);
|
|
92
|
+
const legacyFiles = context.text.list().filter((file) => /^(eslint\.config\..+|\.eslintrc(?:\..+)?|\.prettierrc(?:\..+)?|prettier\.config\..+|\.prettierignore|\.eslintignore)$/.test(file));
|
|
93
|
+
const dependencies = [pkg.dependencies, pkg.devDependencies];
|
|
94
|
+
const legacyScripts = Object.values(pkg.scripts ?? {}).some((script) => /\b(?:eslint|prettier)\b/.test(script));
|
|
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
|
+
}
|
|
99
|
+
const change = {
|
|
100
|
+
line: 1,
|
|
101
|
+
description: "Replace ESLint/Prettier with the default Oxlint/Oxfmt toolchain"
|
|
102
|
+
};
|
|
103
|
+
for (const deps of dependencies) for (const name of Object.keys(deps ?? {})) if (deps && (legacyDependency(name) || name in OXC_VERSIONS)) delete deps[name];
|
|
104
|
+
pkg.devDependencies = {
|
|
105
|
+
...pkg.devDependencies,
|
|
106
|
+
...OXC_VERSIONS
|
|
107
|
+
};
|
|
108
|
+
pkg.scripts = {
|
|
109
|
+
...pkg.scripts,
|
|
110
|
+
...OXC_SCRIPTS
|
|
111
|
+
};
|
|
112
|
+
if (/\beslint\b/.test(pkg.scripts.fix ?? "")) pkg.scripts.fix = OXC_SCRIPTS.lint;
|
|
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.`);
|
|
114
|
+
const hadOxlint = context.text.read(".oxlintrc.json") !== void 0;
|
|
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
|
+
}
|
|
125
|
+
for (const file of legacyFiles) {
|
|
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
|
+
}
|
|
140
|
+
const known = [
|
|
141
|
+
"eslint.config.js",
|
|
142
|
+
".prettierrc.json",
|
|
143
|
+
".prettierignore"
|
|
144
|
+
].includes(file);
|
|
145
|
+
if (content === void 0) continue;
|
|
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.");
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
if (file === ".prettierignore") {
|
|
158
|
+
const existing = context.text.read(".oxfmtignore");
|
|
159
|
+
if (existing === void 0) context.text.write(".oxfmtignore", `${content.trimEnd()}\n`, change);
|
|
160
|
+
else if (existing.trim() !== content.trim()) {
|
|
161
|
+
review(output, file, "Merge these ignore patterns into the existing .oxfmtignore, then remove .prettierignore.");
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
context.text.remove(file, change);
|
|
166
|
+
}
|
|
167
|
+
if (context.text.read(".oxfmtignore") === void 0) context.text.write(".oxfmtignore", "node_modules\ndist\n", change);
|
|
168
|
+
for (const name of ["settings.json", "extensions.json"]) {
|
|
169
|
+
const file = `.vscode/${name}`;
|
|
170
|
+
const content = context.text.read(file);
|
|
171
|
+
if (content === void 0) continue;
|
|
172
|
+
if (name === "settings.json" && sameGenerated(content, asset(`oxc-vscode-${name}`))) continue;
|
|
173
|
+
if (name === "settings.json" && sameGenerated(content, asset(`legacy-vscode-${name}`))) context.text.write(file, asset(`oxc-vscode-${name}`), change);
|
|
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.");
|
|
175
|
+
}
|
|
176
|
+
migrateHealthSwitches(context, output);
|
|
177
|
+
context.text.write("package.json", `${JSON.stringify(pkg, null, 2)}\n`, change);
|
|
178
|
+
return output;
|
|
179
|
+
}
|
|
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
|
+
};
|
|
188
|
+
|
|
189
|
+
//#endregion
|
|
190
|
+
export { OXC_SCRIPTS, OXC_VERSIONS, oxcToolchain, oxcToolchainRemoval };
|
|
191
|
+
//# sourceMappingURL=oxc-toolchain.mjs.map
|
|
@@ -0,0 +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 { 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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"}
|