oxlint-config-awesomeness 1.2.0 → 2.0.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/README.md +60 -3
- package/bin/init.js +43 -0
- package/bin/template.ts +6 -0
- package/index.js +63 -1
- package/package.json +7 -2
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Opinionated Oxlint config for software houses that want all their apps to feel the same.
|
|
4
4
|
|
|
5
|
-
**
|
|
5
|
+
**430 rules** across **10 plugins**. Built for full-stack TypeScript monorepos with React, Next.js, Hono, Prisma, and more.
|
|
6
6
|
|
|
7
7
|
## Installation
|
|
8
8
|
|
|
@@ -15,7 +15,17 @@ npm install -D oxlint-config-awesomeness eslint-plugin-no-only-tests eslint-plug
|
|
|
15
15
|
|
|
16
16
|
## Usage
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
This package ships an oxlint config object — installing it does **not** generate a config file. You opt in by importing it from your own `oxlint.config.ts`.
|
|
19
|
+
|
|
20
|
+
The fastest way is the included scaffolder:
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
npx oxlint-config-awesomeness init
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
This creates `oxlint.config.ts` in the current directory with the extends boilerplate already wired up. Pass `--force` to overwrite an existing config.
|
|
27
|
+
|
|
28
|
+
If you'd rather write the file yourself, here's all it needs to be:
|
|
19
29
|
|
|
20
30
|
```ts
|
|
21
31
|
import awesomeness from 'oxlint-config-awesomeness';
|
|
@@ -28,6 +38,32 @@ export default defineConfig({
|
|
|
28
38
|
|
|
29
39
|
Then run `pnpm oxlint` or `npx oxlint`.
|
|
30
40
|
|
|
41
|
+
## FAQ
|
|
42
|
+
|
|
43
|
+
### I installed the package but no `.oxlintrc.json` was created. What did I miss?
|
|
44
|
+
|
|
45
|
+
Nothing — that's by design. This package is an oxlint config you `import` from a JS/TS config file, not a scaffolder that runs on install (postinstall scaffolders are widely considered hostile to consumers). Run `npx oxlint-config-awesomeness init` to create `oxlint.config.ts`, or write the four-line file yourself per the Usage section above. Once that file exists, oxlint will discover it automatically.
|
|
46
|
+
|
|
47
|
+
### Can I keep using `.oxlintrc.json` and still consume this package?
|
|
48
|
+
|
|
49
|
+
No. Oxlint's JSON config format only supports file-path `extends`, not package imports — so you can't extend a JS-shipped config from JSON. Migrating to `oxlint.config.ts` is the supported path; the file is small enough to author by hand if you don't want the scaffolder.
|
|
50
|
+
|
|
51
|
+
### How do I add per-project overrides?
|
|
52
|
+
|
|
53
|
+
`defineConfig` merges the `awesomeness` config with anything else you pass. Add overrides alongside `extends`:
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
import awesomeness from 'oxlint-config-awesomeness';
|
|
57
|
+
import { defineConfig } from 'oxlint';
|
|
58
|
+
|
|
59
|
+
export default defineConfig({
|
|
60
|
+
extends: [awesomeness],
|
|
61
|
+
overrides: [
|
|
62
|
+
{ files: ['scripts/**/*.ts'], rules: { 'no-console': 'off' } },
|
|
63
|
+
],
|
|
64
|
+
});
|
|
65
|
+
```
|
|
66
|
+
|
|
31
67
|
## Philosophy
|
|
32
68
|
|
|
33
69
|
- **Error, Never Warn.** Warnings are noise. Either it's an issue, or it isn't.
|
|
@@ -71,7 +107,28 @@ The config includes smart overrides so strict rules don't create noise in files
|
|
|
71
107
|
|
|
72
108
|
Instead of enabling the entire `restriction` category (which includes rules like `no-bitwise`, `no-plusplus`, `capitalized-comments` that cause daily friction), this config cherry-picks the most valuable restriction rules:
|
|
73
109
|
|
|
74
|
-
`curly`, `default-case`, `eqeqeq`, `grouped-accessor-pairs`, `
|
|
110
|
+
`curly`, `default-case`, `eqeqeq`, `grouped-accessor-pairs`, `max-classes-per-file`, `max-depth`, `max-lines`, `max-nested-callbacks`, `max-params`, `no-alert`, `no-caller`, `no-console`, `no-eval`, `no-extend-native`, `no-implicit-coercion`, `no-new-func`, `no-new-wrappers`, `no-object-constructor`, `no-param-reassign`, `no-proto`, `no-return-assign`, `no-script-url`, `no-shadow`, `no-throw-literal`, `no-void`, `prefer-promise-reject-errors`, `prefer-template`
|
|
111
|
+
|
|
112
|
+
## Disabled by Intent
|
|
113
|
+
|
|
114
|
+
The five categories are enabled at `error`, but a small set of category-included rules are explicitly disabled because they fight modern React, Next.js, and ESM conventions:
|
|
115
|
+
|
|
116
|
+
| Category of fight | Rules off |
|
|
117
|
+
|-------------------|-----------|
|
|
118
|
+
| **React 17+ JSX transform / composition** | `react/react-in-jsx-scope`, `react/jsx-props-no-spreading`, `react/jsx-max-depth`, `react/no-array-index-key`, `react/jsx-no-useless-fragment`, `react/jsx-no-constructed-context-values` |
|
|
119
|
+
| **Modern ESM (named exports, side-effect imports, namespace imports, `node:` protocol)** | `import/no-named-export`, `import/prefer-default-export`, `import/group-exports`, `import/exports-last`, `import/no-anonymous-default-export`, `import/no-nodejs-modules`, `import/no-unassigned-import`, `import/no-namespace`, `import/max-dependencies`, `import/first`, `import/consistent-type-specifier-style` |
|
|
120
|
+
| **Pedantic style preferences** | `no-magic-numbers`, `no-ternary`, `no-inline-comments`, `capitalized-comments`, `arrow-body-style`, `func-style`, `func-names`, `init-declarations`, `no-inferrable-types`, `prefer-destructuring`, `no-negated-condition`, `no-continue`, `parameter-properties`, `max-statements`, `max-lines-per-function`, `id-length` |
|
|
121
|
+
| **Unicorn overreach** | `unicorn/prefer-global-this`, `unicorn/no-useless-undefined`, `unicorn/no-nested-ternary`, `unicorn/explicit-length-check`, `unicorn/custom-error-definition`, `unicorn/no-zero-fractions`, `unicorn/escape-case`, `unicorn/no-array-callback-reference`, `unicorn/no-array-for-each`, `unicorn/no-array-reduce` |
|
|
122
|
+
| **Promise rules with broken assumptions** | `promise/prefer-await-to-callbacks`, `promise/avoid-new`, `promise/param-names` |
|
|
123
|
+
|
|
124
|
+
A few of these are particularly worth calling out because they form **contradictory pairs** when both fire on the same code:
|
|
125
|
+
|
|
126
|
+
- `unicorn/explicit-length-check` ↔ `no-magic-numbers` — the first asks you to write `arr.length === 0`, the second then flags the `0`. No way to satisfy both.
|
|
127
|
+
- `import/no-named-export` ↔ `import/prefer-default-export` — exact opposites; one of them is always going to complain.
|
|
128
|
+
- `import/no-namespace` ↔ canonical patterns from Sentry, Prisma, lodash that recommend namespace imports — the rule doesn't know about library conventions.
|
|
129
|
+
- `unicorn/no-zero-fractions` ↔ float-math code that uses `1.0` for type-clarity intent — the rule has no signal about why the `.0` is there.
|
|
130
|
+
|
|
131
|
+
If you want any of these back on for your project, add them to your `oxlint.config.ts` overrides.
|
|
75
132
|
|
|
76
133
|
## Sorting Rules Disabled
|
|
77
134
|
|
package/bin/init.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { copyFileSync, existsSync } from "node:fs";
|
|
3
|
+
import { dirname, resolve } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { parseArgs } from "node:util";
|
|
6
|
+
|
|
7
|
+
const HELP = `Usage: npx oxlint-config-awesomeness init [--force]
|
|
8
|
+
|
|
9
|
+
Scaffold oxlint.config.ts in the current directory.
|
|
10
|
+
-f, --force Overwrite an existing oxlint.config.ts
|
|
11
|
+
-h, --help Show this help
|
|
12
|
+
`;
|
|
13
|
+
|
|
14
|
+
const { positionals, values } = parseArgs({
|
|
15
|
+
allowPositionals: true,
|
|
16
|
+
options: {
|
|
17
|
+
force: { short: "f", type: "boolean" },
|
|
18
|
+
help: { short: "h", type: "boolean" },
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
const command = positionals[0];
|
|
23
|
+
|
|
24
|
+
if (values.help || !command) {
|
|
25
|
+
process.stdout.write(HELP);
|
|
26
|
+
process.exit(0);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (command !== "init") {
|
|
30
|
+
process.stderr.write(`Unknown command: ${command}\n\n${HELP}`);
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const target = resolve("oxlint.config.ts");
|
|
35
|
+
|
|
36
|
+
if (existsSync(target) && !values.force) {
|
|
37
|
+
process.stderr.write("oxlint.config.ts already exists. Re-run with --force.\n");
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
42
|
+
copyFileSync(resolve(here, "template.ts"), target);
|
|
43
|
+
process.stdout.write(`Created ${target}\nNext: npx oxlint\n`);
|
package/bin/template.ts
ADDED
package/index.js
CHANGED
|
@@ -134,6 +134,11 @@ export default defineConfig({
|
|
|
134
134
|
'@typescript-eslint/consistent-type-definitions': ['error', 'type'],
|
|
135
135
|
|
|
136
136
|
// Core eslint — custom options
|
|
137
|
+
'eslint/no-duplicate-imports': ['error',
|
|
138
|
+
{
|
|
139
|
+
allowSeparateTypeImports: true,
|
|
140
|
+
}
|
|
141
|
+
],
|
|
137
142
|
'no-warning-comments': [
|
|
138
143
|
'error',
|
|
139
144
|
{
|
|
@@ -141,12 +146,13 @@ export default defineConfig({
|
|
|
141
146
|
},
|
|
142
147
|
],
|
|
143
148
|
|
|
149
|
+
|
|
150
|
+
|
|
144
151
|
// Restriction — cherry-picked (not bulk-enabled)
|
|
145
152
|
curly: 'error',
|
|
146
153
|
'default-case': 'error',
|
|
147
154
|
eqeqeq: 'error',
|
|
148
155
|
'grouped-accessor-pairs': 'error',
|
|
149
|
-
'id-length': ['error', { exceptions: ['_', 'a', 'b', 'i', 'j', 'k', 'x', 'y', 'z'] }],
|
|
150
156
|
'max-classes-per-file': ['error', { max: 1 }],
|
|
151
157
|
'max-depth': ['error', { max: 4 }],
|
|
152
158
|
'max-lines': ['error', { max: 400, skipBlankLines: true, skipComments: true }],
|
|
@@ -171,6 +177,62 @@ export default defineConfig({
|
|
|
171
177
|
'prefer-promise-reject-errors': 'error',
|
|
172
178
|
'prefer-template': 'error',
|
|
173
179
|
|
|
180
|
+
// Disabled — incompatible with React 17+ JSX transform and common composition patterns
|
|
181
|
+
'react/jsx-max-depth': 'off',
|
|
182
|
+
'react/jsx-no-constructed-context-values': 'off',
|
|
183
|
+
'react/jsx-no-useless-fragment': 'off',
|
|
184
|
+
'react/jsx-props-no-spreading': 'off',
|
|
185
|
+
'react/no-array-index-key': 'off',
|
|
186
|
+
'react/react-in-jsx-scope': 'off',
|
|
187
|
+
|
|
188
|
+
// Disabled — modern ESM uses named exports; side-effect imports (CSS, polyfills, node: protocol) are legitimate; namespace imports are canonical for Sentry, Prisma, etc.
|
|
189
|
+
'import/consistent-type-specifier-style': 'off',
|
|
190
|
+
'import/exports-last': 'off',
|
|
191
|
+
'import/first': 'off',
|
|
192
|
+
'import/group-exports': 'off',
|
|
193
|
+
'import/max-dependencies': 'off',
|
|
194
|
+
'import/no-anonymous-default-export': 'off',
|
|
195
|
+
'import/no-named-export': 'off',
|
|
196
|
+
'import/no-namespace': 'off',
|
|
197
|
+
'import/no-nodejs-modules': 'off',
|
|
198
|
+
'import/no-unassigned-import': 'off',
|
|
199
|
+
'import/prefer-default-export': 'off',
|
|
200
|
+
|
|
201
|
+
// Disabled — pedantic style preferences that fight day-to-day clarity
|
|
202
|
+
'arrow-body-style': 'off',
|
|
203
|
+
'capitalized-comments': 'off',
|
|
204
|
+
'func-names': 'off',
|
|
205
|
+
'func-style': 'off',
|
|
206
|
+
'id-length': 'off',
|
|
207
|
+
'init-declarations': 'off',
|
|
208
|
+
'max-lines-per-function': 'off',
|
|
209
|
+
'max-statements': 'off',
|
|
210
|
+
'no-continue': 'off',
|
|
211
|
+
'no-inferrable-types': 'off',
|
|
212
|
+
'no-inline-comments': 'off',
|
|
213
|
+
'no-magic-numbers': 'off',
|
|
214
|
+
'no-negated-condition': 'off',
|
|
215
|
+
'no-ternary': 'off',
|
|
216
|
+
'parameter-properties': 'off',
|
|
217
|
+
'prefer-destructuring': 'off',
|
|
218
|
+
|
|
219
|
+
// Disabled — unicorn rules that overreach into legitimate patterns
|
|
220
|
+
'unicorn/custom-error-definition': 'off',
|
|
221
|
+
'unicorn/escape-case': 'off',
|
|
222
|
+
'unicorn/explicit-length-check': 'off',
|
|
223
|
+
'unicorn/no-array-callback-reference': 'off',
|
|
224
|
+
'unicorn/no-array-for-each': 'off',
|
|
225
|
+
'unicorn/no-array-reduce': 'off',
|
|
226
|
+
'unicorn/no-nested-ternary': 'off',
|
|
227
|
+
'unicorn/no-useless-undefined': 'off',
|
|
228
|
+
'unicorn/no-zero-fractions': 'off',
|
|
229
|
+
'unicorn/prefer-global-this': 'off',
|
|
230
|
+
|
|
231
|
+
// Disabled — async/await is preferred but raw Promise constructors and callbacks remain idiomatic in many APIs (event emitters, streams, callback adapters)
|
|
232
|
+
'promise/avoid-new': 'off',
|
|
233
|
+
'promise/param-names': 'off',
|
|
234
|
+
'promise/prefer-await-to-callbacks': 'off',
|
|
235
|
+
|
|
174
236
|
// Style overrides — handled by perfectionist/oxfmt
|
|
175
237
|
'sort-imports': 'off',
|
|
176
238
|
'sort-keys': 'off',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "oxlint-config-awesomeness",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Oxlint config with sensible defaults.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"autofix",
|
|
@@ -12,10 +12,15 @@
|
|
|
12
12
|
"license": "MIT",
|
|
13
13
|
"files": [
|
|
14
14
|
"index.js",
|
|
15
|
-
"index.d.ts"
|
|
15
|
+
"index.d.ts",
|
|
16
|
+
"bin/init.js",
|
|
17
|
+
"bin/template.ts"
|
|
16
18
|
],
|
|
17
19
|
"type": "module",
|
|
18
20
|
"main": "index.js",
|
|
21
|
+
"bin": {
|
|
22
|
+
"oxlint-config-awesomeness": "./bin/init.js"
|
|
23
|
+
},
|
|
19
24
|
"scripts": {
|
|
20
25
|
"lint": "oxlint ."
|
|
21
26
|
},
|