diff --git a/.github/workflows/tests-main.yml b/.github/workflows/tests-main.yml index c631c9d8bfc..6677ce00044 100644 --- a/.github/workflows/tests-main.yml +++ b/.github/workflows/tests-main.yml @@ -51,8 +51,8 @@ jobs: - name: Oxlint run: pnpm lint:oxlint if: ${{ matrix.os == 'ubuntu-latest' && matrix.node == '26.1.0' }} - - name: Lint - run: pnpm nx run-many --all --target=lint --output-style=stream + - name: ESLint compatibility + run: pnpm lint:eslint --output-style=stream if: ${{ matrix.os == 'ubuntu-latest' && matrix.node == '26.1.0' }} - name: Type-check run: pnpm nx run-many --all --target=type-check --output-style=stream diff --git a/.github/workflows/tests-pr.yml b/.github/workflows/tests-pr.yml index 2b3aaf8a2cf..19523a560e5 100644 --- a/.github/workflows/tests-pr.yml +++ b/.github/workflows/tests-pr.yml @@ -55,8 +55,8 @@ jobs: run: pnpm prettier - name: Oxlint run: pnpm lint:oxlint - - name: Lint - run: pnpm nx run-many --all --target=lint --output-style=stream + - name: ESLint compatibility + run: pnpm lint:eslint --output-style=stream bundle: name: 'Bundle' diff --git a/docs/cli/get-started.md b/docs/cli/get-started.md index d64b8919374..505a90e82bc 100644 --- a/docs/cli/get-started.md +++ b/docs/cli/get-started.md @@ -73,8 +73,8 @@ Besides the scripts for building and running the CLIs, there are others that mig - `pnpm test`: Runs the tests of all the packages. - `pnpm prettier`: Checks formatting for all linted source files. - `pnpm prettier:fix`: Formats all linted source files. -- `pnpm lint`: Runs Prettier, Oxlint, and ESLint checks for all the packages. -- `pnpm lint:fix`: Runs Prettier and ESLint for all the packages and fixes the fixable issues. +- `pnpm lint`: Runs Prettier, Oxlint, and ESLint compatibility checks for all the packages. +- `pnpm lint:fix`: Runs Prettier, Oxlint, and ESLint compatibility checks and fixes supported issues. - `pnpm type-check`: Type-checks all the packagesusing the Typescript `tsc` tool. - `pnpm clean`: Removes the `dist` directory from all the packages. diff --git a/eslint.codegen.config.js b/eslint.codegen.config.js new file mode 100644 index 00000000000..e778ead89c3 --- /dev/null +++ b/eslint.codegen.config.js @@ -0,0 +1,3 @@ +import {eslintBaseConfig} from './eslint.config.js' + +export default eslintBaseConfig diff --git a/eslint.config.js b/eslint.config.js index ca4372edc03..50cb466f3c6 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -1,9 +1,39 @@ import nxPlugin from '@nx/eslint-plugin' import cliPlugin from '@shopify/eslint-plugin-cli' import jsdocPlugin from 'eslint-plugin-jsdoc' +import {readFileSync} from 'node:fs' + +const oxlintConfig = JSON.parse(readFileSync(new URL('./oxlint.json', import.meta.url), 'utf8')) + +const eslintPluginNames = { + import: 'import-x', + node: 'n', + typescript: '@typescript-eslint', +} + +const eslintRuleName = (oxlintRuleName) => { + const [pluginName, ...ruleNameParts] = oxlintRuleName.split('/') + const eslintPluginName = eslintPluginNames[pluginName] + return eslintPluginName ? `${eslintPluginName}/${ruleNameParts.join('/')}` : oxlintRuleName +} + +const isEnabled = (ruleConfiguration) => { + const severity = Array.isArray(ruleConfiguration) ? ruleConfiguration[0] : ruleConfiguration + return severity !== 'off' && severity !== 0 +} + +const eslintCompatibilityConfig = ({files, rules, excludeFiles = []}) => ({ + files: files ?? ['packages/*/src/**/*.{js,mjs,ts,tsx}', 'packages/cli/bin/*.js', 'packages/e2e/**/*.ts'], + ignores: [...oxlintConfig.ignorePatterns, 'packages/eslint-plugin-cli/**', ...excludeFiles], + rules: Object.fromEntries( + Object.entries(rules) + .filter(([, ruleConfiguration]) => isEnabled(ruleConfiguration)) + .map(([ruleName]) => [eslintRuleName(ruleName), 'off']), + ), +}) // Spread the CLI plugin's base config which includes all necessary plugins -const config = [ +export const eslintBaseConfig = [ // Base config from @shopify/eslint-plugin-cli (includes shopify, typescript, prettier, etc.) ...cliPlugin.configs.config, @@ -243,4 +273,16 @@ const config = [ }, ] +const config = [ + ...eslintBaseConfig, + // A directive can target an Oxlint-owned rule, so ESLint alone cannot determine whether it is unused. + { + linterOptions: { + reportUnusedDisableDirectives: 'off', + }, + }, + eslintCompatibilityConfig(oxlintConfig), + ...oxlintConfig.overrides.map((override) => eslintCompatibilityConfig(override)), +] + export default config diff --git a/nx.json b/nx.json index 782e76079c2..9d7caaafeab 100644 --- a/nx.json +++ b/nx.json @@ -80,6 +80,8 @@ "{workspaceRoot}/configurations/tsconfig.json", "{workspaceRoot}/configurations/vite.config.ts", "{workspaceRoot}/eslint.config.js", + "{workspaceRoot}/eslint.codegen.config.js", + "{workspaceRoot}/oxlint.json", "{workspaceRoot}/graphql.config.ts", "{workspaceRoot}/package.json", "{workspaceRoot}/packages/eslint-plugin-cli/**/*", diff --git a/package.json b/package.json index d65766764fb..aaf6aa72792 100644 --- a/package.json +++ b/package.json @@ -17,10 +17,12 @@ "graphql-codegen:get-graphql-schemas": "bin/get-graphql-schemas.js", "graphql-codegen": "nx run-many --target=graphql-codegen --all", "knip": "knip", - "lint:affected": "pnpm prettier && pnpm lint:oxlint && nx affected --target=lint", - "lint:fix:affected": "nx affected --target=lint:fix && pnpm prettier:fix", - "lint:fix": "nx run-many --target=lint:fix --all --skip-nx-cache && pnpm prettier:fix", - "lint": "pnpm prettier && pnpm lint:oxlint && nx run-many --target=lint --all", + "lint:affected": "pnpm prettier && pnpm lint:oxlint && pnpm lint:eslint:affected", + "lint:eslint:affected": "nx affected --target=lint", + "lint:fix:affected": "pnpm lint:oxlint --fix && nx affected --target=lint:fix && pnpm prettier:fix", + "lint:fix": "pnpm lint:oxlint --fix && nx run-many --target=lint:fix --all --skip-nx-cache && pnpm prettier:fix", + "lint": "pnpm prettier && pnpm lint:oxlint && pnpm lint:eslint", + "lint:eslint": "nx run-many --target=lint --all", "lint:oxlint": "oxlint --config oxlint.json --deny-warnings packages/app/src packages/cli-kit/src packages/cli/src packages/create-app/src packages/organizations/src packages/plugin-cloudflare/src packages/plugin-did-you-mean/src packages/store/src packages/theme/src packages/ui-extensions-server-kit/src packages/ui-extensions-test-utils/src packages/cli/bin packages/e2e", "prettier": "prettier --check \"packages/{app,cli-kit,cli,create-app,organizations,plugin-cloudflare,plugin-did-you-mean,store,theme,ui-extensions-server-kit,ui-extensions-test-utils}/src/**/*.{js,ts,tsx}\" \"packages/cli/bin/*.js\" \"packages/e2e/{setup,helpers,tests}/**/*.ts\" \"packages/e2e/*.ts\"", "prettier:fix": "prettier --write \"packages/{app,cli-kit,cli,create-app,organizations,plugin-cloudflare,plugin-did-you-mean,store,theme,ui-extensions-server-kit,ui-extensions-test-utils}/src/**/*.{js,ts,tsx}\" \"packages/cli/bin/*.js\" \"packages/e2e/{setup,helpers,tests}/**/*.ts\" \"packages/e2e/*.ts\"", @@ -191,7 +193,8 @@ ".": { "entry": [ "bin/**/*.js", - "configurations/vite.config.ts" + "configurations/vite.config.ts", + "eslint.codegen.config.js" ], "ignoreBinaries": [ "bin/*", diff --git a/packages/app/project.json b/packages/app/project.json index 357117cda8e..2e85a847346 100644 --- a/packages/app/project.json +++ b/packages/app/project.json @@ -74,13 +74,13 @@ ], "options": { "commands": [ - "pnpm eslint 'src/cli/api/graphql/business-platform-destinations/generated/**/*.{ts,tsx}' --fix && pnpm exec prettier --write --ignore-path ../../.prettierignore 'src/cli/api/graphql/business-platform-destinations/generated/**/*.{ts,tsx}'", - "pnpm eslint 'src/cli/api/graphql/business-platform-organizations/generated/**/*.{ts,tsx}' --fix && pnpm exec prettier --write --ignore-path ../../.prettierignore 'src/cli/api/graphql/business-platform-organizations/generated/**/*.{ts,tsx}'", - "pnpm eslint 'src/cli/api/graphql/app-dev/generated/**/*.{ts,tsx}' --fix && pnpm exec prettier --write --ignore-path ../../.prettierignore 'src/cli/api/graphql/app-dev/generated/**/*.{ts,tsx}'", - "pnpm eslint 'src/cli/api/graphql/app-management/generated/**/*.{ts,tsx}' --fix && pnpm exec prettier --write --ignore-path ../../.prettierignore 'src/cli/api/graphql/app-management/generated/**/*.{ts,tsx}'", - "pnpm eslint 'src/cli/api/graphql/webhooks/generated/**/*.{ts,tsx}' --fix && pnpm exec prettier --write --ignore-path ../../.prettierignore 'src/cli/api/graphql/webhooks/generated/**/*.{ts,tsx}'", - "pnpm eslint 'src/cli/api/graphql/functions/generated/**/*.{ts,tsx}' --fix && pnpm exec prettier --write --ignore-path ../../.prettierignore 'src/cli/api/graphql/functions/generated/**/*.{ts,tsx}'", - "pnpm eslint 'src/cli/api/graphql/admin/generated/**/*.{ts,tsx}' --fix && pnpm exec prettier --write --ignore-path ../../.prettierignore 'src/cli/api/graphql/admin/generated/**/*.{ts,tsx}'" + "pnpm eslint --config ../../eslint.codegen.config.js 'src/cli/api/graphql/business-platform-destinations/generated/**/*.{ts,tsx}' --fix && pnpm exec prettier --write --ignore-path ../../.prettierignore 'src/cli/api/graphql/business-platform-destinations/generated/**/*.{ts,tsx}'", + "pnpm eslint --config ../../eslint.codegen.config.js 'src/cli/api/graphql/business-platform-organizations/generated/**/*.{ts,tsx}' --fix && pnpm exec prettier --write --ignore-path ../../.prettierignore 'src/cli/api/graphql/business-platform-organizations/generated/**/*.{ts,tsx}'", + "pnpm eslint --config ../../eslint.codegen.config.js 'src/cli/api/graphql/app-dev/generated/**/*.{ts,tsx}' --fix && pnpm exec prettier --write --ignore-path ../../.prettierignore 'src/cli/api/graphql/app-dev/generated/**/*.{ts,tsx}'", + "pnpm eslint --config ../../eslint.codegen.config.js 'src/cli/api/graphql/app-management/generated/**/*.{ts,tsx}' --fix && pnpm exec prettier --write --ignore-path ../../.prettierignore 'src/cli/api/graphql/app-management/generated/**/*.{ts,tsx}'", + "pnpm eslint --config ../../eslint.codegen.config.js 'src/cli/api/graphql/webhooks/generated/**/*.{ts,tsx}' --fix && pnpm exec prettier --write --ignore-path ../../.prettierignore 'src/cli/api/graphql/webhooks/generated/**/*.{ts,tsx}'", + "pnpm eslint --config ../../eslint.codegen.config.js 'src/cli/api/graphql/functions/generated/**/*.{ts,tsx}' --fix && pnpm exec prettier --write --ignore-path ../../.prettierignore 'src/cli/api/graphql/functions/generated/**/*.{ts,tsx}'", + "pnpm eslint --config ../../eslint.codegen.config.js 'src/cli/api/graphql/admin/generated/**/*.{ts,tsx}' --fix && pnpm exec prettier --write --ignore-path ../../.prettierignore 'src/cli/api/graphql/admin/generated/**/*.{ts,tsx}'" ], "cwd": "packages/app" } diff --git a/packages/cli-kit/project.json b/packages/cli-kit/project.json index 33381599c2f..e079d7c7e7e 100644 --- a/packages/cli-kit/project.json +++ b/packages/cli-kit/project.json @@ -109,8 +109,8 @@ ], "options": { "commands": [ - "pnpm eslint 'src/cli/api/graphql/admin/generated/**/*.{ts,tsx}' --fix && pnpm exec prettier --write --ignore-path ../../.prettierignore 'src/cli/api/graphql/admin/generated/**/*.{ts,tsx}'", - "pnpm eslint 'src/cli/api/graphql/bulk-operations/generated/**/*.{ts,tsx}' --fix && pnpm exec prettier --write --ignore-path ../../.prettierignore 'src/cli/api/graphql/bulk-operations/generated/**/*.{ts,tsx}'" + "pnpm eslint --config ../../eslint.codegen.config.js 'src/cli/api/graphql/admin/generated/**/*.{ts,tsx}' --fix && pnpm exec prettier --write --ignore-path ../../.prettierignore 'src/cli/api/graphql/admin/generated/**/*.{ts,tsx}'", + "pnpm eslint --config ../../eslint.codegen.config.js 'src/cli/api/graphql/bulk-operations/generated/**/*.{ts,tsx}' --fix && pnpm exec prettier --write --ignore-path ../../.prettierignore 'src/cli/api/graphql/bulk-operations/generated/**/*.{ts,tsx}'" ], "cwd": "packages/cli-kit" } diff --git a/packages/organizations/project.json b/packages/organizations/project.json index 0fbdd920d71..18b9c654419 100644 --- a/packages/organizations/project.json +++ b/packages/organizations/project.json @@ -53,8 +53,8 @@ ], "options": { "commands": [ - "pnpm eslint 'src/cli/api/graphql/business-platform-destinations/generated/**/*.{ts,tsx}' --fix && pnpm exec prettier --write --ignore-path ../../.prettierignore 'src/cli/api/graphql/business-platform-destinations/generated/**/*.{ts,tsx}'", - "pnpm eslint 'src/cli/api/graphql/business-platform-organizations/generated/**/*.{ts,tsx}' --fix && pnpm exec prettier --write --ignore-path ../../.prettierignore 'src/cli/api/graphql/business-platform-organizations/generated/**/*.{ts,tsx}'" + "pnpm eslint --config ../../eslint.codegen.config.js 'src/cli/api/graphql/business-platform-destinations/generated/**/*.{ts,tsx}' --fix && pnpm exec prettier --write --ignore-path ../../.prettierignore 'src/cli/api/graphql/business-platform-destinations/generated/**/*.{ts,tsx}'", + "pnpm eslint --config ../../eslint.codegen.config.js 'src/cli/api/graphql/business-platform-organizations/generated/**/*.{ts,tsx}' --fix && pnpm exec prettier --write --ignore-path ../../.prettierignore 'src/cli/api/graphql/business-platform-organizations/generated/**/*.{ts,tsx}'" ], "cwd": "packages/organizations" } diff --git a/packages/store/project.json b/packages/store/project.json index aa887bdc79c..f34c0144f2f 100644 --- a/packages/store/project.json +++ b/packages/store/project.json @@ -54,8 +54,8 @@ ], "options": { "commands": [ - "pnpm eslint 'src/cli/api/graphql/business-platform-destinations/generated/**/*.{ts,tsx}' --fix && pnpm exec prettier --write --ignore-path ../../.prettierignore 'src/cli/api/graphql/business-platform-destinations/generated/**/*.{ts,tsx}'", - "pnpm eslint 'src/cli/api/graphql/business-platform-organizations/generated/**/*.{ts,tsx}' --fix && pnpm exec prettier --write --ignore-path ../../.prettierignore 'src/cli/api/graphql/business-platform-organizations/generated/**/*.{ts,tsx}'" + "pnpm eslint --config ../../eslint.codegen.config.js 'src/cli/api/graphql/business-platform-destinations/generated/**/*.{ts,tsx}' --fix && pnpm exec prettier --write --ignore-path ../../.prettierignore 'src/cli/api/graphql/business-platform-destinations/generated/**/*.{ts,tsx}'", + "pnpm eslint --config ../../eslint.codegen.config.js 'src/cli/api/graphql/business-platform-organizations/generated/**/*.{ts,tsx}' --fix && pnpm exec prettier --write --ignore-path ../../.prettierignore 'src/cli/api/graphql/business-platform-organizations/generated/**/*.{ts,tsx}'" ], "cwd": "packages/store" }