Skip to content

Commit 8e43a7c

Browse files
atilafassinaIsaac
andauthored
chore: lint template apps with oxlint instead of ESLint (#665)
Signed-off-by: Atila Fassina <atila@fassina.eu> Co-authored-by: Isaac <no-reply@databricks.com>
1 parent 670764d commit 8e43a7c

11 files changed

Lines changed: 5613 additions & 7126 deletions

‎CLAUDE.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,8 @@ The frontend uses `rolldown-vite@7.1.14`, a performance-optimized Vite fork.
321321

322322
The oxc (VoidZero) toolchain is used instead of ESLint/Prettier for faster performance:
323323
- `oxlint` for linting (config in `.oxlintrc.json`)
324+
- Root scripts pass `--disable-nested-config`: `template/.oxlintrc.json` belongs to scaffolded apps and must not apply to the raw template
325+
- The template smoke test lints one fixture per `template/.oxlintrc.json` rule (`tools/template-lint-fixtures.ts`); add a fixture when enabling a rule
324326
- `oxfmt` for formatting + import sorting (config in `.oxfmtrc.json`)
325327
- Lint-staged integration via husky
326328
- Note: oxc does not lint/format CSS

‎package.json‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
"size:compare": "tsx tools/bundle-size.ts --compare",
1212
"sync:template": "node packages/shared/bin/appkit.js plugin sync --write --silent --plugins-dir packages/appkit/src/plugins --output template/appkit.plugins.json --require-plugins server",
1313
"build:watch": "pnpm -r --filter=!dev-playground --filter=!docs build:watch",
14-
"check:fix": "oxlint --fix && oxfmt",
15-
"check": "oxlint && oxfmt --check",
14+
"check:fix": "oxlint --disable-nested-config --fix && oxfmt",
15+
"check": "oxlint --disable-nested-config && oxfmt --check",
1616
"generate:types": "tsx tools/generate-json-schema.ts && tsx tools/generate-registry-types.ts && tsx tools/generate-plugin-entries.ts && tsx tools/generate-plugin-doc-banners.ts",
1717
"generate:plugin-entries": "tsx tools/generate-plugin-entries.ts",
1818
"generate:plugin-doc-banners": "tsx tools/generate-plugin-doc-banners.ts",
@@ -34,8 +34,8 @@
3434
"docs:lint": "oxlint docs/",
3535
"format:check": "oxfmt --check",
3636
"format": "oxfmt",
37-
"lint:fix": "oxlint --fix",
38-
"lint": "oxlint",
37+
"lint:fix": "oxlint --disable-nested-config --fix",
38+
"lint": "oxlint --disable-nested-config",
3939
"pack:sdk": "pnpm build && pnpm --filter=docs build && pnpm -r tarball",
4040
"pack:prerelease": "pnpm build && pnpm --filter=docs build && pnpm -r --filter='@databricks/*' tarball:prerelease",
4141
"prepare": "husky",
@@ -51,7 +51,7 @@
5151
},
5252
"lint-staged": {
5353
"*.{ts,tsx,js,jsx}": [
54-
"oxlint --fix --no-error-on-unmatched-pattern",
54+
"oxlint --disable-nested-config --fix --no-error-on-unmatched-pattern",
5555
"oxfmt --write --no-error-on-unmatched-pattern"
5656
],
5757
"*.json": [

‎template/.oxlintrc.json‎

Lines changed: 244 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
{
2+
"$schema": "./node_modules/oxlint/configuration_schema.json",
3+
"plugins": ["typescript", "react"],
4+
// React Compiler rules run through eslint-plugin-react-hooks. The alias is required because
5+
// oxlint reserves the `react-hooks` name for its native rules-of-hooks and exhaustive-deps.
6+
// JS plugins are alpha and outside semver, so oxlint is pinned exactly. The template smoke test
7+
// (tools/template-lint-fixtures.ts) checks every rule still reports; run it on each oxlint upgrade.
8+
"jsPlugins": [{ "name": "react-hooks-js", "specifier": "eslint-plugin-react-hooks" }],
9+
// Only the rules listed below are enabled.
10+
"categories": {
11+
"correctness": "off"
12+
},
13+
"options": {
14+
"typeAware": true,
15+
"reportUnusedDisableDirectives": "warn"
16+
},
17+
"rules": {
18+
// eslint:recommended
19+
"constructor-super": "error",
20+
"for-direction": "error",
21+
"getter-return": "error",
22+
"no-async-promise-executor": "error",
23+
"no-case-declarations": "error",
24+
"no-class-assign": "error",
25+
"no-compare-neg-zero": "error",
26+
"no-cond-assign": "error",
27+
"no-const-assign": "error",
28+
"no-constant-binary-expression": "error",
29+
"no-constant-condition": "error",
30+
"no-control-regex": "error",
31+
"no-debugger": "error",
32+
"no-delete-var": "error",
33+
"no-dupe-class-members": "error",
34+
"no-dupe-else-if": "error",
35+
"no-dupe-keys": "error",
36+
"no-duplicate-case": "error",
37+
"no-empty": "error",
38+
"no-empty-character-class": "error",
39+
"no-empty-pattern": "error",
40+
"no-empty-static-block": "error",
41+
"no-ex-assign": "error",
42+
"no-extra-boolean-cast": "error",
43+
"no-fallthrough": "error",
44+
"no-func-assign": "error",
45+
"no-global-assign": "error",
46+
"no-import-assign": "error",
47+
"no-invalid-regexp": "error",
48+
// ESLint's defaults; oxlint skips comments, JSX text, regexps and templates by default
49+
"no-irregular-whitespace": [
50+
"error",
51+
{ "skipComments": false, "skipJSXText": false, "skipRegExps": false, "skipStrings": true, "skipTemplates": false }
52+
],
53+
"no-loss-of-precision": "error",
54+
"no-misleading-character-class": "error",
55+
"no-new-native-nonconstructor": "error",
56+
"no-nonoctal-decimal-escape": "error",
57+
"no-obj-calls": "error",
58+
"no-prototype-builtins": "error",
59+
"no-redeclare": "error",
60+
"no-regex-spaces": "error",
61+
"no-self-assign": "error",
62+
"no-setter-return": "error",
63+
"no-shadow-restricted-names": ["error", { "reportGlobalThis": false }],
64+
"no-sparse-arrays": "error",
65+
"no-this-before-super": "error",
66+
"no-undef": "error",
67+
"no-unreachable": "error",
68+
"no-unsafe-finally": "error",
69+
"no-unsafe-negation": "error",
70+
"no-unsafe-optional-chaining": "error",
71+
"no-unused-labels": "error",
72+
"no-unused-private-class-members": "error",
73+
"no-useless-backreference": "error",
74+
"no-useless-catch": "error",
75+
"no-useless-escape": "error",
76+
"no-with": "error",
77+
"require-yield": "error",
78+
"use-isnan": "error",
79+
"valid-typeof": "error",
80+
81+
// typescript-eslint recommended-type-checked
82+
"no-array-constructor": "error",
83+
"no-unused-expressions": "error",
84+
"no-unused-vars": ["error", { "argsIgnorePattern": "^_", "varsIgnorePattern": "^_" }],
85+
"typescript/await-thenable": "error",
86+
"typescript/ban-ts-comment": "error",
87+
"typescript/no-array-delete": "error",
88+
"typescript/no-base-to-string": "error",
89+
"typescript/no-duplicate-enum-values": "error",
90+
"typescript/no-duplicate-type-constituents": "error",
91+
"typescript/no-empty-object-type": "error",
92+
"typescript/no-explicit-any": "warn",
93+
"typescript/no-extra-non-null-assertion": "error",
94+
"typescript/no-floating-promises": "error",
95+
"typescript/no-for-in-array": "error",
96+
"typescript/no-implied-eval": "error",
97+
"typescript/no-misused-new": "error",
98+
"typescript/no-misused-promises": "error",
99+
"typescript/no-namespace": "error",
100+
"typescript/no-non-null-asserted-optional-chain": "error",
101+
"typescript/no-redundant-type-constituents": "error",
102+
"typescript/no-require-imports": "error",
103+
"typescript/no-this-alias": "error",
104+
"typescript/no-unnecessary-type-assertion": "error",
105+
"typescript/no-unnecessary-type-constraint": "error",
106+
"typescript/no-unsafe-argument": "error",
107+
"typescript/no-unsafe-assignment": "error",
108+
"typescript/no-unsafe-call": "error",
109+
"typescript/no-unsafe-declaration-merging": "error",
110+
"typescript/no-unsafe-enum-comparison": "error",
111+
"typescript/no-unsafe-function-type": "error",
112+
"typescript/no-unsafe-member-access": "error",
113+
"typescript/no-unsafe-return": "error",
114+
"typescript/no-unsafe-unary-minus": "error",
115+
"typescript/no-wrapper-object-types": "error",
116+
"typescript/only-throw-error": "error",
117+
"typescript/prefer-as-const": "error",
118+
"typescript/prefer-namespace-keyword": "error",
119+
"typescript/prefer-promise-reject-errors": "error",
120+
"typescript/require-await": "error",
121+
"typescript/restrict-plus-operands": "error",
122+
"typescript/restrict-template-expressions": "error",
123+
"typescript/triple-slash-reference": "error",
124+
"typescript/unbound-method": "error"
125+
},
126+
"overrides": [
127+
{
128+
// TypeScript files: the TypeScript compiler already covers these checks
129+
"files": ["**/*.ts", "**/*.tsx", "**/*.mts", "**/*.cts"],
130+
"rules": {
131+
"constructor-super": "off",
132+
"getter-return": "off",
133+
"no-class-assign": "off",
134+
"no-const-assign": "off",
135+
"no-dupe-class-members": "off",
136+
"no-dupe-keys": "off",
137+
"no-func-assign": "off",
138+
"no-import-assign": "off",
139+
"no-new-native-nonconstructor": "off",
140+
"no-obj-calls": "off",
141+
"no-redeclare": "off",
142+
"no-setter-return": "off",
143+
"no-this-before-super": "off",
144+
"no-undef": "off",
145+
"no-unreachable": "off",
146+
"no-unsafe-negation": "off",
147+
"no-with": "off",
148+
"no-var": "error",
149+
"prefer-const": "error",
150+
"prefer-rest-params": "error",
151+
"prefer-spread": "error"
152+
}
153+
},
154+
{
155+
// React config for client-side files
156+
"files": ["client/**/*.{ts,tsx}", "**/*.tsx"],
157+
"rules": {
158+
"react/display-name": "error",
159+
"react/jsx-key": [
160+
"error",
161+
{ "checkFragmentShorthand": false, "checkKeyMustBeforeSpread": false, "warnOnDuplicates": false }
162+
],
163+
"react/jsx-no-comment-textnodes": "error",
164+
"react/jsx-no-duplicate-props": "error",
165+
"react/jsx-no-target-blank": "error",
166+
"react/jsx-no-undef": "error",
167+
"react/no-children-prop": "error",
168+
"react/no-danger-with-children": "error",
169+
"react/no-direct-mutation-state": "error",
170+
"react/no-find-dom-node": "error",
171+
"react/no-is-mounted": "error",
172+
"react/no-render-return-value": "error",
173+
"react/no-string-refs": "error",
174+
"react/no-unescaped-entities": "error",
175+
"react/no-unknown-property": "error",
176+
"react/require-render-return": "error",
177+
// Stand-ins for eslint-plugin-react's no-deprecated: legacy lifecycle methods (also flags their
178+
// UNSAFE_ variants), plus deprecated APIs through their @deprecated types
179+
"react/no-unsafe": ["error", { "checkAliases": true }],
180+
"typescript/no-deprecated": "warn",
181+
182+
"react/rules-of-hooks": "error",
183+
"react/exhaustive-deps": "warn",
184+
"react-hooks-js/component-hook-factories": "error",
185+
"react-hooks-js/config": "error",
186+
"react-hooks-js/error-boundaries": "error",
187+
"react-hooks-js/gating": "error",
188+
"react-hooks-js/globals": "error",
189+
"react-hooks-js/immutability": "error",
190+
"react-hooks-js/incompatible-library": "warn",
191+
"react-hooks-js/preserve-manual-memoization": "error",
192+
"react-hooks-js/purity": "error",
193+
"react-hooks-js/refs": "error",
194+
"react-hooks-js/set-state-in-effect": "error",
195+
"react-hooks-js/set-state-in-render": "error",
196+
"react-hooks-js/static-components": "error",
197+
"react-hooks-js/unsupported-syntax": "warn",
198+
"react-hooks-js/use-memo": "error",
199+
200+
"react/only-export-components": ["warn", { "allowConstantExport": true }],
201+
"react/no-array-index-key": "warn"
202+
}
203+
},
204+
{
205+
// Disable type-aware rules for JS files and config files, which aren't part of a tsconfig project
206+
"files": ["**/*.js", "*.config.ts", "**/*.config.ts"],
207+
"rules": {
208+
"typescript/await-thenable": "off",
209+
"typescript/no-array-delete": "off",
210+
"typescript/no-base-to-string": "off",
211+
"typescript/no-deprecated": "off",
212+
"typescript/no-duplicate-type-constituents": "off",
213+
"typescript/no-floating-promises": "off",
214+
"typescript/no-for-in-array": "off",
215+
"typescript/no-implied-eval": "off",
216+
"typescript/no-misused-promises": "off",
217+
"typescript/no-redundant-type-constituents": "off",
218+
"typescript/no-unnecessary-type-assertion": "off",
219+
"typescript/no-unsafe-argument": "off",
220+
"typescript/no-unsafe-assignment": "off",
221+
"typescript/no-unsafe-call": "off",
222+
"typescript/no-unsafe-enum-comparison": "off",
223+
"typescript/no-unsafe-member-access": "off",
224+
"typescript/no-unsafe-return": "off",
225+
"typescript/no-unsafe-unary-minus": "off",
226+
"typescript/only-throw-error": "off",
227+
"typescript/prefer-promise-reject-errors": "off",
228+
"typescript/require-await": "off",
229+
"typescript/restrict-plus-operands": "off",
230+
"typescript/restrict-template-expressions": "off",
231+
"typescript/unbound-method": "off"
232+
}
233+
}
234+
],
235+
"ignorePatterns": [
236+
"**/dist/**",
237+
"**/build/**",
238+
"**/node_modules/**",
239+
"**/.next/**",
240+
"**/coverage/**",
241+
"client/dist/**",
242+
"**/.databricks/**"
243+
]
244+
}

‎template/eslint.config.js‎

Lines changed: 0 additions & 89 deletions
This file was deleted.

0 commit comments

Comments
 (0)