@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
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toolchain-templates.mjs","names":[],"sources":["../../../../../../../../../packages/core/src/upgrade/codemods/toolchain-templates.ts"],"sourcesContent":["/** Bundled create-warlock snapshots. oxc-toolchain.spec.ts checks template parity. */\nexport const TOOLCHAIN_TEMPLATES: Readonly<Record<string, string>> = {\n \"legacy-eslint.config.js\": `import tsPlugin from \"@typescript-eslint/eslint-plugin\";\nimport tsParser from \"@typescript-eslint/parser\";\nimport prettierConfig from \"eslint-config-prettier\";\nimport prettierPlugin from \"eslint-plugin-prettier\";\nimport unusedImports from \"eslint-plugin-unused-imports\";\n\nexport default [\n // Global configuration\n {\n languageOptions: {\n ecmaVersion: \"latest\",\n sourceType: \"module\",\n globals: {\n // Node.js globals\n console: \"readonly\",\n process: \"readonly\",\n Buffer: \"readonly\",\n __dirname: \"readonly\",\n __filename: \"readonly\",\n global: \"readonly\",\n module: \"readonly\",\n require: \"readonly\",\n exports: \"readonly\",\n // ES2021 globals\n Promise: \"readonly\",\n // Jest globals\n describe: \"readonly\",\n it: \"readonly\",\n test: \"readonly\",\n expect: \"readonly\",\n beforeEach: \"readonly\",\n afterEach: \"readonly\",\n beforeAll: \"readonly\",\n afterAll: \"readonly\",\n jest: \"readonly\",\n },\n },\n },\n\n // TypeScript files configuration\n {\n files: [\"**/*.ts\", \"**/*.tsx\"],\n languageOptions: {\n parser: tsParser,\n parserOptions: {\n ecmaVersion: \"latest\",\n sourceType: \"module\",\n },\n },\n plugins: {\n \"@typescript-eslint\": tsPlugin,\n prettier: prettierPlugin,\n \"unused-imports\": unusedImports,\n },\n rules: {\n // Prettier integration\n ...prettierConfig.rules,\n \"prettier/prettier\": \"error\",\n\n // TypeScript rules\n \"@typescript-eslint/no-explicit-any\": \"off\",\n \"@typescript-eslint/no-unused-vars\": \"off\",\n \"no-unused-vars\": \"off\",\n \"unused-imports/no-unused-vars\": [\n \"warn\",\n {\n vars: \"all\",\n varsIgnorePattern: \"^_\",\n args: \"after-used\",\n argsIgnorePattern: \"^_\",\n },\n ],\n \"unused-imports/no-unused-imports\": \"error\",\n \"@typescript-eslint/explicit-member-accessibility\": [\n \"error\",\n { accessibility: \"explicit\" },\n ],\n \"@typescript-eslint/consistent-type-imports\": [\n \"error\",\n {\n prefer: \"type-imports\",\n disallowTypeAnnotations: false,\n },\n ],\n },\n },\n\n // Ignore patterns\n {\n ignores: [\n \"dist/\",\n \"node_modules/\",\n \"**/*.js\",\n \"!**/*.config.js\",\n \"!eslint.config.js\",\n ],\n },\n];\n`,\n \"legacy-prettierignore\": `node_modules\ndist\n\n\n`,\n \"legacy-prettierrc.json\": `{\n \"semi\": true,\n \"tabWidth\": 2,\n \"printWidth\": 100,\n \"singleQuote\": false,\n \"arrowParens\": \"always\",\n \"trailingComma\": \"all\",\n \"endOfLine\": \"lf\",\n \"plugins\": [\"@ianvs/prettier-plugin-sort-imports\"],\n \"importOrder\": [\"<BUILTIN_MODULES>\", \"<THIRD_PARTY_MODULES>\", \"^(app|web|@shared)/\", \"^[.]\"],\n \"importOrderParserPlugins\": [\"typescript\", \"jsx\", \"decorators\"]\n}\n`,\n \"legacy-vscode-settings.json\": `{\n \"editor.defaultFormatter\": \"esbenp.prettier-vscode\",\n \"editor.formatOnSave\": true,\n \"editor.codeActionsOnSave\": {\n \"source.fixAll.eslint\": \"explicit\",\n \"source.organizeImports\": \"never\"\n },\n \"[typescript]\": {\n \"editor.defaultFormatter\": \"esbenp.prettier-vscode\",\n \"editor.formatOnSave\": true\n },\n \"[typescriptreact]\": {\n \"editor.defaultFormatter\": \"esbenp.prettier-vscode\",\n \"editor.formatOnSave\": true\n },\n \"[javascript]\": {\n \"editor.defaultFormatter\": \"esbenp.prettier-vscode\",\n \"editor.formatOnSave\": true\n },\n \"[javascriptreact]\": {\n \"editor.defaultFormatter\": \"esbenp.prettier-vscode\",\n \"editor.formatOnSave\": true\n },\n \"[json]\": {\n \"editor.defaultFormatter\": \"esbenp.prettier-vscode\",\n \"editor.formatOnSave\": true\n },\n \"[css]\": {\n \"editor.defaultFormatter\": \"esbenp.prettier-vscode\",\n \"editor.formatOnSave\": true\n },\n \"prettier.configPath\": \".prettierrc.json\",\n \"prettier.requireConfig\": true,\n \"prettier.ignorePath\": \".prettierignore\",\n \"prettier.documentSelectors\": [\"**/*.{ts,tsx,js,jsx,json,css,md}\"],\n \"prettier.enable\": true,\n \"prettier.useEditorConfig\": false,\n \"prettier.resolveGlobalModules\": false,\n \"eslint.format.enable\": false,\n \"eslint.codeActionsOnSave.mode\": \"all\"\n}\n`,\n \"oxc-vscode-settings.json\": `{\n \"editor.defaultFormatter\": \"oxc.oxc-vscode\",\n \"editor.formatOnSave\": true,\n \"editor.codeActionsOnSave\": {\n \"source.fixAll.oxc\": \"explicit\",\n \"source.organizeImports\": \"never\"\n },\n \"[typescript]\": {\n \"editor.defaultFormatter\": \"oxc.oxc-vscode\",\n \"editor.formatOnSave\": true\n },\n \"[typescriptreact]\": {\n \"editor.defaultFormatter\": \"oxc.oxc-vscode\",\n \"editor.formatOnSave\": true\n },\n \"[javascript]\": {\n \"editor.defaultFormatter\": \"oxc.oxc-vscode\",\n \"editor.formatOnSave\": true\n },\n \"[javascriptreact]\": {\n \"editor.defaultFormatter\": \"oxc.oxc-vscode\",\n \"editor.formatOnSave\": true\n },\n \"[json]\": {\n \"editor.defaultFormatter\": \"oxc.oxc-vscode\",\n \"editor.formatOnSave\": true\n },\n \"[css]\": {\n \"editor.defaultFormatter\": \"oxc.oxc-vscode\",\n \"editor.formatOnSave\": true\n },\n \"oxc.enable.oxlint\": true,\n \"oxc.enable.oxfmt\": true,\n \"oxc.requireConfig\": true\n}\n`,\n \"oxfmtrc.json\": `{\n \"$schema\": \"./node_modules/oxfmt/configuration_schema.json\",\n \"semi\": true,\n \"tabWidth\": 2,\n \"printWidth\": 100,\n \"singleQuote\": false,\n \"arrowParens\": \"always\",\n \"trailingComma\": \"all\",\n \"endOfLine\": \"lf\",\n \"sortImports\": {\n \"newlinesBetween\": false,\n \"internalPattern\": [\"app/\", \"web/\", \"@shared/\"]\n },\n \"ignorePatterns\": [\"node_modules/\", \"dist/\"]\n}\n`,\n \"oxlintrc.json\": `{\n \"$schema\": \"./node_modules/oxlint/configuration_schema.json\",\n \"plugins\": [\"typescript\", \"import\", \"react\"],\n \"env\": { \"node\": true, \"es2021\": true },\n \"categories\": { \"correctness\": \"error\" },\n \"rules\": {\n \"typescript/no-explicit-any\": \"off\",\n \"no-unused-vars\": [\n \"warn\",\n {\n \"vars\": \"all\",\n \"varsIgnorePattern\": \"^_\",\n \"args\": \"after-used\",\n \"argsIgnorePattern\": \"^_\"\n }\n ],\n \"typescript/explicit-member-accessibility\": [\"error\", { \"accessibility\": \"explicit\" }],\n \"typescript/consistent-type-imports\": [\n \"error\",\n { \"prefer\": \"type-imports\", \"disallowTypeAnnotations\": false }\n ]\n },\n \"ignorePatterns\": [\"node_modules/\", \"dist/\"]\n}\n`,\n};\n"],"mappings":";;AACA,MAAa,sBAAwD;CACnE,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmG3B,yBAAyB;;;;;CAKzB,0BAA0B;;;;;;;;;;;;;CAa1B,+BAA+B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0C/B,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoC5B,gBAAgB;;;;;;;;;;;;;;;;CAgBhB,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;AAyBnB"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
//#region ../../packages/core/src/upgrade/codemods/validate-oxlint-rule.ts
|
|
2
|
+
function isRecord(value) {
|
|
3
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4
|
+
}
|
|
5
|
+
/** Conservative validation before copying literal rule options into Oxc config. */
|
|
6
|
+
function matchesSchema(value, schema, definitions) {
|
|
7
|
+
if (typeof schema === "boolean") return schema;
|
|
8
|
+
if (schema.$ref) {
|
|
9
|
+
const target = definitions[schema.$ref.replace("#/definitions/", "")];
|
|
10
|
+
if (target === void 0 || !matchesSchema(value, target, definitions)) return false;
|
|
11
|
+
}
|
|
12
|
+
const matches = (candidate) => matchesSchema(value, candidate, definitions);
|
|
13
|
+
if (schema.allOf && !schema.allOf.every(matches)) return false;
|
|
14
|
+
if (schema.anyOf && !schema.anyOf.some(matches)) return false;
|
|
15
|
+
if (schema.oneOf && schema.oneOf.filter(matches).length !== 1) return false;
|
|
16
|
+
if (schema.not !== void 0 && matches(schema.not)) return false;
|
|
17
|
+
if (schema.enum && !schema.enum.some((entry) => JSON.stringify(entry) === JSON.stringify(value))) return false;
|
|
18
|
+
if ("const" in schema && JSON.stringify(schema.const) !== JSON.stringify(value)) return false;
|
|
19
|
+
if (schema.type) {
|
|
20
|
+
const types = Array.isArray(schema.type) ? schema.type : [schema.type];
|
|
21
|
+
const type = value === null ? "null" : Array.isArray(value) ? "array" : typeof value;
|
|
22
|
+
if (!types.includes(type) && !(types.includes("integer") && typeof value === "number" && Number.isInteger(value))) return false;
|
|
23
|
+
}
|
|
24
|
+
if (Array.isArray(value)) {
|
|
25
|
+
if (schema.minItems !== void 0 && value.length < schema.minItems) return false;
|
|
26
|
+
if (schema.maxItems !== void 0 && value.length > schema.maxItems) return false;
|
|
27
|
+
if (schema.uniqueItems && new Set(value.map((entry) => JSON.stringify(entry))).size !== value.length) return false;
|
|
28
|
+
const items = schema.items;
|
|
29
|
+
if (items !== void 0 && !value.every((entry, index) => {
|
|
30
|
+
return matchesSchema(entry, Array.isArray(items) ? items[index] ?? schema.additionalItems ?? true : items, definitions);
|
|
31
|
+
})) return false;
|
|
32
|
+
}
|
|
33
|
+
if (isRecord(value)) {
|
|
34
|
+
if (schema.required?.some((key) => !(key in value))) return false;
|
|
35
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
36
|
+
const property = schema.properties?.[key];
|
|
37
|
+
const patterns = Object.entries(schema.patternProperties ?? {}).filter(([pattern]) => new RegExp(pattern).test(key));
|
|
38
|
+
if (property !== void 0 && !matchesSchema(entry, property, definitions)) return false;
|
|
39
|
+
if (!patterns.every(([, pattern]) => matchesSchema(entry, pattern, definitions))) return false;
|
|
40
|
+
if (property === void 0 && patterns.length === 0 && schema.additionalProperties !== void 0 && !matchesSchema(entry, schema.additionalProperties, definitions)) return false;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
if (typeof value === "number") {
|
|
44
|
+
if (schema.minimum !== void 0 && value < schema.minimum) return false;
|
|
45
|
+
if (schema.maximum !== void 0 && value > schema.maximum) return false;
|
|
46
|
+
if (schema.exclusiveMinimum !== void 0 && value <= schema.exclusiveMinimum) return false;
|
|
47
|
+
if (schema.exclusiveMaximum !== void 0 && value >= schema.exclusiveMaximum) return false;
|
|
48
|
+
if (schema.multipleOf !== void 0 && value % schema.multipleOf !== 0) return false;
|
|
49
|
+
}
|
|
50
|
+
if (typeof value === "string") {
|
|
51
|
+
if (schema.minLength !== void 0 && value.length < schema.minLength) return false;
|
|
52
|
+
if (schema.maxLength !== void 0 && value.length > schema.maxLength) return false;
|
|
53
|
+
if (schema.pattern !== void 0 && !new RegExp(schema.pattern).test(value)) return false;
|
|
54
|
+
}
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
//#endregion
|
|
59
|
+
export { isRecord, matchesSchema };
|
|
60
|
+
//# sourceMappingURL=validate-oxlint-rule.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-oxlint-rule.mjs","names":[],"sources":["../../../../../../../../../packages/core/src/upgrade/codemods/validate-oxlint-rule.ts"],"sourcesContent":["/** JSON Schema assertions used by the pinned Oxlint rule schema snapshot. */\nexport type Schema =\n | boolean\n | {\n $ref?: string;\n type?: string | string[];\n enum?: unknown[];\n const?: unknown;\n allOf?: Schema[];\n anyOf?: Schema[];\n oneOf?: Schema[];\n not?: Schema;\n properties?: Record<string, Schema>;\n patternProperties?: Record<string, Schema>;\n additionalProperties?: Schema;\n required?: string[];\n items?: Schema | Schema[];\n additionalItems?: Schema;\n minItems?: number;\n maxItems?: number;\n uniqueItems?: boolean;\n minimum?: number;\n maximum?: number;\n exclusiveMinimum?: number;\n exclusiveMaximum?: number;\n multipleOf?: number;\n minLength?: number;\n maxLength?: number;\n pattern?: string;\n };\nexport type RuleSchemas = {\n rules: Record<string, Schema>;\n config: Record<string, Schema>;\n definitions: Record<string, Schema>;\n typeAware: string[];\n};\n\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/** Conservative validation before copying literal rule options into Oxc config. */\nexport function matchesSchema(\n value: unknown,\n schema: Schema,\n definitions: Record<string, Schema>,\n): boolean {\n if (typeof schema === \"boolean\") return schema;\n if (schema.$ref) {\n const target = definitions[schema.$ref.replace(\"#/definitions/\", \"\")];\n if (target === undefined || !matchesSchema(value, target, definitions)) return false;\n }\n const matches = (candidate: Schema) => matchesSchema(value, candidate, definitions);\n if (schema.allOf && !schema.allOf.every(matches)) return false;\n if (schema.anyOf && !schema.anyOf.some(matches)) return false;\n if (schema.oneOf && schema.oneOf.filter(matches).length !== 1) return false;\n if (schema.not !== undefined && matches(schema.not)) return false;\n if (schema.enum && !schema.enum.some((entry) => JSON.stringify(entry) === JSON.stringify(value)))\n return false;\n if (\"const\" in schema && JSON.stringify(schema.const) !== JSON.stringify(value)) return false;\n if (schema.type) {\n const types = Array.isArray(schema.type) ? schema.type : [schema.type];\n const type = value === null ? \"null\" : Array.isArray(value) ? \"array\" : typeof value;\n if (\n !types.includes(type) &&\n !(types.includes(\"integer\") && typeof value === \"number\" && Number.isInteger(value))\n )\n return false;\n }\n if (Array.isArray(value)) {\n if (schema.minItems !== undefined && value.length < schema.minItems) return false;\n if (schema.maxItems !== undefined && value.length > schema.maxItems) return false;\n if (\n schema.uniqueItems &&\n new Set(value.map((entry) => JSON.stringify(entry))).size !== value.length\n )\n return false;\n const items = schema.items;\n if (\n items !== undefined &&\n !value.every((entry, index) => {\n const item = Array.isArray(items)\n ? (items[index] ?? schema.additionalItems ?? true)\n : items;\n return matchesSchema(entry, item, definitions);\n })\n )\n return false;\n }\n if (isRecord(value)) {\n if (schema.required?.some((key) => !(key in value))) return false;\n for (const [key, entry] of Object.entries(value)) {\n const property = schema.properties?.[key];\n const patterns = Object.entries(schema.patternProperties ?? {}).filter(([pattern]) =>\n new RegExp(pattern).test(key),\n );\n if (property !== undefined && !matchesSchema(entry, property, definitions)) return false;\n if (!patterns.every(([, pattern]) => matchesSchema(entry, pattern, definitions)))\n return false;\n if (\n property === undefined &&\n patterns.length === 0 &&\n schema.additionalProperties !== undefined &&\n !matchesSchema(entry, schema.additionalProperties, definitions)\n )\n return false;\n }\n }\n if (typeof value === \"number\") {\n if (schema.minimum !== undefined && value < schema.minimum) return false;\n if (schema.maximum !== undefined && value > schema.maximum) return false;\n if (schema.exclusiveMinimum !== undefined && value <= schema.exclusiveMinimum) return false;\n if (schema.exclusiveMaximum !== undefined && value >= schema.exclusiveMaximum) return false;\n if (schema.multipleOf !== undefined && value % schema.multipleOf !== 0) return false;\n }\n if (typeof value === \"string\") {\n if (schema.minLength !== undefined && value.length < schema.minLength) return false;\n if (schema.maxLength !== undefined && value.length > schema.maxLength) return false;\n if (schema.pattern !== undefined && !new RegExp(schema.pattern).test(value)) return false;\n }\n return true;\n}\n"],"mappings":"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"}
|
package/esm/upgrade/notes.mjs
CHANGED
|
@@ -3,13 +3,20 @@
|
|
|
3
3
|
* Breaking changes with nothing to edit in source: they change data or
|
|
4
4
|
* operations. Printed so the rollout plans for them.
|
|
5
5
|
*/
|
|
6
|
-
const UPGRADE_NOTES = [
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
6
|
+
const UPGRADE_NOTES = [
|
|
7
|
+
{
|
|
8
|
+
version: "5.34.0",
|
|
9
|
+
text: "ESLint and Prettier support is gone in 5.34.0. Oxlint/Oxfmt is the only toolchain. The oxc-toolchain-removal step migrates remaining legacy configs/dependencies; review its manual findings. New/migrated templates enable correctness: error, which may report additional defects."
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
version: "5.30.0",
|
|
13
|
+
text: "Auth login throttle keys are hashed: counters and lockouts written by 5.29 are forgotten on upgrade (locked accounts and IPs unlock)."
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
version: "5.30.0",
|
|
17
|
+
text: "Image derivatives use a new cache layout: the first request re-renders each one. Delete the old two-level cache folders once the rollout is done."
|
|
18
|
+
}
|
|
19
|
+
];
|
|
13
20
|
|
|
14
21
|
//#endregion
|
|
15
22
|
export { UPGRADE_NOTES };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notes.mjs","names":[],"sources":["../../../../../../../../packages/core/src/upgrade/notes.ts"],"sourcesContent":["import type { UpgradeNote } from \"./types\";\n\n/**\n * Breaking changes with nothing to edit in source: they change data or\n * operations. Printed so the rollout plans for them.\n */\nexport const UPGRADE_NOTES: readonly UpgradeNote[] = [\n {\n version: \"5.30.0\",\n text: \"Auth login throttle keys are hashed: counters and lockouts written by 5.29 are forgotten on upgrade (locked accounts and IPs unlock).\",\n },\n {\n version: \"5.30.0\",\n text: \"Image derivatives use a new cache layout: the first request re-renders each one. Delete the old two-level cache folders once the rollout is done.\",\n },\n];\n"],"mappings":";;;;;AAMA,MAAa,gBAAwC
|
|
1
|
+
{"version":3,"file":"notes.mjs","names":[],"sources":["../../../../../../../../packages/core/src/upgrade/notes.ts"],"sourcesContent":["import type { UpgradeNote } from \"./types\";\n\n/**\n * Breaking changes with nothing to edit in source: they change data or\n * operations. Printed so the rollout plans for them.\n */\nexport const UPGRADE_NOTES: readonly UpgradeNote[] = [\n {\n version: \"5.34.0\",\n text: \"ESLint and Prettier support is gone in 5.34.0. Oxlint/Oxfmt is the only toolchain. The oxc-toolchain-removal step migrates remaining legacy configs/dependencies; review its manual findings. New/migrated templates enable correctness: error, which may report additional defects.\",\n },\n {\n version: \"5.30.0\",\n text: \"Auth login throttle keys are hashed: counters and lockouts written by 5.29 are forgotten on upgrade (locked accounts and IPs unlock).\",\n },\n {\n version: \"5.30.0\",\n text: \"Image derivatives use a new cache layout: the first request re-renders each one. Delete the old two-level cache folders once the rollout is done.\",\n },\n];\n"],"mappings":";;;;;AAMA,MAAa,gBAAwC;CACnD;EACE,SAAS;EACT,MAAM;CACR;CACA;EACE,SAAS;EACT,MAAM;CACR;CACA;EACE,SAAS;EACT,MAAM;CACR;AACF"}
|
|
@@ -5,7 +5,7 @@ import { CODEMODS } from "./codemods/index.mjs";
|
|
|
5
5
|
import { unifiedDiff } from "./diff.mjs";
|
|
6
6
|
import { UPGRADE_NOTES } from "./notes.mjs";
|
|
7
7
|
import path from "node:path";
|
|
8
|
-
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
8
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
|
|
9
9
|
import glob from "fast-glob";
|
|
10
10
|
|
|
11
11
|
//#region ../../packages/core/src/upgrade/run-upgrade.ts
|
|
@@ -64,6 +64,15 @@ async function runUpgrade(options) {
|
|
|
64
64
|
relativePath: (sourceFile) => relativeOf.get(sourceFile) ?? path.relative(root, sourceFile.getFilePath()).split(path.sep).join("/"),
|
|
65
65
|
text: {
|
|
66
66
|
read: (file) => textFiles.read(file),
|
|
67
|
+
list: () => readdirSync(root),
|
|
68
|
+
remove: (file, change) => {
|
|
69
|
+
textFiles.remove(file);
|
|
70
|
+
if (activeCodemod) applied.push({
|
|
71
|
+
codemod: activeCodemod.id,
|
|
72
|
+
file,
|
|
73
|
+
...change
|
|
74
|
+
});
|
|
75
|
+
},
|
|
67
76
|
write: (file, content, change) => {
|
|
68
77
|
textFiles.write(file, content);
|
|
69
78
|
if (activeCodemod) applied.push({
|
|
@@ -143,8 +152,15 @@ async function runUpgrade(options) {
|
|
|
143
152
|
});
|
|
144
153
|
for (const change of textFiles.changes()) changes.push(change);
|
|
145
154
|
changes.sort((left, right) => left.file.localeCompare(right.file));
|
|
146
|
-
if (!options.dryRun) for (const change of changes)
|
|
147
|
-
|
|
155
|
+
if (!options.dryRun) for (const change of changes) {
|
|
156
|
+
const target = path.join(root, change.file);
|
|
157
|
+
if (change.after === void 0) rmSync(target, { force: true });
|
|
158
|
+
else {
|
|
159
|
+
mkdirSync(path.dirname(target), { recursive: true });
|
|
160
|
+
writeFileSync(target, change.after);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
const packageJsonChanged = changes.some((change) => change.file === "package.json");
|
|
148
164
|
return {
|
|
149
165
|
from,
|
|
150
166
|
to,
|
|
@@ -154,7 +170,7 @@ async function runUpgrade(options) {
|
|
|
154
170
|
manual,
|
|
155
171
|
notes: UPGRADE_NOTES.filter((note) => compareVersions(note.version, from) > 0 && compareVersions(note.version, to) <= 0),
|
|
156
172
|
changedFiles: changes.map((change) => change.file),
|
|
157
|
-
diff: changes.map((change) => unifiedDiff(change.file, change.before, change.after)).join(""),
|
|
173
|
+
diff: changes.map((change) => unifiedDiff(change.file, change.before, change.after ?? "")).join(""),
|
|
158
174
|
...packageJsonChanged && { installHint: getInstallCommand(await detectPackageManager(root)) }
|
|
159
175
|
};
|
|
160
176
|
}
|
|
@@ -233,10 +249,13 @@ function createTextFiles(root) {
|
|
|
233
249
|
write: (file, content) => {
|
|
234
250
|
entry(file).current = content;
|
|
235
251
|
},
|
|
236
|
-
|
|
252
|
+
remove: (file) => {
|
|
253
|
+
entry(file).current = void 0;
|
|
254
|
+
},
|
|
255
|
+
changes: () => [...files.entries()].filter(([, value]) => value.current !== value.before).map(([file, value]) => ({
|
|
237
256
|
file,
|
|
238
257
|
before: value.before ?? "",
|
|
239
|
-
after: value.current
|
|
258
|
+
after: value.current
|
|
240
259
|
}))
|
|
241
260
|
};
|
|
242
261
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-upgrade.mjs","names":[],"sources":["../../../../../../../../packages/core/src/upgrade/run-upgrade.ts"],"sourcesContent":["import glob from \"fast-glob\";\nimport { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { detectPackageManager, getInstallCommand } from \"../updater/package-manager\";\nimport { CODEMODS } from \"./codemods\";\nimport { unifiedDiff } from \"./diff\";\nimport { loadTsMorph } from \"./load-ts-morph\";\nimport { UPGRADE_NOTES } from \"./notes\";\nimport type {\n AppliedChange,\n Codemod,\n CodemodContext,\n ManualItem,\n SourceEdit,\n SourceFile,\n TextFiles,\n TsMorphModule,\n UpgradeResult,\n} from \"./types\";\nimport { compareVersions, normalizeVersion, parseVersion } from \"./version\";\n\nexport type RunUpgradeOptions = {\n /** App root. Defaults to the current directory. */\n root?: string;\n /** Target version, e.g. `5.31` or `5.31.0`. */\n to: string;\n /** Version upgrading from; detected from the installed `@warlock.js/core` when omitted. */\n from?: string;\n /** Compute and report everything, write nothing. */\n dryRun?: boolean;\n /** Override the codemod list (tests). */\n codemods?: readonly Codemod[];\n /** Override how ts-morph is loaded (tests). */\n loadTsMorph?: (root: string) => Promise<TsMorphModule>;\n};\n\n/** Thrown for a request the command cannot act on (bad versions, nothing to detect). */\nexport class UpgradeUsageError extends Error {\n public override readonly name = \"UpgradeUsageError\";\n}\n\n/**\n * Apply the mechanical edits for every breaking change between two releases\n * and list what needs a decision. Writes nothing with `dryRun`.\n */\nexport async function runUpgrade(options: RunUpgradeOptions): Promise<UpgradeResult> {\n const root = path.resolve(options.root ?? process.cwd());\n const to = toVersion(options.to);\n const from = options.from ? toVersion(options.from) : detectInstalledVersion(root);\n\n if (compareVersions(from, to) >= 0) {\n throw new UpgradeUsageError(notNewerMessage(from, to, options.from !== undefined));\n }\n\n const selected = (options.codemods ?? CODEMODS).filter(\n (codemod) =>\n codemod.version === \"target\" ||\n (compareVersions(codemod.version, from) > 0 && compareVersions(codemod.version, to) <= 0),\n );\n\n const tsMorph = await (options.loadTsMorph ?? loadTsMorph)(root);\n const project = new tsMorph.Project({\n skipAddingFilesFromTsConfig: true,\n skipFileDependencyResolution: true,\n compilerOptions: { jsx: tsMorph.ts.JsxEmit.Preserve, allowJs: false },\n });\n\n const relativePaths = await glob(\"src/**/*.{ts,tsx}\", {\n cwd: root,\n ignore: [\"**/node_modules/**\", \"**/dist/**\", \"**/.warlock/**\", \"**/*.d.ts\"],\n dot: false,\n });\n relativePaths.sort();\n\n const originals = new Map<string, string>();\n const sourceFiles: SourceFile[] = [];\n for (const relative of relativePaths) {\n const content = readFileSync(path.join(root, relative), \"utf8\");\n originals.set(relative, content);\n sourceFiles.push(\n project.createSourceFile(path.join(root, relative), content, { overwrite: true }),\n );\n }\n\n const relativeOf = new Map<SourceFile, string>(\n sourceFiles.map((sourceFile, index) => [sourceFile, relativePaths[index] ?? \"\"]),\n );\n\n const applied: AppliedChange[] = [];\n const manual: ManualItem[] = [];\n const textFiles = createTextFiles(root);\n let activeCodemod: Codemod | undefined;\n\n const text: TextFiles = {\n read: (file) => textFiles.read(file),\n write: (file, content, change) => {\n textFiles.write(file, content);\n if (activeCodemod) {\n applied.push({ codemod: activeCodemod.id, file, ...change });\n }\n },\n };\n\n const context: CodemodContext = {\n tsMorph,\n sourceFiles,\n relativePath: (sourceFile) =>\n relativeOf.get(sourceFile) ??\n path.relative(root, sourceFile.getFilePath()).split(path.sep).join(\"/\"),\n text,\n targetVersion: to,\n };\n\n const summary: UpgradeResult[\"codemods\"] = [];\n\n for (const codemod of selected) {\n activeCodemod = codemod;\n const appliedBefore = applied.length;\n const output = codemod.run(context);\n\n for (const finding of output.manual) {\n manual.push({ ...finding, codemod: codemod.id, skill: codemod.skill });\n }\n\n const byFile = new Map<string, SourceEdit[]>();\n for (const edit of output.edits) {\n const list = byFile.get(edit.file) ?? [];\n list.push(edit);\n byFile.set(edit.file, list);\n }\n\n for (const [file, edits] of byFile) {\n const sourceFile = sourceFiles[relativePaths.indexOf(file)];\n if (!sourceFile) continue;\n\n let content = sourceFile.getFullText();\n let lowestStart = Number.POSITIVE_INFINITY;\n for (const edit of [...edits].sort((left, right) => right.start - left.start)) {\n // Overlapping edits (one inside another) would corrupt the file: keep the outer one.\n if (edit.end > lowestStart) {\n manual.push({\n codemod: codemod.id,\n skill: codemod.skill,\n file,\n line: edit.line,\n hint: `Not edited automatically (overlaps another change): ${edit.description}. Run the upgrade again after reviewing.`,\n });\n continue;\n }\n content = content.slice(0, edit.start) + edit.text + content.slice(edit.end);\n lowestStart = edit.start;\n applied.push({ codemod: codemod.id, file, line: edit.line, description: edit.description });\n }\n\n sourceFile.replaceWithText(content);\n }\n\n summary.push({\n id: codemod.id,\n version: codemod.version === \"target\" ? to : codemod.version,\n title: codemod.title,\n applied: applied.length - appliedBefore,\n manual: manual.filter((item) => item.codemod === codemod.id).length,\n });\n }\n activeCodemod = undefined;\n\n applied.sort(byFileAndLine);\n manual.sort(byFileAndLine);\n\n const changes: { file: string; before: string; after: string }[] = [];\n sourceFiles.forEach((sourceFile, index) => {\n const file = relativePaths[index];\n if (file === undefined) return;\n const before = originals.get(file) ?? \"\";\n const after = sourceFile.getFullText();\n if (before !== after) changes.push({ file, before, after });\n });\n for (const change of textFiles.changes()) changes.push(change);\n changes.sort((left, right) => left.file.localeCompare(right.file));\n\n if (!options.dryRun) {\n for (const change of changes) writeFileSync(path.join(root, change.file), change.after);\n }\n\n const packageJsonChanged = changes.some(\n (change) =>\n change.file === \"package.json\" &&\n applied.some((item) => item.codemod === \"warlock-versions\" && item.file === \"package.json\"),\n );\n\n return {\n from,\n to,\n dryRun: options.dryRun === true,\n codemods: summary,\n applied,\n manual,\n notes: UPGRADE_NOTES.filter(\n (note) => compareVersions(note.version, from) > 0 && compareVersions(note.version, to) <= 0,\n ),\n changedFiles: changes.map((change) => change.file),\n diff: changes.map((change) => unifiedDiff(change.file, change.before, change.after)).join(\"\"),\n ...(packageJsonChanged && {\n installHint: getInstallCommand(await detectPackageManager(root)),\n }),\n };\n}\n\n/**\n * Explain why `--to` is not newer than the starting version. The usual cause\n * is running the command after installing the new release: the starting\n * version is read from the installed `@warlock.js/core`, which is then already\n * the target, so the command needs `--from`.\n */\nfunction notNewerMessage(from: string, to: string, fromWasPassed: boolean): string {\n if (fromWasPassed) {\n return `--from ${from} is not older than --to ${to}. Pass the version this app is upgrading from.`;\n }\n\n const example = `warlock upgrade --from ${previousMinor(to)} --to ${to}`;\n\n if (compareVersions(from, to) === 0) {\n return `The installed @warlock.js/core is already ${from}, the --to version, so the version this app is upgrading from cannot be detected. Pass it with --from <previous version>, e.g. ${example}.`;\n }\n\n return `This app is already on ${from}; --to ${to} is not newer. If the detected version is wrong, pass --from <previous version>, e.g. ${example}.`;\n}\n\n/** `5.31.0` → `5.30`. A major's first release has no minor to step back to, so it gets a placeholder. */\nfunction previousMinor(version: string): string {\n const [major, minor] = parseVersion(version) ?? [0, 0, 0];\n\n return minor > 0 ? `${major}.${minor - 1}` : \"<previous version>\";\n}\n\nfunction toVersion(value: string): string {\n try {\n return normalizeVersion(value);\n } catch (error) {\n throw new UpgradeUsageError(error instanceof Error ? error.message : String(error));\n }\n}\n\n/** The installed `@warlock.js/core`, or the version its package.json range names. */\nexport function detectInstalledVersion(root: string): string {\n const installed = path.join(root, \"node_modules\", \"@warlock.js\", \"core\", \"package.json\");\n if (existsSync(installed)) {\n const version = (JSON.parse(readFileSync(installed, \"utf8\")) as { version?: unknown }).version;\n if (typeof version === \"string\" && parseVersion(version))\n return normalizeVersion(stripRange(version));\n }\n\n const manifest = path.join(root, \"package.json\");\n if (existsSync(manifest)) {\n const pkg = JSON.parse(readFileSync(manifest, \"utf8\")) as {\n dependencies?: Record<string, unknown>;\n devDependencies?: Record<string, unknown>;\n };\n const spec =\n pkg.dependencies?.[\"@warlock.js/core\"] ?? pkg.devDependencies?.[\"@warlock.js/core\"];\n const parsed = typeof spec === \"string\" ? parseVersion(spec) : undefined;\n if (parsed) return parsed.join(\".\");\n }\n\n throw new UpgradeUsageError(\n \"Could not tell which Warlock version this app is on (no installed @warlock.js/core). Pass it with --from, e.g. --from 5.29.\",\n );\n}\n\nfunction stripRange(version: string): string {\n return (parseVersion(version) ?? [0, 0, 0]).join(\".\");\n}\n\nfunction byFileAndLine(\n left: { file: string; line: number },\n right: { file: string; line: number },\n) {\n return left.file.localeCompare(right.file) || left.line - right.line;\n}\n\n/** Non-TypeScript files a codemod reads and rewrites, buffered until the end. */\nfunction createTextFiles(root: string) {\n const files = new Map<string, { before: string | undefined; current: string | undefined }>();\n\n const entry = (file: string) => {\n let existing = files.get(file);\n if (!existing) {\n const absolute = path.join(root, file);\n const content = existsSync(absolute) ? readFileSync(absolute, \"utf8\") : undefined;\n existing = { before: content, current: content };\n files.set(file, existing);\n }\n return existing;\n };\n\n return {\n read: (file: string) => entry(file).current,\n write: (file: string, content: string) => {\n entry(file).current = content;\n },\n changes: () =>\n [...files.entries()]\n .filter(([, value]) => value.current !== undefined && value.current !== value.before)\n .map(([file, value]) => ({ file, before: value.before ?? \"\", after: value.current ?? \"\" })),\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"run-upgrade.mjs","names":[],"sources":["../../../../../../../../packages/core/src/upgrade/run-upgrade.ts"],"sourcesContent":["import glob from \"fast-glob\";\nimport { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { detectPackageManager, getInstallCommand } from \"../updater/package-manager\";\nimport { CODEMODS } from \"./codemods\";\nimport { unifiedDiff } from \"./diff\";\nimport { loadTsMorph } from \"./load-ts-morph\";\nimport { UPGRADE_NOTES } from \"./notes\";\nimport type {\n AppliedChange,\n Codemod,\n CodemodContext,\n ManualItem,\n SourceEdit,\n SourceFile,\n TextFiles,\n TsMorphModule,\n UpgradeResult,\n} from \"./types\";\nimport { compareVersions, normalizeVersion, parseVersion } from \"./version\";\n\nexport type RunUpgradeOptions = {\n /** App root. Defaults to the current directory. */\n root?: string;\n /** Target version, e.g. `5.31` or `5.31.0`. */\n to: string;\n /** Version upgrading from; detected from the installed `@warlock.js/core` when omitted. */\n from?: string;\n /** Compute and report everything, write nothing. */\n dryRun?: boolean;\n /** Override the codemod list (tests). */\n codemods?: readonly Codemod[];\n /** Override how ts-morph is loaded (tests). */\n loadTsMorph?: (root: string) => Promise<TsMorphModule>;\n};\n\n/** Thrown for a request the command cannot act on (bad versions, nothing to detect). */\nexport class UpgradeUsageError extends Error {\n public override readonly name = \"UpgradeUsageError\";\n}\n\n/**\n * Apply the mechanical edits for every breaking change between two releases\n * and list what needs a decision. Writes nothing with `dryRun`.\n */\nexport async function runUpgrade(options: RunUpgradeOptions): Promise<UpgradeResult> {\n const root = path.resolve(options.root ?? process.cwd());\n const to = toVersion(options.to);\n const from = options.from ? toVersion(options.from) : detectInstalledVersion(root);\n\n if (compareVersions(from, to) >= 0) {\n throw new UpgradeUsageError(notNewerMessage(from, to, options.from !== undefined));\n }\n\n const selected = (options.codemods ?? CODEMODS).filter(\n (codemod) =>\n codemod.version === \"target\" ||\n (compareVersions(codemod.version, from) > 0 && compareVersions(codemod.version, to) <= 0),\n );\n\n const tsMorph = await (options.loadTsMorph ?? loadTsMorph)(root);\n const project = new tsMorph.Project({\n skipAddingFilesFromTsConfig: true,\n skipFileDependencyResolution: true,\n compilerOptions: { jsx: tsMorph.ts.JsxEmit.Preserve, allowJs: false },\n });\n\n const relativePaths = await glob(\"src/**/*.{ts,tsx}\", {\n cwd: root,\n ignore: [\"**/node_modules/**\", \"**/dist/**\", \"**/.warlock/**\", \"**/*.d.ts\"],\n dot: false,\n });\n relativePaths.sort();\n\n const originals = new Map<string, string>();\n const sourceFiles: SourceFile[] = [];\n for (const relative of relativePaths) {\n const content = readFileSync(path.join(root, relative), \"utf8\");\n originals.set(relative, content);\n sourceFiles.push(\n project.createSourceFile(path.join(root, relative), content, { overwrite: true }),\n );\n }\n\n const relativeOf = new Map<SourceFile, string>(\n sourceFiles.map((sourceFile, index) => [sourceFile, relativePaths[index] ?? \"\"]),\n );\n\n const applied: AppliedChange[] = [];\n const manual: ManualItem[] = [];\n const textFiles = createTextFiles(root);\n let activeCodemod: Codemod | undefined;\n\n const text: TextFiles = {\n read: (file) => textFiles.read(file),\n list: () => readdirSync(root),\n remove: (file, change) => {\n textFiles.remove(file);\n if (activeCodemod) applied.push({ codemod: activeCodemod.id, file, ...change });\n },\n write: (file, content, change) => {\n textFiles.write(file, content);\n if (activeCodemod) {\n applied.push({ codemod: activeCodemod.id, file, ...change });\n }\n },\n };\n\n const context: CodemodContext = {\n tsMorph,\n sourceFiles,\n relativePath: (sourceFile) =>\n relativeOf.get(sourceFile) ??\n path.relative(root, sourceFile.getFilePath()).split(path.sep).join(\"/\"),\n text,\n targetVersion: to,\n };\n\n const summary: UpgradeResult[\"codemods\"] = [];\n\n for (const codemod of selected) {\n activeCodemod = codemod;\n const appliedBefore = applied.length;\n const output = codemod.run(context);\n\n for (const finding of output.manual) {\n manual.push({ ...finding, codemod: codemod.id, skill: codemod.skill });\n }\n\n const byFile = new Map<string, SourceEdit[]>();\n for (const edit of output.edits) {\n const list = byFile.get(edit.file) ?? [];\n list.push(edit);\n byFile.set(edit.file, list);\n }\n\n for (const [file, edits] of byFile) {\n const sourceFile = sourceFiles[relativePaths.indexOf(file)];\n if (!sourceFile) continue;\n\n let content = sourceFile.getFullText();\n let lowestStart = Number.POSITIVE_INFINITY;\n for (const edit of [...edits].sort((left, right) => right.start - left.start)) {\n // Overlapping edits (one inside another) would corrupt the file: keep the outer one.\n if (edit.end > lowestStart) {\n manual.push({\n codemod: codemod.id,\n skill: codemod.skill,\n file,\n line: edit.line,\n hint: `Not edited automatically (overlaps another change): ${edit.description}. Run the upgrade again after reviewing.`,\n });\n continue;\n }\n content = content.slice(0, edit.start) + edit.text + content.slice(edit.end);\n lowestStart = edit.start;\n applied.push({ codemod: codemod.id, file, line: edit.line, description: edit.description });\n }\n\n sourceFile.replaceWithText(content);\n }\n\n summary.push({\n id: codemod.id,\n version: codemod.version === \"target\" ? to : codemod.version,\n title: codemod.title,\n applied: applied.length - appliedBefore,\n manual: manual.filter((item) => item.codemod === codemod.id).length,\n });\n }\n activeCodemod = undefined;\n\n applied.sort(byFileAndLine);\n manual.sort(byFileAndLine);\n\n const changes: { file: string; before: string; after: string | undefined }[] = [];\n sourceFiles.forEach((sourceFile, index) => {\n const file = relativePaths[index];\n if (file === undefined) return;\n const before = originals.get(file) ?? \"\";\n const after = sourceFile.getFullText();\n if (before !== after) changes.push({ file, before, after });\n });\n for (const change of textFiles.changes()) changes.push(change);\n changes.sort((left, right) => left.file.localeCompare(right.file));\n\n if (!options.dryRun) {\n for (const change of changes) {\n const target = path.join(root, change.file);\n if (change.after === undefined) rmSync(target, { force: true });\n else {\n mkdirSync(path.dirname(target), { recursive: true });\n writeFileSync(target, change.after);\n }\n }\n }\n\n const packageJsonChanged = changes.some((change) => change.file === \"package.json\");\n\n return {\n from,\n to,\n dryRun: options.dryRun === true,\n codemods: summary,\n applied,\n manual,\n notes: UPGRADE_NOTES.filter(\n (note) => compareVersions(note.version, from) > 0 && compareVersions(note.version, to) <= 0,\n ),\n changedFiles: changes.map((change) => change.file),\n diff: changes\n .map((change) => unifiedDiff(change.file, change.before, change.after ?? \"\"))\n .join(\"\"),\n ...(packageJsonChanged && {\n installHint: getInstallCommand(await detectPackageManager(root)),\n }),\n };\n}\n\n/**\n * Explain why `--to` is not newer than the starting version. The usual cause\n * is running the command after installing the new release: the starting\n * version is read from the installed `@warlock.js/core`, which is then already\n * the target, so the command needs `--from`.\n */\nfunction notNewerMessage(from: string, to: string, fromWasPassed: boolean): string {\n if (fromWasPassed) {\n return `--from ${from} is not older than --to ${to}. Pass the version this app is upgrading from.`;\n }\n\n const example = `warlock upgrade --from ${previousMinor(to)} --to ${to}`;\n\n if (compareVersions(from, to) === 0) {\n return `The installed @warlock.js/core is already ${from}, the --to version, so the version this app is upgrading from cannot be detected. Pass it with --from <previous version>, e.g. ${example}.`;\n }\n\n return `This app is already on ${from}; --to ${to} is not newer. If the detected version is wrong, pass --from <previous version>, e.g. ${example}.`;\n}\n\n/** `5.31.0` → `5.30`. A major's first release has no minor to step back to, so it gets a placeholder. */\nfunction previousMinor(version: string): string {\n const [major, minor] = parseVersion(version) ?? [0, 0, 0];\n\n return minor > 0 ? `${major}.${minor - 1}` : \"<previous version>\";\n}\n\nfunction toVersion(value: string): string {\n try {\n return normalizeVersion(value);\n } catch (error) {\n throw new UpgradeUsageError(error instanceof Error ? error.message : String(error));\n }\n}\n\n/** The installed `@warlock.js/core`, or the version its package.json range names. */\nexport function detectInstalledVersion(root: string): string {\n const installed = path.join(root, \"node_modules\", \"@warlock.js\", \"core\", \"package.json\");\n if (existsSync(installed)) {\n const version = (JSON.parse(readFileSync(installed, \"utf8\")) as { version?: unknown }).version;\n if (typeof version === \"string\" && parseVersion(version))\n return normalizeVersion(stripRange(version));\n }\n\n const manifest = path.join(root, \"package.json\");\n if (existsSync(manifest)) {\n const pkg = JSON.parse(readFileSync(manifest, \"utf8\")) as {\n dependencies?: Record<string, unknown>;\n devDependencies?: Record<string, unknown>;\n };\n const spec =\n pkg.dependencies?.[\"@warlock.js/core\"] ?? pkg.devDependencies?.[\"@warlock.js/core\"];\n const parsed = typeof spec === \"string\" ? parseVersion(spec) : undefined;\n if (parsed) return parsed.join(\".\");\n }\n\n throw new UpgradeUsageError(\n \"Could not tell which Warlock version this app is on (no installed @warlock.js/core). Pass it with --from, e.g. --from 5.29.\",\n );\n}\n\nfunction stripRange(version: string): string {\n return (parseVersion(version) ?? [0, 0, 0]).join(\".\");\n}\n\nfunction byFileAndLine(\n left: { file: string; line: number },\n right: { file: string; line: number },\n) {\n return left.file.localeCompare(right.file) || left.line - right.line;\n}\n\n/** Non-TypeScript files a codemod reads and rewrites, buffered until the end. */\nfunction createTextFiles(root: string) {\n const files = new Map<string, { before: string | undefined; current: string | undefined }>();\n\n const entry = (file: string) => {\n let existing = files.get(file);\n if (!existing) {\n const absolute = path.join(root, file);\n const content = existsSync(absolute) ? readFileSync(absolute, \"utf8\") : undefined;\n existing = { before: content, current: content };\n files.set(file, existing);\n }\n return existing;\n };\n\n return {\n read: (file: string) => entry(file).current,\n write: (file: string, content: string) => {\n entry(file).current = content;\n },\n remove: (file: string) => {\n entry(file).current = undefined;\n },\n changes: () =>\n [...files.entries()]\n .filter(([, value]) => value.current !== value.before)\n .map(([file, value]) => ({ file, before: value.before ?? \"\", after: value.current })),\n };\n}\n"],"mappings":"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"}
|
|
@@ -169,7 +169,7 @@ export type WarlockConfig = {
|
|
|
169
169
|
};
|
|
170
170
|
/**
|
|
171
171
|
* Built-in checker switches, custom checker array, or false to disable.
|
|
172
|
-
*
|
|
172
|
+
* TypeScript and installed/configured Oxlint run by default.
|
|
173
173
|
*/
|
|
174
174
|
healthCheckers?: FileHealthCheckerContract[] | BuiltInHealthCheckerOptions | false;
|
|
175
175
|
/**
|