Remove ESLint and use independent Oxlint rules - #8211
gonzaloriestra wants to merge 4 commits into
Conversation
|
Warning This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
This stack of pull requests is managed by Graphite. Learn more about stacking. |
|
This PR seems inactive. If it's still relevant, please add a comment saying so. Otherwise, take no action. |
2b07749 to
24f882f
Compare
24f882f to
9a488dd
Compare
9a488dd to
0e8ac24
Compare
Differences in type declarationsWe detected differences in the type declarations generated by Typescript for this branch compared to the baseline ('main' branch). Please, review them to ensure they are backward-compatible. Here are some important things to keep in mind:
New type declarationsWe found no new type declarations in this PR Existing type declarationspackages/cli-kit/dist/cli/api/graphql/admin/generated/find_development_theme_by_name.d.ts@@ -5,12 +5,12 @@ export type FindDevelopmentThemeByNameQueryVariables = Types.Exact<{
}>;
export type FindDevelopmentThemeByNameQuery = {
themes?: {
- nodes: {
+ nodes: Array<{
id: string;
name: string;
role: Types.ThemeRole;
processing: boolean;
- }[];
+ }>;
} | null;
};
export declare const FindDevelopmentThemeByName: DocumentNode<FindDevelopmentThemeByNameQuery, FindDevelopmentThemeByNameQueryVariables>;
\ No newline at end of file
packages/cli-kit/dist/cli/api/graphql/admin/generated/get_theme_file_bodies.d.ts@@ -3,12 +3,12 @@ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/
export type GetThemeFileBodiesQueryVariables = Types.Exact<{
id: Types.Scalars['ID']['input'];
after?: Types.InputMaybe<Types.Scalars['String']['input']>;
- filenames?: Types.InputMaybe<Types.Scalars['String']['input'][] | Types.Scalars['String']['input']>;
+ filenames?: Types.InputMaybe<Array<Types.Scalars['String']['input']> | Types.Scalars['String']['input']>;
}>;
export type GetThemeFileBodiesQuery = {
theme?: {
files?: {
- nodes: {
+ nodes: Array<{
filename: string;
size: unknown;
checksumMd5?: string | null;
@@ -22,11 +22,11 @@ export type GetThemeFileBodiesQuery = {
__typename: 'OnlineStoreThemeFileBodyUrl';
url: string;
};
- }[];
- userErrors: {
+ }>;
+ userErrors: Array<{
filename: string;
code: Types.OnlineStoreThemeFileResultType;
- }[];
+ }>;
pageInfo: {
hasNextPage: boolean;
endCursor?: string | null;
packages/cli-kit/dist/cli/api/graphql/admin/generated/get_theme_file_checksums.d.ts@@ -7,15 +7,15 @@ export type GetThemeFileChecksumsQueryVariables = Types.Exact<{
export type GetThemeFileChecksumsQuery = {
theme?: {
files?: {
- nodes: {
+ nodes: Array<{
filename: string;
size: unknown;
checksumMd5?: string | null;
- }[];
- userErrors: {
+ }>;
+ userErrors: Array<{
filename: string;
code: Types.OnlineStoreThemeFileResultType;
- }[];
+ }>;
pageInfo: {
hasNextPage: boolean;
endCursor?: string | null;
packages/cli-kit/dist/cli/api/graphql/admin/generated/get_themes.d.ts@@ -5,12 +5,12 @@ export type GetThemesQueryVariables = Types.Exact<{
}>;
export type GetThemesQuery = {
themes?: {
- nodes: {
+ nodes: Array<{
id: string;
name: string;
role: Types.ThemeRole;
processing: boolean;
- }[];
+ }>;
pageInfo: {
hasNextPage: boolean;
endCursor?: string | null;
packages/cli-kit/dist/cli/api/graphql/admin/generated/metafield_definitions_by_owner_type.d.ts@@ -5,7 +5,7 @@ export type MetafieldDefinitionsByOwnerTypeQueryVariables = Types.Exact<{
}>;
export type MetafieldDefinitionsByOwnerTypeQuery = {
metafieldDefinitions: {
- nodes: {
+ nodes: Array<{
key: string;
name: string;
namespace: string;
@@ -14,7 +14,7 @@ export type MetafieldDefinitionsByOwnerTypeQuery = {
category: string;
name: string;
};
- }[];
+ }>;
};
};
export declare const MetafieldDefinitionsByOwnerType: DocumentNode<MetafieldDefinitionsByOwnerTypeQuery, MetafieldDefinitionsByOwnerTypeQueryVariables>;
\ No newline at end of file
packages/cli-kit/dist/cli/api/graphql/admin/generated/public_api_versions.d.ts@@ -4,9 +4,9 @@ export type PublicApiVersionsQueryVariables = Types.Exact<{
[key: string]: never;
}>;
export type PublicApiVersionsQuery = {
- publicApiVersions: {
+ publicApiVersions: Array<{
handle: string;
supported: boolean;
- }[];
+ }>;
};
export declare const PublicApiVersions: DocumentNode<PublicApiVersionsQuery, PublicApiVersionsQueryVariables>;
\ No newline at end of file
packages/cli-kit/dist/cli/api/graphql/admin/generated/theme_create.d.ts@@ -12,10 +12,10 @@ export type ThemeCreateMutation = {
name: string;
role: Types.ThemeRole;
} | null;
- userErrors: {
- field?: string[] | null;
+ userErrors: Array<{
+ field?: Array<string> | null;
message: string;
- }[];
+ }>;
} | null;
};
export declare const ThemeCreate: DocumentNode<ThemeCreateMutation, ThemeCreateMutationVariables>;
\ No newline at end of file
packages/cli-kit/dist/cli/api/graphql/admin/generated/theme_delete.d.ts@@ -6,10 +6,10 @@ export type ThemeDeleteMutationVariables = Types.Exact<{
export type ThemeDeleteMutation = {
themeDelete?: {
deletedThemeId?: string | null;
- userErrors: {
- field?: string[] | null;
+ userErrors: Array<{
+ field?: Array<string> | null;
message: string;
- }[];
+ }>;
} | null;
};
export declare const ThemeDelete: DocumentNode<ThemeDeleteMutation, ThemeDeleteMutationVariables>;
\ No newline at end of file
packages/cli-kit/dist/cli/api/graphql/admin/generated/theme_duplicate.d.ts@@ -11,10 +11,10 @@ export type ThemeDuplicateMutation = {
name: string;
role: Types.ThemeRole;
} | null;
- userErrors: {
- field?: string[] | null;
+ userErrors: Array<{
+ field?: Array<string> | null;
message: string;
- }[];
+ }>;
} | null;
};
export declare const ThemeDuplicate: DocumentNode<ThemeDuplicateMutation, ThemeDuplicateMutationVariables>;
\ No newline at end of file
packages/cli-kit/dist/cli/api/graphql/admin/generated/theme_files_delete.d.ts@@ -2,18 +2,18 @@ import * as Types from './types.js';
import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';
export type ThemeFilesDeleteMutationVariables = Types.Exact<{
themeId: Types.Scalars['ID']['input'];
- files: Types.Scalars['String']['input'][] | Types.Scalars['String']['input'];
+ files: Array<Types.Scalars['String']['input']> | Types.Scalars['String']['input'];
}>;
export type ThemeFilesDeleteMutation = {
themeFilesDelete?: {
- deletedThemeFiles?: {
+ deletedThemeFiles?: Array<{
filename: string;
- }[] | null;
- userErrors: {
+ }> | null;
+ userErrors: Array<{
filename?: string | null;
code?: Types.OnlineStoreThemeFilesUserErrorsCode | null;
message: string;
- }[];
+ }>;
} | null;
};
export declare const ThemeFilesDelete: DocumentNode<ThemeFilesDeleteMutation, ThemeFilesDeleteMutationVariables>;
\ No newline at end of file
packages/cli-kit/dist/cli/api/graphql/admin/generated/theme_files_upsert.d.ts@@ -1,18 +1,18 @@
import * as Types from './types.js';
import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';
export type ThemeFilesUpsertMutationVariables = Types.Exact<{
- files: Types.OnlineStoreThemeFilesUpsertFileInput[] | Types.OnlineStoreThemeFilesUpsertFileInput;
+ files: Array<Types.OnlineStoreThemeFilesUpsertFileInput> | Types.OnlineStoreThemeFilesUpsertFileInput;
themeId: Types.Scalars['ID']['input'];
}>;
export type ThemeFilesUpsertMutation = {
themeFilesUpsert?: {
- upsertedThemeFiles?: {
+ upsertedThemeFiles?: Array<{
filename: string;
- }[] | null;
- userErrors: {
+ }> | null;
+ userErrors: Array<{
filename?: string | null;
message: string;
- }[];
+ }>;
} | null;
};
export declare const ThemeFilesUpsert: DocumentNode<ThemeFilesUpsertMutation, ThemeFilesUpsertMutationVariables>;
\ No newline at end of file
packages/cli-kit/dist/cli/api/graphql/admin/generated/theme_publish.d.ts@@ -10,10 +10,10 @@ export type ThemePublishMutation = {
name: string;
role: Types.ThemeRole;
} | null;
- userErrors: {
- field?: string[] | null;
+ userErrors: Array<{
+ field?: Array<string> | null;
message: string;
- }[];
+ }>;
} | null;
};
export declare const ThemePublish: DocumentNode<ThemePublishMutation, ThemePublishMutationVariables>;
\ No newline at end of file
packages/cli-kit/dist/cli/api/graphql/admin/generated/theme_update.d.ts@@ -11,10 +11,10 @@ export type ThemeUpdateMutation = {
name: string;
role: Types.ThemeRole;
} | null;
- userErrors: {
- field?: string[] | null;
+ userErrors: Array<{
+ field?: Array<string> | null;
message: string;
- }[];
+ }>;
} | null;
};
export declare const ThemeUpdate: DocumentNode<ThemeUpdateMutation, ThemeUpdateMutationVariables>;
\ No newline at end of file
packages/cli-kit/dist/cli/api/graphql/bulk-operations/generated/bulk-operation-cancel.d.ts@@ -19,10 +19,10 @@ export type BulkOperationCancelMutation = {
type: Types.BulkOperationType;
url?: string | null;
} | null;
- userErrors: {
- field?: string[] | null;
+ userErrors: Array<{
+ field?: Array<string> | null;
message: string;
- }[];
+ }>;
} | null;
};
export declare const BulkOperationCancel: DocumentNode<BulkOperationCancelMutation, BulkOperationCancelMutationVariables>;
\ No newline at end of file
packages/cli-kit/dist/cli/api/graphql/bulk-operations/generated/bulk-operation-run-mutation.d.ts@@ -18,11 +18,11 @@ export type BulkOperationRunMutationMutation = {
status: Types.BulkOperationStatus;
url?: string | null;
} | null;
- userErrors: {
+ userErrors: Array<{
code?: Types.BulkMutationErrorCode | null;
- field?: string[] | null;
+ field?: Array<string> | null;
message: string;
- }[];
+ }>;
} | null;
};
export declare const BulkOperationRunMutation: DocumentNode<BulkOperationRunMutationMutation, BulkOperationRunMutationMutationVariables>;
\ No newline at end of file
packages/cli-kit/dist/cli/api/graphql/bulk-operations/generated/bulk-operation-run-query.d.ts@@ -16,11 +16,11 @@ export type BulkOperationRunQueryMutation = {
status: Types.BulkOperationStatus;
url?: string | null;
} | null;
- userErrors: {
+ userErrors: Array<{
code?: Types.BulkOperationUserErrorCode | null;
- field?: string[] | null;
+ field?: Array<string> | null;
message: string;
- }[];
+ }>;
} | null;
};
export declare const BulkOperationRunQuery: DocumentNode<BulkOperationRunQueryMutation, BulkOperationRunQueryMutationVariables>;
\ No newline at end of file
packages/cli-kit/dist/cli/api/graphql/bulk-operations/generated/list-bulk-operations.d.ts@@ -7,7 +7,7 @@ export type ListBulkOperationsQueryVariables = Types.Exact<{
}>;
export type ListBulkOperationsQuery = {
bulkOperations: {
- nodes: {
+ nodes: Array<{
id: string;
status: Types.BulkOperationStatus;
errorCode?: Types.BulkOperationErrorCode | null;
@@ -16,7 +16,7 @@ export type ListBulkOperationsQuery = {
completedAt?: unknown | null;
url?: string | null;
partialDataUrl?: string | null;
- }[];
+ }>;
};
};
export declare const ListBulkOperations: DocumentNode<ListBulkOperationsQuery, ListBulkOperationsQueryVariables>;
\ No newline at end of file
packages/cli-kit/dist/cli/api/graphql/bulk-operations/generated/staged-uploads-create.d.ts@@ -1,22 +1,22 @@
import * as Types from './types.js';
import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';
export type StagedUploadsCreateMutationVariables = Types.Exact<{
- input: Types.StagedUploadInput[] | Types.StagedUploadInput;
+ input: Array<Types.StagedUploadInput> | Types.StagedUploadInput;
}>;
export type StagedUploadsCreateMutation = {
stagedUploadsCreate?: {
- stagedTargets?: {
+ stagedTargets?: Array<{
url?: string | null;
resourceUrl?: string | null;
- parameters: {
+ parameters: Array<{
name: string;
value: string;
- }[];
- }[] | null;
- userErrors: {
- field?: string[] | null;
+ }>;
+ }> | null;
+ userErrors: Array<{
+ field?: Array<string> | null;
message: string;
- }[];
+ }>;
} | null;
};
export declare const StagedUploadsCreate: DocumentNode<StagedUploadsCreateMutation, StagedUploadsCreateMutationVariables>;
\ No newline at end of file
|
5782533 to
2be3736
Compare
cbbfb0f to
5e5074d
Compare
5e5074d to
5261c59
Compare
|
| Changeset | Package |
|---|---|
remove-cli-eslint-config-dependencies.md |
'@shopify/eslint-plugin-cli': major |

WHY are these changes introduced?
Remove ESLint from the CLI lint command and installed dependency tree while retaining the public CLI rules and as many existing checks as practical.
WHAT is this pull request doing?
Use native Oxlint, its type-aware checker, Prettier, and the independent rules prepared in #8725. Remove the compatibility adapter, upstream ESLint plugins, repository ESLint configuration, and associated CI/editor wiring. Workspace boundary checks read package manifests directly, removing Nx graph generation from lint startup.
Keep
@shopify/eslint-plugin-clipublic and preserve all 14 custom rule exports, includingcommand-json-output. Itsconfigs.configentry point now contains only CLI rules and test exemptions. Consumers must supply their own shared configs and TypeScript parser. This breaking public config change has a major changeset.Preserve existing type assertions, default imports, and suppression names through dependency-free rule aliases. This reduces the final PR from 257 to 85 changed files (192 to 26 under
src). Remaining source edits remove obsolete/unused suppressions. The codegen formatter preserves the existing generated import spacing, eliminating all nine whitespace-only generated-file diffs. Repeated uncached code generation produces identical files; this formatting change does not alter lint rules or coverage.Disable three native checks that report code accepted by the previous ESLint pipeline:
typescript/no-unnecessary-type-assertion,import/no-named-as-default, andimport/no-named-as-default-member. Their available options do not give equivalent behavior for these cases. This is an explicit coverage tradeoff to minimize migration changes. Declared type parameters remain checked; inferred bindings keep their existing names.Coverage audit
Against the original configuration, 243 of 301 lint rule names have replacements: 194 native counterparts, 14 retained implementations, and 35 partial independent replacements. 58 rule names have no dedicated replacement; 11 have identified coverage or overlap elsewhere in the existing toolchain. Prettier covers formatting separately. These counts do not mean 58 wholly missing capabilities, and overlap is not proof of full behavioral parity.
Existing tools cover part of this territory:
Remaining gaps include redundant type assertions, ambiguous default imports, deprecated imports and redundant paths, import checks outside the tools' scopes, advanced JSDoc semantics, consistent returns and atomic updates, Node API metadata, specialized Shopify/style policies, and Nx cycles/tags/buildability/lazy loading. Knip excludes the plugin and e2e workspaces and selected generated files. Several original rules, including consistent returns and undeclared dependencies, applied only to JavaScript; TypeScript does not replace those scopes. The shared TS config does not enable
checkJsornoImplicitReturns.The ESLint-free audit compares 1,633 surviving files against a frozen baseline. It reports no lint-rule scope, severity, option, or formatting gaps beyond the declared limitations. It also lists manually verified tool overlap separately; it does not prove equivalent scopes across tools. See
docs/cli/oxlint-rule-coverage.mdandconfigurations/oxlint-rule-mapping.jsonfor the full mapping and counterexamples.Benchmark
Apple M3 Pro / macOS arm64, Node 24.15.0, pnpm 10.11.1. Medians of three serial
pnpm lintruns per side after one warm-up, alternating order, with Nx local/remote caches disabled and the daemon off. Compared #8725 (e8e0270c0d) with this PR (6daafb361b). No tests or code generation ran concurrently.Checklist