@hooshid/ox-config 0.3.0 → 1.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 CHANGED
@@ -16,11 +16,11 @@ pnpm add -D @hooshid/ox-config
16
16
  Create `oxlint.config.ts` in your project root:
17
17
 
18
18
  ```ts
19
- import { base, unicorn, depend, react, tailwind, vitest } from '@hooshid/ox-config/lint'
19
+ import { base, unicorn, depend, reactVite, tailwind } from '@hooshid/ox-config/lint'
20
20
  import { defineConfig } from 'oxlint'
21
21
 
22
22
  export default defineConfig({
23
- extends: [base(), unicorn(), depend(), react(), tailwind(), vitest()],
23
+ extends: [base(), unicorn(), depend(), reactVite(), tailwind()],
24
24
  })
25
25
  ```
26
26
 
@@ -52,20 +52,21 @@ export default defineConfig({
52
52
 
53
53
  #### Runtime
54
54
 
55
- | Preset | Description |
56
- | ----------- | ---------------------------------- |
57
- | `node()` | Node.js specific rules |
58
- | `promise()` | Promise best practices (16 rules) |
55
+ | Preset | Description |
56
+ | ----------- | --------------------------------- |
57
+ | `node()` | Node.js specific rules |
58
+ | `promise()` | Promise best practices (16 rules) |
59
59
 
60
60
  #### Frontend
61
61
 
62
- | Preset | Description |
63
- | ------------------ | -------------------------------------------------------- |
64
- | `react()` | React + React Hooks |
65
- | `reactVite()` | React + React Hooks + React Refresh (for Vite) |
66
- | `nextjs()` | Next.js rules + Core Web Vitals |
67
- | `tanstackRouter()` | TanStack Router — route param names + property ordering |
68
- | `tailwind()` | Tailwind class consistency (better-tailwindcss plugin) |
62
+ | Preset | Description |
63
+ | ------------------ | --------------------------------------------------------------- |
64
+ | `react()` | React + React Hooks — core rules for any React setup |
65
+ | `reactVite()` | React + React Hooks + React Refresh (for Vite) |
66
+ | `nextjs()` | Next.js rules + Core Web Vitals |
67
+ | `tanstackRouter()` | TanStack Router — routing rules + route folder naming convention |
68
+ | `tanstackStart()` | TanStack Start — server/client boundaries, SSR safety |
69
+ | `tailwind()` | Tailwind class consistency (better-tailwindcss plugin) |
69
70
 
70
71
  #### Backend / ORM
71
72
 
@@ -89,53 +90,91 @@ export default defineConfig({
89
90
 
90
91
  ### Which React preset should I use?
91
92
 
92
- | Project type | Preset |
93
- | ----------------------------- | ------------- |
94
- | Next.js | `nextjs()` |
95
- | Vite + React | `reactVite()` |
96
- | TanStack Start | `reactVite()` |
97
- | Plain React (CRA, custom) | `react()` |
93
+ | Project type | Presets to use |
94
+ | ------------------------- | ------------------------------------------------- |
95
+ | Next.js | `nextjs()` + `react()` |
96
+ | Vite + React | `reactVite()` |
97
+ | TanStack Router (SPA) | `reactVite()` + `tanstackRouter()` |
98
+ | TanStack Start | `reactVite()` + `tanstackRouter()` + `tanstackStart()` |
99
+ | Plain React (custom build)| `react()` |
98
100
 
99
101
  > `reactVite()` adds `eslint-plugin-react-refresh` to warn about incorrect fast-refresh patterns — use it for any Vite-based setup.
100
102
 
101
- ### NestJS projects
103
+ ### React rules
102
104
 
103
- > [!WARNING]
104
- > NestJS must disable `typescript/consistent-type-imports` — NestJS DI uses runtime class references in constructor params, and without type-aware linting this rule incorrectly converts them to `import type`, breaking DI at runtime.
105
- >
106
- > ```ts
107
- > export default defineConfig({
108
- > extends: [base(), nestjs()],
109
- > overrides: [
110
- > {
111
- > files: ['**/*.{ts,mts,cts,tsx}'],
112
- > rules: {
113
- > 'typescript/consistent-type-imports': 'off',
114
- > 'typescript/no-extraneous-class': ['error', { allowWithDecorator: true }],
115
- > },
116
- > },
117
- > ],
118
- > })
119
- > ```
105
+ The `react()` and `reactVite()` presets enable **~27 rules** covering:
106
+
107
+ - **Hooks (critical):** `rules-of-hooks`, `exhaustive-deps`
108
+ - **JSX correctness:** `jsx-key`, `jsx-no-duplicate-props`, `jsx-no-undef`, `jsx-no-target-blank`, `jsx-no-script-url`, `jsx-no-comment-textnodes`
109
+ - **JSX style:** `jsx-boolean-value`, `jsx-curly-brace-presence`, `jsx-fragments`, `jsx-pascal-case`, `self-closing-comp`, `hook-use-state`
110
+ - **Runtime safety:** `no-children-prop`, `no-danger-with-children`, `no-deprecated`, `no-direct-mutation-state`, `no-find-dom-node`, `no-is-mounted`, `no-render-return-value`, `no-string-refs`, `no-unknown-property`, `no-unsafe`, `require-render-return`, `void-dom-elements-no-children`
111
+
112
+ Modern React 17+ is assumed — `react/react-in-jsx-scope` and `react/jsx-uses-react` are off.
120
113
 
121
114
  ### TanStack Router
122
115
 
123
- The `tanstackRouter()` preset loads [`@tanstack/eslint-plugin-router`](https://www.npmjs.com/package/@tanstack/eslint-plugin-router):
116
+ The `tanstackRouter()` preset loads [`@tanstack/eslint-plugin-router`](https://www.npmjs.com/package/@tanstack/eslint-plugin-router) and enforces file naming for the `routes/` folder.
124
117
 
125
118
  ```ts
126
- import { base, tanstackRouter } from '@hooshid/ox-config/lint'
119
+ import { base, reactVite, tanstackRouter, tailwind } from '@hooshid/ox-config/lint'
127
120
  import { defineConfig } from 'oxlint'
128
121
 
129
122
  export default defineConfig({
130
- extends: [base(), tanstackRouter()],
123
+ extends: [base(), reactVite(), tanstackRouter(), tailwind()],
131
124
  })
132
125
  ```
133
126
 
134
- Covers:
135
- - `route-param-names` — validates route param placeholders match
136
- - `create-route-property-order` — enforces property ordering in `createRoute()`
127
+ **Rules provided:**
128
+
129
+ - `tanstack-router/route-param-names` — validates `$param` names between route path and params
130
+ - `tanstack-router/create-route-property-order` — enforces property order in `createRoute()`
137
131
 
138
- ### Full frontend example
132
+ **File naming convention:**
133
+
134
+ All files inside a `routes/` folder must be **kebab-case**:
135
+
136
+ | Filename | Valid? | Notes |
137
+ | --------------------------- | ------ | -------------------------------------- |
138
+ | `posts.tsx` | ✅ | |
139
+ | `posts-index.tsx` | ✅ | |
140
+ | `about-page.tsx` | ✅ | |
141
+ | `posts.$postId.tsx` | ✅ | exception: `$` dynamic params |
142
+ | `_auth.tsx` | ✅ | exception: `_` pathless routes |
143
+ | `__root.tsx` | ✅ | exception: `_` prefix |
144
+ | `posts.index.tsx` | ✅ | exception: multiple dots (file nesting)|
145
+ | `Posts.tsx` | ❌ | must be `posts.tsx` |
146
+ | `postsIndex.tsx` | ❌ | must be `posts-index.tsx` |
147
+ | `posts_index.tsx` | ❌ | must be `posts-index.tsx` |
148
+
149
+ > [!NOTE]
150
+ > Folder naming inside `routes/` is **not** covered by Oxlint (linters run file-by-file). To enforce kebab-case for folders, use a separate script or CI step.
151
+
152
+ ### TanStack Start
153
+
154
+ The `tanstackStart()` preset adds rules for **server/client boundaries**, **server function safety**, and **SSR conventions**.
155
+
156
+ > [!IMPORTANT]
157
+ > This preset does **not** include `reactVite()` or `tanstackRouter()`. Add them in the correct order:
158
+ >
159
+ > ```ts
160
+ > extends: [base(), reactVite(), tanstackRouter(), tanstackStart(), tailwind(), vitest()]
161
+ > ```
162
+
163
+ **Rules added:**
164
+
165
+ - `no-async-promise-executor`, `consistent-return`, `no-empty-function`
166
+ - `import/no-nodejs-modules` — prevents Node.js APIs from leaking into client bundles
167
+ - `no-restricted-globals` for `window`/`document`/`localStorage`/`sessionStorage` in server files
168
+
169
+ **File scope conventions:**
170
+
171
+ | File pattern | Behavior |
172
+ | --------------------------------------------------------------- | ----------------------------------------------------- |
173
+ | `**/*.server.{ts,tsx}`, `**/server/**`, `**/server-fns/**` | Node.js APIs allowed, browser globals forbidden |
174
+ | `**/*.client.{ts,tsx}`, `**/components/**` | Node.js APIs forbidden |
175
+ | `**/routes/**` | Warning on direct `fetch()` — prefer loaders |
176
+
177
+ **Example:**
139
178
 
140
179
  ```ts
141
180
  import {
@@ -144,6 +183,7 @@ import {
144
183
  depend,
145
184
  reactVite,
146
185
  tanstackRouter,
186
+ tanstackStart,
147
187
  tailwind,
148
188
  vitest,
149
189
  } from '@hooshid/ox-config/lint'
@@ -156,23 +196,25 @@ export default defineConfig({
156
196
  depend(),
157
197
  reactVite(),
158
198
  tanstackRouter(),
159
- tailwind({ entryPoint: 'src/styles/globals.css', rootFontSize: 16 }),
199
+ tanstackStart(),
200
+ tailwind({ entryPoint: 'src/styles/globals.css' }),
160
201
  vitest(),
161
202
  ],
162
203
  })
163
204
  ```
164
205
 
165
- ### Full backend example
206
+ ### NestJS
207
+
208
+ > [!WARNING]
209
+ > NestJS must disable `typescript/consistent-type-imports` — NestJS DI uses runtime class references in constructor params, and without type-aware linting this rule incorrectly converts them to `import type`, breaking DI at runtime.
166
210
 
167
211
  ```ts
168
- import { base, unicorn, depend, node, promise, nestjs, drizzle, vitest } from '@hooshid/ox-config/lint'
212
+ import { base, node, promise, nestjs, drizzle, vitest } from '@hooshid/ox-config/lint'
169
213
  import { defineConfig } from 'oxlint'
170
214
 
171
215
  export default defineConfig({
172
216
  extends: [
173
217
  base(),
174
- unicorn(),
175
- depend(),
176
218
  node(),
177
219
  promise(),
178
220
  nestjs(),
@@ -223,10 +265,10 @@ Each package's own `tsconfig.json` is auto-detected by oxlint — no extra confi
223
265
 
224
266
  #### Do I still need a separate `tsc --noEmit` step?
225
267
 
226
- Short answer: **yes, keep it.** With `typeCheck` enabled, oxlint already surfaces tsc diagnostics for the files it lints, so during local development you'll usually catch type errors from `lint` alone. But a dedicated `typecheck` script is still worth keeping because:
268
+ **Yes, keep it.** With `typeCheck` enabled, `oxlint` already surfaces tsc diagnostics for the files it lints, so during local development you'll usually catch type errors from `lint` alone. But a dedicated `typecheck` script is still worth keeping because:
227
269
 
228
- - **Different file scope.** `tsc --noEmit` honors the tsconfig's `include` / `exclude`. `oxlint` walks the filesystem by its own rules and honors `ignorePatterns`. The two sets overlap but are not identical — a file covered by tsconfig but excluded from lint (or vice versa) will only be checked by one of them.
229
- - **Project-level diagnostics.** tsc catches errors that aren't attached to a single source file: `tsconfig.json` misconfiguration (`TS5xxx`), broken project `references`, `paths` alias typos. Per-file type-aware linting can't see these.
270
+ - **Different file scope.** `tsc --noEmit` honors the tsconfig's `include`/`exclude`. `oxlint` walks the filesystem by its own rules and honors `ignorePatterns`. The two sets overlap but are not identical.
271
+ - **Project-level diagnostics.** tsc catches errors that aren't attached to a single source file: `tsconfig.json` misconfiguration (`TS5xxx`), broken project `references`, `paths` alias typos.
230
272
  - **Clearer CI failures.** Running `typecheck` and `lint` as separate steps makes it obvious whether a red build is a type error or a lint rule violation.
231
273
 
232
274
  ### Monorepo (nested configs)
@@ -235,8 +277,6 @@ Oxlint supports [nested configuration](https://oxc.rs/docs/guide/usage/linter/ne
235
277
 
236
278
  #### Root config
237
279
 
238
- Keep shared baseline and `typeAware()` at the root:
239
-
240
280
  ```ts
241
281
  // oxlint.config.ts (root)
242
282
  import { base, typeAware, unicorn, depend } from '@hooshid/ox-config/lint'
@@ -252,11 +292,11 @@ export default defineConfig({
252
292
  ```ts
253
293
  // packages/web/oxlint.config.ts
254
294
  import rootConfig from '../../oxlint.config.ts'
255
- import { reactVite, tanstackRouter, vitest, tailwind } from '@hooshid/ox-config/lint'
295
+ import { reactVite, tanstackRouter, tanstackStart, vitest, tailwind } from '@hooshid/ox-config/lint'
256
296
  import { defineConfig } from 'oxlint'
257
297
 
258
298
  export default defineConfig({
259
- extends: [rootConfig, reactVite(), tanstackRouter(), vitest(), tailwind()],
299
+ extends: [rootConfig, reactVite(), tanstackRouter(), tanstackStart(), vitest(), tailwind()],
260
300
  })
261
301
  ```
262
302
 
@@ -272,7 +312,7 @@ export default defineConfig({
272
312
  ```
273
313
 
274
314
  > [!TIP]
275
- > Packages without their own `oxlint.config.ts` automatically use the root config — no setup needed for packages that only need the shared baseline.
315
+ > Packages without their own `oxlint.config.ts` automatically use the root config.
276
316
 
277
317
  > [!WARNING]
278
318
  > Passing `-c` or `--config` explicitly on the CLI **disables** nested config lookup. Let oxlint auto-detect configs by running without `-c`.
@@ -300,6 +340,7 @@ export default defineConfig({ ...format() })
300
340
  | `endOfLine` | `lf` |
301
341
  | Import sorting | Grouped with newlines |
302
342
  | Package.json sorting | Enabled |
343
+ | Ignore patterns | Build outputs, lockfiles, generated files |
303
344
 
304
345
  ### Override
305
346
 
@@ -359,6 +400,51 @@ Most modern editors support EditorConfig natively or via a plugin. This ensures
359
400
  }
360
401
  ```
361
402
 
403
+ ## Full-stack example (TanStack Start + NestJS)
404
+
405
+ ```ts
406
+ // apps/web/oxlint.config.ts
407
+ import rootConfig from '../../oxlint.config.ts'
408
+ import { reactVite, tanstackRouter, tanstackStart, tailwind, vitest } from '@hooshid/ox-config/lint'
409
+ import { defineConfig } from 'oxlint'
410
+
411
+ export default defineConfig({
412
+ extends: [
413
+ rootConfig,
414
+ reactVite(),
415
+ tanstackRouter(),
416
+ tanstackStart(),
417
+ tailwind(),
418
+ vitest(),
419
+ ],
420
+ })
421
+ ```
422
+
423
+ ```ts
424
+ // apps/api/oxlint.config.ts
425
+ import rootConfig from '../../oxlint.config.ts'
426
+ import { node, promise, nestjs, drizzle, vitest } from '@hooshid/ox-config/lint'
427
+ import { defineConfig } from 'oxlint'
428
+
429
+ export default defineConfig({
430
+ extends: [rootConfig, node(), promise(), nestjs(), drizzle(), vitest()],
431
+ overrides: [
432
+ {
433
+ files: ['**/*.{ts,mts,cts,tsx}'],
434
+ rules: {
435
+ 'typescript/consistent-type-imports': 'off',
436
+ 'typescript/no-extraneous-class': ['error', { allowWithDecorator: true }],
437
+ },
438
+ },
439
+ ],
440
+ })
441
+ ```
442
+
362
443
  ## License
363
444
 
364
- MIT
445
+ MIT
446
+
447
+ ## Sources
448
+
449
+ 1. [Oxlint: Writing JS Plugins](https://oxc.rs/docs/guide/usage/linter/writing-js-plugins.html)
450
+ 3. [infra-code source](https://github.com/oNo500/infra-code/tree/master/packages/code-quality)
package/dist/lint.d.mts CHANGED
@@ -34,17 +34,32 @@ export declare function depend(overrides?: Partial<OxlintConfig>): OxlintConfig;
34
34
  export declare function node(overrides?: Partial<OxlintConfig>): OxlintConfig;
35
35
  /** Promise lint preset — native promise plugin. */
36
36
  export declare function promise(overrides?: Partial<OxlintConfig>): OxlintConfig;
37
- /** React lint preset — enables native react + react-hooks plugin. */
37
+ /** React lint preset — core React + Hooks rules. */
38
38
  export declare function react(overrides?: Partial<OxlintConfig>): OxlintConfig;
39
- /** React + react-refresh preset (for Vite projects). Use instead of `react`. */
39
+ /** React + react-refresh preset (for Vite, TanStack Start, etc.). */
40
40
  export declare function reactVite(overrides?: Partial<OxlintConfig>): OxlintConfig;
41
41
  /** Next.js lint preset — enables native nextjs plugin. */
42
42
  export declare function nextjs(overrides?: Partial<OxlintConfig>): OxlintConfig;
43
43
  /**
44
- * TanStack Router lint preset — loads @tanstack/eslint-plugin-router.
45
- * Covers route-param-names and create-route-property-order.
44
+ * TanStack Router lint preset.
45
+ *
46
+ * Loads @tanstack/eslint-plugin-router and applies conventions specific
47
+ * to file-based routing setups.
48
+ *
49
+ * Rules provided by the plugin:
50
+ * - `route-param-names` — validates `$param` names match between route path and params
51
+ * - `create-route-property-order` — enforces consistent property order in `createRoute()`
46
52
  */
47
53
  export declare function tanstackRouter(overrides?: Partial<OxlintConfig>): OxlintConfig;
54
+ /**
55
+ * TanStack Start lint preset.
56
+ *
57
+ * Adds rules for server functions, client/server boundaries, and Start
58
+ * conventions. This preset assumes `reactVite()` and `tanstackRouter()`
59
+ * are already in the `extends` array.
60
+ *
61
+ */
62
+ export declare function tanstackStart(overrides?: Partial<OxlintConfig>): OxlintConfig;
48
63
  /** Accessibility lint preset — enables native jsx-a11y plugin. */
49
64
  export declare function a11y(overrides?: Partial<OxlintConfig>): OxlintConfig;
50
65
  /** JSDoc lint preset — enables native jsdoc plugin. */
@@ -1 +1 @@
1
- {"version":3,"file":"lint.d.mts","names":[],"sources":["../src/utils.ts","../src/lint.ts"],"mappings":";;;qBAgDa;;qBAGA;;qBAGA;;qBAGA;;qBAGA;;qBAMA;;qBAGA;;;;;;;wBCsCG,KAAK,YAAY,QAAQ,gBAAgB;;;;;wBAuHzC,UAAU,YAAY,QAAQ,gBAAgB;;wBAa9C,QAAQ,YAAY,QAAQ,gBAAgB;;wBA6B5C,OAAO,YAAY,QAAQ,gBAAgB;;wBAwB3C,KAAK,YAAY,QAAQ,gBAAgB;;wBAKzC,QAAQ,YAAY,QAAQ,gBAAgB;;wBAkB5C,MAAM,YAAY,QAAQ,gBAAgB;;wBAe1C,UAAU,YAAY,QAAQ,gBAAgB;;wBAe9C,OAAO,YAAY,QAAQ,gBAAgB;;;;;wBAQ3C,eAAe,YAAY,QAAQ,gBAAgB;;wBAoBnD,KAAK,YAAY,QAAQ,gBAAgB;;wBAKzC,MAAM,YAAY,QAAQ,gBAAgB;UAQhD,sBAAsB,QAAQ;;EAEtC;;;wBAIc,OAAO,UAAU,gBAAgB;UA0CvC,wBAAwB,QAAQ;EACxC;EACA;;EAEA;;;wBAIc,SAAS,UAAS,kBAAuB;;;;;wBA6BzC,OAAO,YAAY,QAAQ,gBAAgB;;wBA+B3C,QAAQ,YAAY,QAAQ,gBAAgB"}
1
+ {"version":3,"file":"lint.d.mts","names":[],"sources":["../src/utils.ts","../src/lint.ts"],"mappings":";;;qBAgDa;;qBAGA;;qBAGA;;qBAGA;;qBAGA;;qBAMA;;qBAGA;;;;;;;wBCsCG,KAAK,YAAY,QAAQ,gBAAgB;;;;;wBAuHzC,UAAU,YAAY,QAAQ,gBAAgB;;wBAa9C,QAAQ,YAAY,QAAQ,gBAAgB;;wBA6B5C,OAAO,YAAY,QAAQ,gBAAgB;;wBAwB3C,KAAK,YAAY,QAAQ,gBAAgB;;wBAKzC,QAAQ,YAAY,QAAQ,gBAAgB;;wBAqD5C,MAAM,YAAY,QAAQ,gBAAgB;;wBAW1C,UAAU,YAAY,QAAQ,gBAAgB;;wBAe9C,OAAO,YAAY,QAAQ,gBAAgB;;;;;;;;;;;wBAc3C,eAAe,YAAY,QAAQ,gBAAgB;;;;;;;;;wBAwEnD,cAAc,YAAY,QAAQ,gBAAgB;;wBAkGlD,KAAK,YAAY,QAAQ,gBAAgB;;wBAKzC,MAAM,YAAY,QAAQ,gBAAgB;UAQhD,sBAAsB,QAAQ;;EAEtC;;;wBAIc,OAAO,UAAU,gBAAgB;UA0CvC,wBAAwB,QAAQ;EACxC;EACA;;EAEA;;;wBAIc,SAAS,UAAS,kBAAuB;;;;;wBA6BzC,OAAO,YAAY,QAAQ,gBAAgB;;wBA+B3C,QAAQ,YAAY,QAAQ,gBAAgB"}
package/dist/lint.mjs CHANGED
@@ -261,32 +261,62 @@ function node(overrides) {
261
261
  function promise(overrides) {
262
262
  return preset({ plugins: ["promise"] }, overrides);
263
263
  }
264
- const reactStyleRules = {
265
- "react/jsx-pascal-case": "error",
266
- "react/jsx-boolean-value": "error",
267
- "react/jsx-curly-brace-presence": "error",
268
- "react/jsx-fragments": "error",
269
- "react/self-closing-comp": "error",
270
- "react/hook-use-state": "error"
264
+ const reactRules = {
265
+ "react/rules-of-hooks": "error",
266
+ "react/exhaustive-deps": "warn",
267
+ "react/jsx-key": "error",
268
+ "react/jsx-no-duplicate-props": "error",
269
+ "react/jsx-no-undef": "error",
270
+ "react/jsx-uses-vars": "error",
271
+ "react/jsx-no-target-blank": ["error", { allowReferrer: false }],
272
+ "react/jsx-no-comment-textnodes": "error",
273
+ "react/jsx-no-script-url": "error",
274
+ "react/jsx-boolean-value": ["error", "never"],
275
+ "react/jsx-curly-brace-presence": ["error", {
276
+ props: "never",
277
+ children: "never"
278
+ }],
279
+ "react/jsx-fragments": ["error", "syntax"],
280
+ "react/jsx-pascal-case": ["error", {
281
+ allowAllCaps: false,
282
+ allowNamespace: true
283
+ }],
284
+ "react/self-closing-comp": ["error", {
285
+ component: true,
286
+ html: true
287
+ }],
288
+ "react/hook-use-state": "error",
289
+ "react/no-children-prop": "error",
290
+ "react/no-danger-with-children": "error",
291
+ "react/no-deprecated": "error",
292
+ "react/no-direct-mutation-state": "error",
293
+ "react/no-find-dom-node": "error",
294
+ "react/no-is-mounted": "error",
295
+ "react/no-render-return-value": "error",
296
+ "react/no-string-refs": "error",
297
+ "react/no-unknown-property": "error",
298
+ "react/no-unsafe": "error",
299
+ "react/require-render-return": "error",
300
+ "react/void-dom-elements-no-children": "error",
301
+ "react/react-in-jsx-scope": "off",
302
+ "react/jsx-uses-react": "off",
303
+ "react/no-unescaped-entities": "off"
271
304
  };
272
- /** React lint preset — enables native react + react-hooks plugin. */
305
+ /** React lint preset — core React + Hooks rules. */
273
306
  function react(overrides) {
274
307
  return preset({
275
308
  plugins: ["react"],
276
- rules: {
277
- "react/react-in-jsx-scope": "off",
278
- ...reactStyleRules
279
- }
309
+ rules: reactRules
280
310
  }, overrides);
281
311
  }
282
- /** React + react-refresh preset (for Vite projects). Use instead of `react`. */
312
+ /** React + react-refresh preset (for Vite, TanStack Start, etc.). */
283
313
  function reactVite(overrides) {
284
314
  return preset({
285
315
  plugins: ["react"],
286
316
  jsPlugins: resolvePlugins(["eslint-plugin-react-refresh"]),
287
317
  rules: {
288
- "react/react-in-jsx-scope": "off",
289
- ...reactStyleRules
318
+ ...reactRules,
319
+ "react-refresh/only-export-components": ["warn", { allowConstantExport: true }]
290
320
  }
291
321
  }, overrides);
292
322
  }
@@ -295,8 +325,14 @@ function nextjs(overrides) {
295
325
  return preset({ plugins: ["nextjs"] }, overrides);
296
326
  }
297
327
  /**
298
- * TanStack Router lint preset — loads @tanstack/eslint-plugin-router.
299
- * Covers route-param-names and create-route-property-order.
328
+ * TanStack Router lint preset.
329
+ *
330
+ * Loads @tanstack/eslint-plugin-router and applies conventions specific
331
+ * to file-based routing setups.
332
+ *
333
+ * Rules provided by the plugin:
334
+ * - `route-param-names` — validates `$param` names match between route path and params
335
+ * - `create-route-property-order` — enforces consistent property order in `createRoute()`
300
336
  */
301
337
  function tanstackRouter(overrides) {
302
338
  return preset({
@@ -306,8 +342,115 @@ function tanstackRouter(overrides) {
306
342
  }]),
307
343
  rules: {
308
344
  "tanstack-router/route-param-names": "error",
309
- "tanstack-router/create-route-property-order": "error"
310
- }
345
+ "tanstack-router/create-route-property-order": "error",
346
+ "import/no-default-export": "off"
347
+ },
348
+ overrides: [
349
+ {
350
+ files: ["**/routes/**/*.{ts,tsx}"],
351
+ rules: { "no-restricted-globals": ["error", {
352
+ name: "window",
353
+ message: "Use useRouter() or useNavigate() instead of window in route files."
354
+ }] }
355
+ },
356
+ {
357
+ files: ["**/routes/**/*.{ts,tsx}"],
358
+ plugins: ["unicorn"],
359
+ rules: { "unicorn/filename-case": ["error", {
360
+ case: "kebabCase",
361
+ ignore: [
362
+ "\\$",
363
+ "^_",
364
+ "\\."
365
+ ]
366
+ }] }
367
+ },
368
+ {
369
+ files: ["**/routes/__root.tsx"],
370
+ rules: { "no-restricted-globals": "off" }
371
+ }
372
+ ]
373
+ }, overrides);
374
+ }
375
+ /**
376
+ * TanStack Start lint preset.
377
+ *
378
+ * Adds rules for server functions, client/server boundaries, and Start
379
+ * conventions. This preset assumes `reactVite()` and `tanstackRouter()`
380
+ * are already in the `extends` array.
381
+ *
382
+ */
383
+ function tanstackStart(overrides) {
384
+ return preset({
385
+ rules: {
386
+ "no-async-promise-executor": "error",
387
+ "no-await-in-loop": "off",
388
+ "import/no-nodejs-modules": "error",
389
+ "consistent-return": "error",
390
+ "no-empty-function": "warn"
391
+ },
392
+ overrides: [
393
+ {
394
+ files: [
395
+ "**/*.server.{ts,tsx}",
396
+ "**/server/**/*.{ts,tsx}",
397
+ "**/server-fns/**/*.{ts,tsx}"
398
+ ],
399
+ rules: {
400
+ "import/no-nodejs-modules": "off",
401
+ "no-console": "off"
402
+ }
403
+ },
404
+ {
405
+ files: ["**/*.client.{ts,tsx}", "**/components/**/*.{ts,tsx}"],
406
+ rules: { "import/no-nodejs-modules": "error" }
407
+ },
408
+ {
409
+ files: ["**/routes/**/*.{ts,tsx}"],
410
+ rules: { "no-restricted-syntax": ["warn", {
411
+ selector: "CallExpression[callee.name=\"fetch\"]",
412
+ message: "Prefer a loader or server function over direct fetch in route files."
413
+ }] }
414
+ },
415
+ {
416
+ files: ["**/*.server.{ts,tsx}", "**/*.client.{ts,tsx}"],
417
+ plugins: ["unicorn"],
418
+ rules: { "unicorn/filename-case": ["error", {
419
+ case: "kebabCase",
420
+ ignore: ["\\."]
421
+ }] }
422
+ },
423
+ {
424
+ files: [
425
+ "**/*.server.{ts,tsx}",
426
+ "**/server/**/*.{ts,tsx}",
427
+ "**/server-fns/**/*.{ts,tsx}"
428
+ ],
429
+ rules: {
430
+ "import/no-nodejs-modules": "off",
431
+ "no-console": "off",
432
+ "no-restricted-globals": [
433
+ "error",
434
+ {
435
+ name: "window",
436
+ message: "Not available in server context. Use a server function or guard with typeof window."
437
+ },
438
+ {
439
+ name: "document",
440
+ message: "Not available in server context."
441
+ },
442
+ {
443
+ name: "localStorage",
444
+ message: "Not available in server context."
445
+ },
446
+ {
447
+ name: "sessionStorage",
448
+ message: "Not available in server context."
449
+ }
450
+ ]
451
+ }
452
+ }
453
+ ]
311
454
  }, overrides);
312
455
  }
313
456
  /** Accessibility lint preset — enables native jsx-a11y plugin. */
@@ -410,6 +553,6 @@ function drizzle(overrides) {
410
553
  }, overrides);
411
554
  }
412
555
  //#endregion
413
- export { GLOB_JS, GLOB_JSON, GLOB_JSX, GLOB_MARKDOWN, GLOB_SRC, GLOB_TESTS, GLOB_TS, a11y, base, defineConfig, depend, drizzle, jsdoc, nestjs, nextjs, node, promise, react, reactVite, tailwind, tanstackRouter, typeAware, unicorn, vitest };
556
+ export { GLOB_JS, GLOB_JSON, GLOB_JSX, GLOB_MARKDOWN, GLOB_SRC, GLOB_TESTS, GLOB_TS, a11y, base, defineConfig, depend, drizzle, jsdoc, nestjs, nextjs, node, promise, react, reactVite, tailwind, tanstackRouter, tanstackStart, typeAware, unicorn, vitest };
414
557
 
415
558
  //# sourceMappingURL=lint.mjs.map
package/dist/lint.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"lint.mjs","names":["defineConfig"],"sources":["../src/utils.ts","../src/lint.ts"],"sourcesContent":["/**\n * Utility functions and constants\n */\n\n// ============================================================================\n// Environment detection\n// ============================================================================\n\nconst env = process.env\n\nfunction isCI(): boolean {\n return !!(\n env['CI'] ||\n env['CONTINUOUS_INTEGRATION'] ||\n env['BUILD_ID'] ||\n env['BUILD_NUMBER'] ||\n env['RUN_ID']\n )\n}\n\nfunction isInGitHooksOrLintStaged(): boolean {\n return (\n !!(env['GIT_PARAMS'] || env['VSCODE_GIT_COMMAND']) ||\n env['npm_lifecycle_script']?.startsWith('lint-staged') === true\n )\n}\n\n/**\n * Detects whether running in an editor environment.\n * Returns false in CI, Git Hooks, or lint-staged.\n */\nexport function isInEditorEnv(): boolean {\n if (isCI()) return false\n if (isInGitHooksOrLintStaged()) return false\n return !!(\n env['VSCODE_PID'] ||\n env['VSCODE_CWD'] ||\n env['JETBRAINS_IDE'] ||\n env['VIM'] ||\n env['NVIM']\n )\n}\n\n// ============================================================================\n// File matching patterns (Globs)\n// ============================================================================\n\n/** All JS/TS source files */\nexport const GLOB_SRC = '**/*.{js,mjs,cjs,jsx,ts,mts,cts,tsx}'\n\n/** JavaScript files only */\nexport const GLOB_JS = '**/*.{js,mjs,cjs,jsx}'\n\n/** TypeScript files only */\nexport const GLOB_TS = '**/*.{ts,mts,cts,tsx}'\n\n/** JSX/TSX files (React-related) */\nexport const GLOB_JSX = '**/*.{jsx,tsx}'\n\n/** Test files */\nexport const GLOB_TESTS: string[] = [\n '**/*.{test,spec}.{js,mjs,cjs,jsx,ts,mts,cts,tsx}',\n '**/__tests__/**/*.{js,mjs,cjs,jsx,ts,mts,cts,tsx}',\n]\n\n/** JSON files */\nexport const GLOB_JSON = '**/*.json'\n\n/** Markdown files */\nexport const GLOB_MARKDOWN = '**/*.md'\n","/**\n * Oxlint lint presets.\n *\n * Every preset is a function that accepts optional overrides, merged via `defu`.\n * User overrides take priority over preset defaults.\n *\n * @example\n * ```ts\n * // oxlint.config.ts\n * import { base, unicorn, react, tailwind, vitest } from '@hooshid/ox-config/lint'\n * import { defineConfig } from 'oxlint'\n *\n * export default defineConfig({\n * extends: [base(), unicorn(), react(), tailwind(), vitest()],\n * })\n * ```\n */\nimport { existsSync, readFileSync } from 'node:fs'\nimport { createRequire } from 'node:module'\nimport path from 'node:path'\n\nimport { defu } from 'defu'\nimport { defineConfig } from 'oxlint'\n\nimport { GLOB_JSX, GLOB_SRC, GLOB_TESTS, GLOB_TS, isInEditorEnv } from './utils'\n\nimport type { ExternalPluginEntry, OxlintConfig } from 'oxlint'\n\nconst require = createRequire(import.meta.url)\n\n// ============================================================================\n// Ignore patterns\n// ============================================================================\n\nconst DEFAULT_IGNORES: string[] = [\n '**/node_modules/**',\n '**/dist/**',\n '**/build/**',\n '**/out/**',\n '**/.next/**',\n '**/.cache/**',\n '**/.turbo/**',\n '**/.output/**',\n '**/.nitro/**',\n '**/.tanstack/**',\n '**/.vinxi/**',\n '**/.git/**',\n '**/.svn/**',\n '**/.hg/**',\n '**/.pnp.*',\n '**/public/**',\n '**/*.d.ts',\n]\n\nfunction loadGitignorePatterns(): string[] {\n const gitignoreFile = path.resolve(process.cwd(), '.gitignore')\n if (!existsSync(gitignoreFile)) return []\n\n return readFileSync(gitignoreFile, 'utf8')\n .split(/\\r?\\n/u)\n .map((line) => line.trim())\n .filter((line) => line && !line.startsWith('#'))\n .map((pattern) => {\n let p = pattern.trimEnd()\n if (p.startsWith('/')) p = p.slice(1)\n if (!p.includes('/') && !p.includes('*')) p = `**/${p}`\n if (p.endsWith('/')) p = `${p}**`\n return p\n })\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nfunction preset(defaults: OxlintConfig, overrides?: Partial<OxlintConfig>): OxlintConfig {\n return defineConfig(defu(overrides ?? {}, defaults))\n}\n\n/**\n * Resolve a jsPlugin package name to its absolute path.\n * This allows oxlint to load plugins directly without relying on\n * Node module resolution from the consumer's CWD — fixes pnpm strict mode.\n */\nfunction resolvePlugin(name: string): string {\n try {\n return require.resolve(name)\n } catch {\n return name\n }\n}\n\nfunction resolvePlugins(plugins: ExternalPluginEntry[]): ExternalPluginEntry[] {\n return plugins.map((p) => {\n if (typeof p === 'string') return resolvePlugin(p)\n return { ...p, specifier: resolvePlugin(p.specifier) }\n })\n}\n\n// ============================================================================\n// Core\n// ============================================================================\n\n/**\n * Base lint preset — TypeScript + Import plugins, categories, env, ignores.\n * Always include first.\n */\nexport function base(overrides?: Partial<OxlintConfig>): OxlintConfig {\n return preset(\n {\n plugins: ['typescript', 'import'],\n categories: {\n correctness: 'error',\n suspicious: 'error',\n perf: 'error',\n pedantic: 'warn',\n },\n rules: {\n // Shape-only check; necessary in interactive CLI and sequential workflows.\n 'no-await-in-loop': 'off',\n // High-noise; readonly intent better expressed via `const generics` or call-site.\n 'typescript/prefer-readonly-parameter-types': 'off',\n // Turns `if (str)` into ceremony for marginal safety gain.\n 'typescript/strict-boolean-expressions': 'off',\n // File/function size is a reviewer call, not a lint rule.\n 'max-lines': 'off',\n 'max-lines-per-function': 'off',\n // Misfires on `/* @__PURE__ */` and similar bundler annotations.\n 'no-inline-comments': 'off',\n // TODO/FIXME triage belongs in the issue tracker.\n 'no-warning-comments': 'off',\n // Default cap of 10 is too tight for modern React/Next component files.\n 'import/max-dependencies': 'off',\n // Modern React renders apostrophes correctly; legacy noise.\n 'react/no-unescaped-entities': 'off',\n // Misfires on Next.js Server Actions and placeholder async functions.\n 'require-await': 'off',\n },\n env: {\n browser: true,\n node: true,\n es2026: true,\n builtin: true,\n },\n ignorePatterns: [...DEFAULT_IGNORES, ...loadGitignorePatterns()],\n overrides: [\n {\n files: [GLOB_TS],\n rules: {\n // Only list rules that DIFFER from categories defaults\n 'typescript/consistent-type-definitions': 'off',\n 'typescript/consistent-type-imports': 'error',\n 'no-unused-vars': 'off',\n 'typescript/array-type': 'error',\n 'typescript/consistent-generic-constructors': 'error',\n 'typescript/consistent-indexed-object-style': 'error',\n 'typescript/consistent-type-assertions': 'error',\n 'typescript/ban-tslint-comment': 'error',\n 'typescript/no-empty-interface': 'error',\n 'typescript/no-inferrable-types': 'error',\n 'typescript/prefer-for-of': 'error',\n 'typescript/prefer-function-type': 'error',\n 'typescript/unified-signatures': 'error',\n },\n },\n {\n files: [GLOB_SRC],\n rules: {\n // CSS/style side-effect imports are standard in all frontend frameworks\n 'import/no-unassigned-import': 'off',\n 'import/no-relative-parent-imports': 'error',\n 'import/first': 'error',\n 'import/no-duplicates': 'error',\n 'import/consistent-type-specifier-style': 'error',\n 'import/no-mutable-exports': 'error',\n 'import/no-named-default': 'error',\n },\n },\n {\n // Config files commonly import shared roots via `../../config.ts`\n // in monorepos — intended pattern, not a smell.\n files: ['**/*.config.{ts,mts,cts,js,mjs,cjs}'],\n rules: {\n 'import/no-relative-parent-imports': 'off',\n },\n },\n {\n // Test files use mock setup patterns (vi.mock/vi.hoisted before imports),\n // explicit mock signatures, and fixture data that\n // legitimately violate strict style/safety rules.\n files: GLOB_TESTS,\n rules: {\n // Mock setup pattern breaks standard import ordering\n 'import/first': 'off',\n 'import/no-duplicates': 'off',\n 'import/consistent-type-specifier-style': 'off',\n // Mock signatures need explicit values / async without await\n 'unicorn/no-useless-undefined': 'off',\n 'typescript/no-empty-function': 'off',\n // Modernization hints aren't useful in tests\n 'unicorn/prefer-string-replace-all': 'off',\n 'unicorn/no-array-callback-reference': 'off',\n 'unicorn/prefer-spread': 'off',\n // Tests deliberately use non-null assertions, magic numbers, any\n 'typescript/no-non-null-assertion': 'off',\n 'no-magic-numbers': 'off',\n 'typescript/no-explicit-any': 'off',\n 'typescript/no-unsafe-assignment': 'off',\n 'typescript/no-unsafe-call': 'off',\n 'typescript/no-unsafe-member-access': 'off',\n 'typescript/no-unsafe-return': 'off',\n 'typescript/no-unsafe-argument': 'off',\n // Index keys are fine when rendering fixture lists\n 'react/no-array-index-key': 'off',\n },\n },\n ],\n },\n overrides,\n )\n}\n\n/**\n * Type-aware lint preset — enables 59 type-aware rules via tsgolint + type checking.\n * Requires TypeScript 7.0+ and `oxlint-tsgolint` (bundled as dependency).\n */\nexport function typeAware(overrides?: Partial<OxlintConfig>): OxlintConfig {\n return preset(\n {\n options: {\n typeAware: true,\n typeCheck: true,\n },\n },\n overrides,\n )\n}\n\n/** Unicorn lint preset — 100+ code quality rules. */\nexport function unicorn(overrides?: Partial<OxlintConfig>): OxlintConfig {\n return preset(\n {\n plugins: ['unicorn'],\n rules: {\n 'unicorn/no-null': 'off',\n 'unicorn/filename-case': ['error', { case: 'kebabCase' }],\n 'unicorn/catch-error-name': 'error',\n 'unicorn/error-message': 'error',\n 'unicorn/prefer-optional-catch-binding': 'error',\n 'unicorn/no-zero-fractions': 'error',\n 'unicorn/number-literal-case': 'error',\n 'unicorn/numeric-separators-style': 'error',\n 'unicorn/prefer-includes': 'error',\n 'unicorn/prefer-spread': 'error',\n 'unicorn/prefer-ternary': 'error',\n 'unicorn/prefer-string-trim-start-end': 'error',\n 'unicorn/prefer-structured-clone': 'error',\n 'unicorn/prefer-default-parameters': 'error',\n 'unicorn/no-console-spaces': 'error',\n 'unicorn/throw-new-error': 'error',\n 'unicorn/require-array-join-separator': 'error',\n },\n },\n overrides,\n )\n}\n\n/** Dependency optimization — flags packages replaceable with native APIs. */\nexport function depend(overrides?: Partial<OxlintConfig>): OxlintConfig {\n return preset(\n {\n jsPlugins: resolvePlugins(['eslint-plugin-depend']),\n rules: {\n 'depend/ban-dependencies': [\n 'error',\n {\n presets: ['native', 'microutilities', 'preferred'],\n modules: [],\n allowed: ['dotenv'],\n },\n ],\n },\n },\n overrides,\n )\n}\n\n// ============================================================================\n// Runtime environments\n// ============================================================================\n\n/** Node.js lint preset — native node plugin. */\nexport function node(overrides?: Partial<OxlintConfig>): OxlintConfig {\n return preset({ plugins: ['node'] }, overrides)\n}\n\n/** Promise lint preset — native promise plugin. */\nexport function promise(overrides?: Partial<OxlintConfig>): OxlintConfig {\n return preset({ plugins: ['promise'] }, overrides)\n}\n\n// ============================================================================\n// Frontend\n// ============================================================================\n\nconst reactStyleRules = {\n 'react/jsx-pascal-case': 'error',\n 'react/jsx-boolean-value': 'error',\n 'react/jsx-curly-brace-presence': 'error',\n 'react/jsx-fragments': 'error',\n 'react/self-closing-comp': 'error',\n 'react/hook-use-state': 'error',\n} as const\n\n/** React lint preset — enables native react + react-hooks plugin. */\nexport function react(overrides?: Partial<OxlintConfig>): OxlintConfig {\n return preset(\n {\n plugins: ['react'],\n rules: {\n // Automatic JSX runtime (React 17+) does not require explicit React import\n 'react/react-in-jsx-scope': 'off',\n ...reactStyleRules,\n },\n },\n overrides,\n )\n}\n\n/** React + react-refresh preset (for Vite projects). Use instead of `react`. */\nexport function reactVite(overrides?: Partial<OxlintConfig>): OxlintConfig {\n return preset(\n {\n plugins: ['react'],\n jsPlugins: resolvePlugins(['eslint-plugin-react-refresh']),\n rules: {\n 'react/react-in-jsx-scope': 'off',\n ...reactStyleRules,\n },\n },\n overrides,\n )\n}\n\n/** Next.js lint preset — enables native nextjs plugin. */\nexport function nextjs(overrides?: Partial<OxlintConfig>): OxlintConfig {\n return preset({ plugins: ['nextjs'] }, overrides)\n}\n\n/**\n * TanStack Router lint preset — loads @tanstack/eslint-plugin-router.\n * Covers route-param-names and create-route-property-order.\n */\nexport function tanstackRouter(overrides?: Partial<OxlintConfig>): OxlintConfig {\n return preset(\n {\n jsPlugins: resolvePlugins([\n { name: 'tanstack-router', specifier: '@tanstack/eslint-plugin-router' },\n ]),\n rules: {\n 'tanstack-router/route-param-names': 'error',\n 'tanstack-router/create-route-property-order': 'error',\n },\n },\n overrides,\n )\n}\n\n// ============================================================================\n// Quality\n// ============================================================================\n\n/** Accessibility lint preset — enables native jsx-a11y plugin. */\nexport function a11y(overrides?: Partial<OxlintConfig>): OxlintConfig {\n return preset({ plugins: ['jsx-a11y'] }, overrides)\n}\n\n/** JSDoc lint preset — enables native jsdoc plugin. */\nexport function jsdoc(overrides?: Partial<OxlintConfig>): OxlintConfig {\n return preset({ plugins: ['jsdoc'] }, overrides)\n}\n\n// ============================================================================\n// Testing\n// ============================================================================\n\ninterface VitestOptions extends Partial<OxlintConfig> {\n /** Test file glob patterns. Replaces the default GLOB_TESTS. */\n files?: string[]\n}\n\n/** Vitest lint preset — native vitest plugin with test-file scoping. */\nexport function vitest(options?: VitestOptions): OxlintConfig {\n const { files, ...overrides } = options ?? {}\n\n return preset(\n {\n plugins: ['vitest'],\n settings: { vitest: { typecheck: true } },\n overrides: [\n {\n files: files ?? GLOB_TESTS,\n rules: {\n 'vitest/expect-expect': 'error',\n 'vitest/no-conditional-expect': 'error',\n 'vitest/no-identical-title': 'error',\n 'vitest/no-import-node-test': 'error',\n 'vitest/no-interpolation-in-snapshots': 'error',\n 'vitest/no-mocks-import': 'error',\n 'vitest/no-standalone-expect': 'error',\n 'vitest/valid-describe-callback': 'error',\n 'vitest/valid-expect': 'error',\n 'vitest/valid-title': 'error',\n 'vitest/consistent-test-it': ['error', { fn: 'it', withinDescribe: 'it' }],\n 'vitest/prefer-hooks-in-order': 'error',\n 'vitest/prefer-lowercase-title': 'error',\n 'vitest/no-disabled-tests': isInEditorEnv() ? 'warn' : 'error',\n 'vitest/no-focused-tests': isInEditorEnv() ? 'warn' : 'error',\n 'vitest/require-mock-type-parameters': 'off',\n 'no-console': 'off',\n 'unicorn/no-null': 'off',\n 'typescript/ban-ts-comment': 'off',\n },\n },\n ],\n },\n overrides,\n )\n}\n\n// ============================================================================\n// Tailwind\n// ============================================================================\n\ninterface TailwindOptions extends Partial<OxlintConfig> {\n entryPoint?: string\n rootFontSize?: number\n /** File glob patterns for tailwind rules. @default GLOB_JSX */\n files?: string[]\n}\n\n/** Tailwind CSS lint preset — eslint-plugin-better-tailwindcss. */\nexport function tailwind(options: TailwindOptions = {}): OxlintConfig {\n const { entryPoint = 'src/styles/globals.css', rootFontSize = 16, files, ...overrides } = options\n\n return preset(\n {\n jsPlugins: resolvePlugins(['eslint-plugin-better-tailwindcss']),\n settings: { 'better-tailwindcss': { entryPoint, rootFontSize } },\n overrides: [\n {\n files: files ?? [GLOB_JSX],\n rules: {\n 'better-tailwindcss/enforce-consistent-line-wrapping': ['error', { printWidth: 0 }],\n 'better-tailwindcss/enforce-canonical-classes': 'error',\n },\n },\n ],\n },\n overrides,\n )\n}\n\n// ============================================================================\n// Backend / ORM\n// ============================================================================\n\n/**\n * NestJS lint preset — loads @darraghor/eslint-plugin-nestjs-typed via jsPlugin.\n * Covers DI validation, Swagger consistency, decorator bug prevention (19 AST rules).\n */\nexport function nestjs(overrides?: Partial<OxlintConfig>): OxlintConfig {\n return preset(\n {\n jsPlugins: resolvePlugins([\n { name: 'nestjs-typed', specifier: '@darraghor/eslint-plugin-nestjs-typed' },\n ]),\n rules: {\n // DI\n 'nestjs-typed/injectable-should-be-provided': 'error',\n 'nestjs-typed/provided-injected-should-match-factory-parameters': 'error',\n 'nestjs-typed/use-injectable-provided-token': 'error',\n // Swagger\n 'nestjs-typed/api-property-matches-property-optionality': 'error',\n 'nestjs-typed/controllers-should-supply-api-tags': 'error',\n 'nestjs-typed/api-method-should-specify-api-response': 'error',\n 'nestjs-typed/api-property-returning-array-should-set-array': 'error',\n 'nestjs-typed/api-property-should-have-api-extra-models': 'error',\n 'nestjs-typed/api-operation-summary-description-capitalized': 'error',\n // Bug prevention\n 'nestjs-typed/param-decorator-name-matches-route-param': 'error',\n 'nestjs-typed/validate-nested-of-array-should-set-each': 'error',\n 'nestjs-typed/all-properties-are-whitelisted': 'error',\n 'nestjs-typed/no-duplicate-decorators': 'error',\n 'nestjs-typed/validation-pipe-should-use-forbid-unknown': 'error',\n },\n },\n overrides,\n )\n}\n\n/** Drizzle ORM lint preset — eslint-plugin-drizzle. */\nexport function drizzle(overrides?: Partial<OxlintConfig>): OxlintConfig {\n return preset(\n {\n jsPlugins: resolvePlugins(['eslint-plugin-drizzle']),\n rules: {\n 'drizzle/enforce-delete-with-where': 'error',\n 'drizzle/enforce-update-with-where': 'error',\n },\n },\n overrides,\n )\n}\n\n// ============================================================================\n// Re-exports\n// ============================================================================\n\nexport { defineConfig } from 'oxlint'\nexport { GLOB_SRC, GLOB_JS, GLOB_TS, GLOB_JSX, GLOB_TESTS, GLOB_JSON, GLOB_MARKDOWN } from './utils'\n"],"mappings":"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"}
1
+ {"version":3,"file":"lint.mjs","names":["defineConfig"],"sources":["../src/utils.ts","../src/lint.ts"],"sourcesContent":["/**\n * Utility functions and constants\n */\n\n// ============================================================================\n// Environment detection\n// ============================================================================\n\nconst env = process.env\n\nfunction isCI(): boolean {\n return !!(\n env['CI'] ||\n env['CONTINUOUS_INTEGRATION'] ||\n env['BUILD_ID'] ||\n env['BUILD_NUMBER'] ||\n env['RUN_ID']\n )\n}\n\nfunction isInGitHooksOrLintStaged(): boolean {\n return (\n !!(env['GIT_PARAMS'] || env['VSCODE_GIT_COMMAND']) ||\n env['npm_lifecycle_script']?.startsWith('lint-staged') === true\n )\n}\n\n/**\n * Detects whether running in an editor environment.\n * Returns false in CI, Git Hooks, or lint-staged.\n */\nexport function isInEditorEnv(): boolean {\n if (isCI()) return false\n if (isInGitHooksOrLintStaged()) return false\n return !!(\n env['VSCODE_PID'] ||\n env['VSCODE_CWD'] ||\n env['JETBRAINS_IDE'] ||\n env['VIM'] ||\n env['NVIM']\n )\n}\n\n// ============================================================================\n// File matching patterns (Globs)\n// ============================================================================\n\n/** All JS/TS source files */\nexport const GLOB_SRC = '**/*.{js,mjs,cjs,jsx,ts,mts,cts,tsx}'\n\n/** JavaScript files only */\nexport const GLOB_JS = '**/*.{js,mjs,cjs,jsx}'\n\n/** TypeScript files only */\nexport const GLOB_TS = '**/*.{ts,mts,cts,tsx}'\n\n/** JSX/TSX files (React-related) */\nexport const GLOB_JSX = '**/*.{jsx,tsx}'\n\n/** Test files */\nexport const GLOB_TESTS: string[] = [\n '**/*.{test,spec}.{js,mjs,cjs,jsx,ts,mts,cts,tsx}',\n '**/__tests__/**/*.{js,mjs,cjs,jsx,ts,mts,cts,tsx}',\n]\n\n/** JSON files */\nexport const GLOB_JSON = '**/*.json'\n\n/** Markdown files */\nexport const GLOB_MARKDOWN = '**/*.md'\n","/**\n * Oxlint lint presets.\n *\n * Every preset is a function that accepts optional overrides, merged via `defu`.\n * User overrides take priority over preset defaults.\n *\n * @example\n * ```ts\n * // oxlint.config.ts\n * import { base, unicorn, react, tailwind, vitest } from '@hooshid/ox-config/lint'\n * import { defineConfig } from 'oxlint'\n *\n * export default defineConfig({\n * extends: [base(), unicorn(), react(), tailwind(), vitest()],\n * })\n * ```\n */\nimport { existsSync, readFileSync } from 'node:fs'\nimport { createRequire } from 'node:module'\nimport path from 'node:path'\n\nimport { defu } from 'defu'\nimport { defineConfig } from 'oxlint'\n\nimport { GLOB_JSX, GLOB_SRC, GLOB_TESTS, GLOB_TS, isInEditorEnv } from './utils'\n\nimport type { ExternalPluginEntry, OxlintConfig } from 'oxlint'\n\nconst require = createRequire(import.meta.url)\n\n// ============================================================================\n// Ignore patterns\n// ============================================================================\n\nconst DEFAULT_IGNORES: string[] = [\n '**/node_modules/**',\n '**/dist/**',\n '**/build/**',\n '**/out/**',\n '**/.next/**',\n '**/.cache/**',\n '**/.turbo/**',\n '**/.output/**',\n '**/.nitro/**',\n '**/.tanstack/**',\n '**/.vinxi/**',\n '**/.git/**',\n '**/.svn/**',\n '**/.hg/**',\n '**/.pnp.*',\n '**/public/**',\n '**/*.d.ts',\n]\n\nfunction loadGitignorePatterns(): string[] {\n const gitignoreFile = path.resolve(process.cwd(), '.gitignore')\n if (!existsSync(gitignoreFile)) return []\n\n return readFileSync(gitignoreFile, 'utf8')\n .split(/\\r?\\n/u)\n .map((line) => line.trim())\n .filter((line) => line && !line.startsWith('#'))\n .map((pattern) => {\n let p = pattern.trimEnd()\n if (p.startsWith('/')) p = p.slice(1)\n if (!p.includes('/') && !p.includes('*')) p = `**/${p}`\n if (p.endsWith('/')) p = `${p}**`\n return p\n })\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nfunction preset(defaults: OxlintConfig, overrides?: Partial<OxlintConfig>): OxlintConfig {\n return defineConfig(defu(overrides ?? {}, defaults))\n}\n\n/**\n * Resolve a jsPlugin package name to its absolute path.\n * This allows oxlint to load plugins directly without relying on\n * Node module resolution from the consumer's CWD — fixes pnpm strict mode.\n */\nfunction resolvePlugin(name: string): string {\n try {\n return require.resolve(name)\n } catch {\n return name\n }\n}\n\nfunction resolvePlugins(plugins: ExternalPluginEntry[]): ExternalPluginEntry[] {\n return plugins.map((p) => {\n if (typeof p === 'string') return resolvePlugin(p)\n return { ...p, specifier: resolvePlugin(p.specifier) }\n })\n}\n\n// ============================================================================\n// Core\n// ============================================================================\n\n/**\n * Base lint preset — TypeScript + Import plugins, categories, env, ignores.\n * Always include first.\n */\nexport function base(overrides?: Partial<OxlintConfig>): OxlintConfig {\n return preset(\n {\n plugins: ['typescript', 'import'],\n categories: {\n correctness: 'error',\n suspicious: 'error',\n perf: 'error',\n pedantic: 'warn',\n },\n rules: {\n // Shape-only check; necessary in interactive CLI and sequential workflows.\n 'no-await-in-loop': 'off',\n // High-noise; readonly intent better expressed via `const generics` or call-site.\n 'typescript/prefer-readonly-parameter-types': 'off',\n // Turns `if (str)` into ceremony for marginal safety gain.\n 'typescript/strict-boolean-expressions': 'off',\n // File/function size is a reviewer call, not a lint rule.\n 'max-lines': 'off',\n 'max-lines-per-function': 'off',\n // Misfires on `/* @__PURE__ */` and similar bundler annotations.\n 'no-inline-comments': 'off',\n // TODO/FIXME triage belongs in the issue tracker.\n 'no-warning-comments': 'off',\n // Default cap of 10 is too tight for modern React/Next component files.\n 'import/max-dependencies': 'off',\n // Modern React renders apostrophes correctly; legacy noise.\n 'react/no-unescaped-entities': 'off',\n // Misfires on Next.js Server Actions and placeholder async functions.\n 'require-await': 'off',\n },\n env: {\n browser: true,\n node: true,\n es2026: true,\n builtin: true,\n },\n ignorePatterns: [...DEFAULT_IGNORES, ...loadGitignorePatterns()],\n overrides: [\n {\n files: [GLOB_TS],\n rules: {\n // Only list rules that DIFFER from categories defaults\n 'typescript/consistent-type-definitions': 'off',\n 'typescript/consistent-type-imports': 'error',\n 'no-unused-vars': 'off',\n 'typescript/array-type': 'error',\n 'typescript/consistent-generic-constructors': 'error',\n 'typescript/consistent-indexed-object-style': 'error',\n 'typescript/consistent-type-assertions': 'error',\n 'typescript/ban-tslint-comment': 'error',\n 'typescript/no-empty-interface': 'error',\n 'typescript/no-inferrable-types': 'error',\n 'typescript/prefer-for-of': 'error',\n 'typescript/prefer-function-type': 'error',\n 'typescript/unified-signatures': 'error',\n },\n },\n {\n files: [GLOB_SRC],\n rules: {\n // CSS/style side-effect imports are standard in all frontend frameworks\n 'import/no-unassigned-import': 'off',\n 'import/no-relative-parent-imports': 'error',\n 'import/first': 'error',\n 'import/no-duplicates': 'error',\n 'import/consistent-type-specifier-style': 'error',\n 'import/no-mutable-exports': 'error',\n 'import/no-named-default': 'error',\n },\n },\n {\n // Config files commonly import shared roots via `../../config.ts`\n // in monorepos — intended pattern, not a smell.\n files: ['**/*.config.{ts,mts,cts,js,mjs,cjs}'],\n rules: {\n 'import/no-relative-parent-imports': 'off',\n },\n },\n {\n // Test files use mock setup patterns (vi.mock/vi.hoisted before imports),\n // explicit mock signatures, and fixture data that\n // legitimately violate strict style/safety rules.\n files: GLOB_TESTS,\n rules: {\n // Mock setup pattern breaks standard import ordering\n 'import/first': 'off',\n 'import/no-duplicates': 'off',\n 'import/consistent-type-specifier-style': 'off',\n // Mock signatures need explicit values / async without await\n 'unicorn/no-useless-undefined': 'off',\n 'typescript/no-empty-function': 'off',\n // Modernization hints aren't useful in tests\n 'unicorn/prefer-string-replace-all': 'off',\n 'unicorn/no-array-callback-reference': 'off',\n 'unicorn/prefer-spread': 'off',\n // Tests deliberately use non-null assertions, magic numbers, any\n 'typescript/no-non-null-assertion': 'off',\n 'no-magic-numbers': 'off',\n 'typescript/no-explicit-any': 'off',\n 'typescript/no-unsafe-assignment': 'off',\n 'typescript/no-unsafe-call': 'off',\n 'typescript/no-unsafe-member-access': 'off',\n 'typescript/no-unsafe-return': 'off',\n 'typescript/no-unsafe-argument': 'off',\n // Index keys are fine when rendering fixture lists\n 'react/no-array-index-key': 'off',\n },\n },\n ],\n },\n overrides,\n )\n}\n\n/**\n * Type-aware lint preset — enables 59 type-aware rules via tsgolint + type checking.\n * Requires TypeScript 7.0+ and `oxlint-tsgolint` (bundled as dependency).\n */\nexport function typeAware(overrides?: Partial<OxlintConfig>): OxlintConfig {\n return preset(\n {\n options: {\n typeAware: true,\n typeCheck: true,\n },\n },\n overrides,\n )\n}\n\n/** Unicorn lint preset — 100+ code quality rules. */\nexport function unicorn(overrides?: Partial<OxlintConfig>): OxlintConfig {\n return preset(\n {\n plugins: ['unicorn'],\n rules: {\n 'unicorn/no-null': 'off',\n 'unicorn/filename-case': ['error', { case: 'kebabCase' }],\n 'unicorn/catch-error-name': 'error',\n 'unicorn/error-message': 'error',\n 'unicorn/prefer-optional-catch-binding': 'error',\n 'unicorn/no-zero-fractions': 'error',\n 'unicorn/number-literal-case': 'error',\n 'unicorn/numeric-separators-style': 'error',\n 'unicorn/prefer-includes': 'error',\n 'unicorn/prefer-spread': 'error',\n 'unicorn/prefer-ternary': 'error',\n 'unicorn/prefer-string-trim-start-end': 'error',\n 'unicorn/prefer-structured-clone': 'error',\n 'unicorn/prefer-default-parameters': 'error',\n 'unicorn/no-console-spaces': 'error',\n 'unicorn/throw-new-error': 'error',\n 'unicorn/require-array-join-separator': 'error',\n },\n },\n overrides,\n )\n}\n\n/** Dependency optimization — flags packages replaceable with native APIs. */\nexport function depend(overrides?: Partial<OxlintConfig>): OxlintConfig {\n return preset(\n {\n jsPlugins: resolvePlugins(['eslint-plugin-depend']),\n rules: {\n 'depend/ban-dependencies': [\n 'error',\n {\n presets: ['native', 'microutilities', 'preferred'],\n modules: [],\n allowed: ['dotenv'],\n },\n ],\n },\n },\n overrides,\n )\n}\n\n// ============================================================================\n// Runtime environments\n// ============================================================================\n\n/** Node.js lint preset — native node plugin. */\nexport function node(overrides?: Partial<OxlintConfig>): OxlintConfig {\n return preset({ plugins: ['node'] }, overrides)\n}\n\n/** Promise lint preset — native promise plugin. */\nexport function promise(overrides?: Partial<OxlintConfig>): OxlintConfig {\n return preset({ plugins: ['promise'] }, overrides)\n}\n\n// ============================================================================\n// Frontend\n// ============================================================================\n\nconst reactRules = {\n // ─── Hooks (CRITICAL) ─────────────────────────────\n 'react/rules-of-hooks': 'error',\n 'react/exhaustive-deps': 'warn',\n\n // ─── JSX Correctness ──────────────────────────────\n 'react/jsx-key': 'error',\n 'react/jsx-no-duplicate-props': 'error',\n 'react/jsx-no-undef': 'error',\n 'react/jsx-uses-vars': 'error',\n 'react/jsx-no-target-blank': ['error', { allowReferrer: false }],\n 'react/jsx-no-comment-textnodes': 'error',\n 'react/jsx-no-script-url': 'error',\n\n // ─── JSX Style ────────────────────────────────────\n 'react/jsx-boolean-value': ['error', 'never'],\n 'react/jsx-curly-brace-presence': ['error', { props: 'never', children: 'never' }],\n 'react/jsx-fragments': ['error', 'syntax'],\n 'react/jsx-pascal-case': ['error', { allowAllCaps: false, allowNamespace: true }],\n 'react/self-closing-comp': ['error', { component: true, html: true }],\n 'react/hook-use-state': 'error',\n\n // ─── Runtime Safety ───────────────────────────────\n 'react/no-children-prop': 'error',\n 'react/no-danger-with-children': 'error',\n 'react/no-deprecated': 'error',\n 'react/no-direct-mutation-state': 'error',\n 'react/no-find-dom-node': 'error',\n 'react/no-is-mounted': 'error',\n 'react/no-render-return-value': 'error',\n 'react/no-string-refs': 'error',\n 'react/no-unknown-property': 'error',\n 'react/no-unsafe': 'error',\n 'react/require-render-return': 'error',\n 'react/void-dom-elements-no-children': 'error',\n\n // ─── Modern React (17+) ───────────────────────────\n 'react/react-in-jsx-scope': 'off',\n 'react/jsx-uses-react': 'off',\n\n // ─── Noise Reduction ──────────────────────────────\n 'react/no-unescaped-entities': 'off',\n} satisfies NonNullable<OxlintConfig['rules']>\n\n/** React lint preset — core React + Hooks rules. */\nexport function react(overrides?: Partial<OxlintConfig>): OxlintConfig {\n return preset(\n {\n plugins: ['react'],\n rules: reactRules,\n },\n overrides,\n )\n}\n\n/** React + react-refresh preset (for Vite, TanStack Start, etc.). */\nexport function reactVite(overrides?: Partial<OxlintConfig>): OxlintConfig {\n return preset(\n {\n plugins: ['react'],\n jsPlugins: resolvePlugins(['eslint-plugin-react-refresh']),\n rules: {\n ...reactRules,\n 'react-refresh/only-export-components': ['warn', { allowConstantExport: true }],\n },\n },\n overrides,\n )\n}\n\n/** Next.js lint preset — enables native nextjs plugin. */\nexport function nextjs(overrides?: Partial<OxlintConfig>): OxlintConfig {\n return preset({ plugins: ['nextjs'] }, overrides)\n}\n\n/**\n * TanStack Router lint preset.\n *\n * Loads @tanstack/eslint-plugin-router and applies conventions specific\n * to file-based routing setups.\n *\n * Rules provided by the plugin:\n * - `route-param-names` — validates `$param` names match between route path and params\n * - `create-route-property-order` — enforces consistent property order in `createRoute()`\n */\nexport function tanstackRouter(overrides?: Partial<OxlintConfig>): OxlintConfig {\n return preset(\n {\n jsPlugins: resolvePlugins([\n { name: 'tanstack-router', specifier: '@tanstack/eslint-plugin-router' },\n ]),\n rules: {\n // ─── Route Configuration ─────────────────────────\n 'tanstack-router/route-param-names': 'error',\n 'tanstack-router/create-route-property-order': 'error',\n\n // ─── Route File Conventions ──────────────────────\n // Route files should use named exports for route objects\n // (default export reserved for the component or route)\n 'import/no-default-export': 'off', // Router requires default exports\n },\n overrides: [\n {\n // Route files follow specific naming and structure\n files: ['**/routes/**/*.{ts,tsx}'],\n rules: {\n // Routes must not use window directly — use router hooks\n 'no-restricted-globals': [\n 'error',\n {\n name: 'window',\n message: 'Use useRouter() or useNavigate() instead of window in route files.',\n },\n ],\n },\n },\n {\n // ─── Filename Convention (kebab-case) ─────────\n // Applies only to files inside a `routes/` folder.\n files: ['**/routes/**/*.{ts,tsx}'],\n plugins: ['unicorn'],\n rules: {\n 'unicorn/filename-case': [\n 'error',\n {\n case: 'kebabCase',\n ignore: [\n '\\\\$', // dynamic params: $postId.tsx, posts.$postId.tsx\n '^_', // pathless/root: _auth.tsx, __root.tsx\n '\\\\.', // multi-segment: posts.index.tsx, route.lazy.tsx\n ],\n },\n ],\n },\n },\n {\n // Root route file convention\n files: ['**/routes/__root.tsx'],\n rules: {\n // __root.tsx can't use useNavigate (no router context yet)\n 'no-restricted-globals': 'off',\n },\n },\n ],\n },\n overrides,\n )\n}\n\n/**\n * TanStack Start lint preset.\n *\n * Adds rules for server functions, client/server boundaries, and Start\n * conventions. This preset assumes `reactVite()` and `tanstackRouter()`\n * are already in the `extends` array.\n *\n */\nexport function tanstackStart(overrides?: Partial<OxlintConfig>): OxlintConfig {\n return preset(\n {\n rules: {\n // ─── Server Function Safety ──────────────────────\n // Prevent async promise executors (Start loaders must be sync wrapper)\n 'no-async-promise-executor': 'error',\n // Sequential awaits are fine in server functions\n 'no-await-in-loop': 'off',\n\n // ─── Client / Server Boundary ────────────────────\n // Node.js modules must not leak into client bundles\n 'import/no-nodejs-modules': 'error',\n\n // ─── Loader Conventions ──────────────────────────\n // Loaders must consistently return or throw\n 'consistent-return': 'error',\n\n // ─── Common Start Pitfalls ───────────────────────\n // Empty functions are common in placeholder server functions\n 'no-empty-function': 'warn',\n },\n\n overrides: [\n {\n // Server-only files — Node.js APIs allowed\n files: ['**/*.server.{ts,tsx}', '**/server/**/*.{ts,tsx}', '**/server-fns/**/*.{ts,tsx}'],\n rules: {\n 'import/no-nodejs-modules': 'off',\n 'no-console': 'off',\n },\n },\n {\n // Client-only files — Node.js APIs forbidden\n files: ['**/*.client.{ts,tsx}', '**/components/**/*.{ts,tsx}'],\n rules: {\n 'import/no-nodejs-modules': 'error',\n },\n },\n {\n // Route files — server-aware\n files: ['**/routes/**/*.{ts,tsx}'],\n rules: {\n // Routes use loaders, not direct fetch in component\n 'no-restricted-syntax': [\n 'warn',\n {\n selector: 'CallExpression[callee.name=\"fetch\"]',\n message: 'Prefer a loader or server function over direct fetch in route files.',\n },\n ],\n },\n },\n {\n files: ['**/*.server.{ts,tsx}', '**/*.client.{ts,tsx}'],\n plugins: ['unicorn'],\n rules: {\n 'unicorn/filename-case': [\n 'error',\n {\n case: 'kebabCase',\n ignore: [\n '\\\\.', // allow *.server.ts / *.client.ts (has dots)\n ],\n },\n ],\n },\n },\n {\n files: ['**/*.server.{ts,tsx}', '**/server/**/*.{ts,tsx}', '**/server-fns/**/*.{ts,tsx}'],\n rules: {\n 'import/no-nodejs-modules': 'off',\n 'no-console': 'off',\n // ← جدید: جلوگیری از crash توی SSR\n 'no-restricted-globals': [\n 'error',\n {\n name: 'window',\n message:\n 'Not available in server context. Use a server function or guard with typeof window.',\n },\n { name: 'document', message: 'Not available in server context.' },\n { name: 'localStorage', message: 'Not available in server context.' },\n { name: 'sessionStorage', message: 'Not available in server context.' },\n ],\n },\n },\n ],\n },\n overrides,\n )\n}\n\n// ============================================================================\n// Quality\n// ============================================================================\n\n/** Accessibility lint preset — enables native jsx-a11y plugin. */\nexport function a11y(overrides?: Partial<OxlintConfig>): OxlintConfig {\n return preset({ plugins: ['jsx-a11y'] }, overrides)\n}\n\n/** JSDoc lint preset — enables native jsdoc plugin. */\nexport function jsdoc(overrides?: Partial<OxlintConfig>): OxlintConfig {\n return preset({ plugins: ['jsdoc'] }, overrides)\n}\n\n// ============================================================================\n// Testing\n// ============================================================================\n\ninterface VitestOptions extends Partial<OxlintConfig> {\n /** Test file glob patterns. Replaces the default GLOB_TESTS. */\n files?: string[]\n}\n\n/** Vitest lint preset — native vitest plugin with test-file scoping. */\nexport function vitest(options?: VitestOptions): OxlintConfig {\n const { files, ...overrides } = options ?? {}\n\n return preset(\n {\n plugins: ['vitest'],\n settings: { vitest: { typecheck: true } },\n overrides: [\n {\n files: files ?? GLOB_TESTS,\n rules: {\n 'vitest/expect-expect': 'error',\n 'vitest/no-conditional-expect': 'error',\n 'vitest/no-identical-title': 'error',\n 'vitest/no-import-node-test': 'error',\n 'vitest/no-interpolation-in-snapshots': 'error',\n 'vitest/no-mocks-import': 'error',\n 'vitest/no-standalone-expect': 'error',\n 'vitest/valid-describe-callback': 'error',\n 'vitest/valid-expect': 'error',\n 'vitest/valid-title': 'error',\n 'vitest/consistent-test-it': ['error', { fn: 'it', withinDescribe: 'it' }],\n 'vitest/prefer-hooks-in-order': 'error',\n 'vitest/prefer-lowercase-title': 'error',\n 'vitest/no-disabled-tests': isInEditorEnv() ? 'warn' : 'error',\n 'vitest/no-focused-tests': isInEditorEnv() ? 'warn' : 'error',\n 'vitest/require-mock-type-parameters': 'off',\n 'no-console': 'off',\n 'unicorn/no-null': 'off',\n 'typescript/ban-ts-comment': 'off',\n },\n },\n ],\n },\n overrides,\n )\n}\n\n// ============================================================================\n// Tailwind\n// ============================================================================\n\ninterface TailwindOptions extends Partial<OxlintConfig> {\n entryPoint?: string\n rootFontSize?: number\n /** File glob patterns for tailwind rules. @default GLOB_JSX */\n files?: string[]\n}\n\n/** Tailwind CSS lint preset — eslint-plugin-better-tailwindcss. */\nexport function tailwind(options: TailwindOptions = {}): OxlintConfig {\n const { entryPoint = 'src/styles/globals.css', rootFontSize = 16, files, ...overrides } = options\n\n return preset(\n {\n jsPlugins: resolvePlugins(['eslint-plugin-better-tailwindcss']),\n settings: { 'better-tailwindcss': { entryPoint, rootFontSize } },\n overrides: [\n {\n files: files ?? [GLOB_JSX],\n rules: {\n 'better-tailwindcss/enforce-consistent-line-wrapping': ['error', { printWidth: 0 }],\n 'better-tailwindcss/enforce-canonical-classes': 'error',\n },\n },\n ],\n },\n overrides,\n )\n}\n\n// ============================================================================\n// Backend / ORM\n// ============================================================================\n\n/**\n * NestJS lint preset — loads @darraghor/eslint-plugin-nestjs-typed via jsPlugin.\n * Covers DI validation, Swagger consistency, decorator bug prevention (19 AST rules).\n */\nexport function nestjs(overrides?: Partial<OxlintConfig>): OxlintConfig {\n return preset(\n {\n jsPlugins: resolvePlugins([\n { name: 'nestjs-typed', specifier: '@darraghor/eslint-plugin-nestjs-typed' },\n ]),\n rules: {\n // DI\n 'nestjs-typed/injectable-should-be-provided': 'error',\n 'nestjs-typed/provided-injected-should-match-factory-parameters': 'error',\n 'nestjs-typed/use-injectable-provided-token': 'error',\n // Swagger\n 'nestjs-typed/api-property-matches-property-optionality': 'error',\n 'nestjs-typed/controllers-should-supply-api-tags': 'error',\n 'nestjs-typed/api-method-should-specify-api-response': 'error',\n 'nestjs-typed/api-property-returning-array-should-set-array': 'error',\n 'nestjs-typed/api-property-should-have-api-extra-models': 'error',\n 'nestjs-typed/api-operation-summary-description-capitalized': 'error',\n // Bug prevention\n 'nestjs-typed/param-decorator-name-matches-route-param': 'error',\n 'nestjs-typed/validate-nested-of-array-should-set-each': 'error',\n 'nestjs-typed/all-properties-are-whitelisted': 'error',\n 'nestjs-typed/no-duplicate-decorators': 'error',\n 'nestjs-typed/validation-pipe-should-use-forbid-unknown': 'error',\n },\n },\n overrides,\n )\n}\n\n/** Drizzle ORM lint preset — eslint-plugin-drizzle. */\nexport function drizzle(overrides?: Partial<OxlintConfig>): OxlintConfig {\n return preset(\n {\n jsPlugins: resolvePlugins(['eslint-plugin-drizzle']),\n rules: {\n 'drizzle/enforce-delete-with-where': 'error',\n 'drizzle/enforce-update-with-where': 'error',\n },\n },\n overrides,\n )\n}\n\n// ============================================================================\n// Re-exports\n// ============================================================================\n\nexport { defineConfig } from 'oxlint'\nexport { GLOB_SRC, GLOB_JS, GLOB_TS, GLOB_JSX, GLOB_TESTS, GLOB_JSON, GLOB_MARKDOWN } from './utils'\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hooshid/ox-config",
3
- "version": "0.3.0",
3
+ "version": "1.0.0",
4
4
  "description": "Shared Oxlint + Oxfmt presets — one install for lint and format.",
5
5
  "keywords": [
6
6
  "config",