@hooshid/ox-config 0.2.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
@@ -1,26 +1,189 @@
1
1
  # @hooshid/ox-config
2
2
 
3
- Shared Oxlint + Oxfmt presets for my projects — one install for lint and format.
3
+ Shared [Oxlint](https://oxc.rs/) + [Oxfmt](https://oxc.rs/docs/guide/usage/formatter) presets for my projects. One install, lint and format ready.
4
4
 
5
5
  ## Install
6
6
 
7
7
  ```bash
8
- pnpm add -D @hooshid/ox-config oxlint oxfmt
8
+ pnpm add -D @hooshid/ox-config
9
9
  ```
10
10
 
11
- ## Usage
11
+ > [!TIP]
12
+ > Works with pnpm strict mode out of the box — jsPlugin paths are resolved internally via `require.resolve()`, no hoisting hacks needed.
12
13
 
13
- ### Oxlint
14
+ ## Lint (Oxlint)
14
15
 
15
16
  Create `oxlint.config.ts` in your project root:
16
17
 
18
+ ```ts
19
+ import { base, unicorn, depend, reactVite, tailwind } from '@hooshid/ox-config/lint'
20
+ import { defineConfig } from 'oxlint'
21
+
22
+ export default defineConfig({
23
+ extends: [base(), unicorn(), depend(), reactVite(), tailwind()],
24
+ })
25
+ ```
26
+
27
+ Every preset is a function. Call without arguments for defaults, or pass overrides:
28
+
29
+ ```ts
30
+ export default defineConfig({
31
+ extends: [
32
+ base({ rules: { 'no-console': 'off' } }),
33
+ unicorn({ rules: { 'unicorn/no-array-for-each': 'off' } }),
34
+ vitest({ files: ['**/*.e2e-spec.ts', '**/*.spec.ts'] }),
35
+ ],
36
+ })
37
+ ```
38
+
39
+ > [!IMPORTANT]
40
+ > Most presets use deep merge via `defu` — user values take priority. File scope options **replace** their defaults (e.g. `vitest({ files: [...] })` replaces the default test globs).
41
+
42
+ ### Available presets
43
+
44
+ #### Core
45
+
46
+ | Preset | Description |
47
+ | ------------- | ------------------------------------------------------------------- |
48
+ | `base()` | TypeScript, Import, categories, env, ignores. Always include first. |
49
+ | `typeAware()` | 59 type-aware rules via tsgolint (requires TS-compatible tsconfig) |
50
+ | `unicorn()` | 100+ code quality rules |
51
+ | `depend()` | Flag packages replaceable with native APIs or micro-utilities |
52
+
53
+ #### Runtime
54
+
55
+ | Preset | Description |
56
+ | ----------- | --------------------------------- |
57
+ | `node()` | Node.js specific rules |
58
+ | `promise()` | Promise best practices (16 rules) |
59
+
60
+ #### Frontend
61
+
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) |
70
+
71
+ #### Backend / ORM
72
+
73
+ | Preset | Description |
74
+ | ----------- | ---------------------------------------------------------------------- |
75
+ | `nestjs()` | NestJS DI validation, Swagger consistency, decorator checks (14 rules) |
76
+ | `drizzle()` | Drizzle ORM — enforce where clause on delete/update |
77
+
78
+ #### Quality
79
+
80
+ | Preset | Description |
81
+ | --------- | ------------------------ |
82
+ | `a11y()` | JSX accessibility (WCAG) |
83
+ | `jsdoc()` | JSDoc validation |
84
+
85
+ #### Testing
86
+
87
+ | Preset | Description |
88
+ | ---------- | ---------------------------------------- |
89
+ | `vitest()` | Vitest best practices, environment-aware |
90
+
91
+ ### Which React preset should I use?
92
+
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()` |
100
+
101
+ > `reactVite()` adds `eslint-plugin-react-refresh` to warn about incorrect fast-refresh patterns — use it for any Vite-based setup.
102
+
103
+ ### React rules
104
+
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.
113
+
114
+ ### TanStack Router
115
+
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.
117
+
118
+ ```ts
119
+ import { base, reactVite, tanstackRouter, tailwind } from '@hooshid/ox-config/lint'
120
+ import { defineConfig } from 'oxlint'
121
+
122
+ export default defineConfig({
123
+ extends: [base(), reactVite(), tanstackRouter(), tailwind()],
124
+ })
125
+ ```
126
+
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()`
131
+
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:**
178
+
17
179
  ```ts
18
180
  import {
19
181
  base,
20
182
  unicorn,
21
183
  depend,
22
- react,
184
+ reactVite,
23
185
  tanstackRouter,
186
+ tanstackStart,
24
187
  tailwind,
25
188
  vitest,
26
189
  } from '@hooshid/ox-config/lint'
@@ -31,54 +194,257 @@ export default defineConfig({
31
194
  base(),
32
195
  unicorn(),
33
196
  depend(),
34
- react(),
197
+ reactVite(),
35
198
  tanstackRouter(),
36
- tailwind(),
199
+ tanstackStart(),
200
+ tailwind({ entryPoint: 'src/styles/globals.css' }),
37
201
  vitest(),
38
202
  ],
39
203
  })
40
204
  ```
41
205
 
42
- ### Oxfmt
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.
210
+
211
+ ```ts
212
+ import { base, node, promise, nestjs, drizzle, vitest } from '@hooshid/ox-config/lint'
213
+ import { defineConfig } from 'oxlint'
214
+
215
+ export default defineConfig({
216
+ extends: [
217
+ base(),
218
+ node(),
219
+ promise(),
220
+ nestjs(),
221
+ drizzle({
222
+ rules: {
223
+ 'drizzle/enforce-delete-with-where': ['error', { drizzleObjectName: 'db' }],
224
+ 'drizzle/enforce-update-with-where': ['error', { drizzleObjectName: 'db' }],
225
+ },
226
+ }),
227
+ vitest({ files: ['**/*.spec.ts', '**/*.e2e-spec.ts'] }),
228
+ ],
229
+ rules: {
230
+ // NestJS exception filter .catch() is not Promise.catch()
231
+ 'promise/valid-params': 'off',
232
+ },
233
+ overrides: [
234
+ {
235
+ files: ['**/*.{ts,mts,cts,tsx}'],
236
+ rules: {
237
+ 'typescript/consistent-type-imports': 'off',
238
+ 'typescript/no-extraneous-class': ['error', { allowWithDecorator: true }],
239
+ },
240
+ },
241
+ ],
242
+ })
243
+ ```
244
+
245
+ ### Type-aware linting
246
+
247
+ The `typeAware()` preset enables two options on oxlint:
248
+
249
+ - **`typeAware`** — turns on ~59 lint rules that need type information, implemented via [`oxlint-tsgolint`](https://www.npmjs.com/package/oxlint-tsgolint) (e.g. `no-floating-promises`, `no-misused-promises`, `consistent-type-imports`)
250
+ - **`typeCheck`** — pipes the TypeScript compiler's own diagnostics (`TS2322`, `TS6133`, `TS2307`, ...) through oxlint, so `oxlint` reports type errors alongside lint violations
251
+
252
+ ```ts
253
+ import { base, typeAware, unicorn } from '@hooshid/ox-config/lint'
254
+ import { defineConfig } from 'oxlint'
255
+
256
+ export default defineConfig({
257
+ extends: [base(), typeAware(), unicorn()],
258
+ })
259
+ ```
260
+
261
+ > [!IMPORTANT]
262
+ > `typeAware` and `typeCheck` are **root-config-only** options. Oxlint will error if either is set in a nested (per-package) config file. Always place `typeAware()` in the root config only.
263
+
264
+ Each package's own `tsconfig.json` is auto-detected by oxlint — no extra configuration needed.
265
+
266
+ #### Do I still need a separate `tsc --noEmit` step?
267
+
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:
269
+
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.
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.
273
+
274
+ ### Monorepo (nested configs)
275
+
276
+ Oxlint supports [nested configuration](https://oxc.rs/docs/guide/usage/linter/nested-config.html) for monorepos. Each package can have its own `oxlint.config.ts` that extends the root config and adds package-specific presets.
277
+
278
+ #### Root config
279
+
280
+ ```ts
281
+ // oxlint.config.ts (root)
282
+ import { base, typeAware, unicorn, depend } from '@hooshid/ox-config/lint'
283
+ import { defineConfig } from 'oxlint'
284
+
285
+ export default defineConfig({
286
+ extends: [base(), typeAware(), unicorn(), depend()],
287
+ })
288
+ ```
289
+
290
+ #### Package configs
291
+
292
+ ```ts
293
+ // packages/web/oxlint.config.ts
294
+ import rootConfig from '../../oxlint.config.ts'
295
+ import { reactVite, tanstackRouter, tanstackStart, vitest, tailwind } from '@hooshid/ox-config/lint'
296
+ import { defineConfig } from 'oxlint'
297
+
298
+ export default defineConfig({
299
+ extends: [rootConfig, reactVite(), tanstackRouter(), tanstackStart(), vitest(), tailwind()],
300
+ })
301
+ ```
302
+
303
+ ```ts
304
+ // packages/api/oxlint.config.ts
305
+ import rootConfig from '../../oxlint.config.ts'
306
+ import { node, nestjs, drizzle, vitest } from '@hooshid/ox-config/lint'
307
+ import { defineConfig } from 'oxlint'
308
+
309
+ export default defineConfig({
310
+ extends: [rootConfig, node(), nestjs(), drizzle(), vitest()],
311
+ })
312
+ ```
313
+
314
+ > [!TIP]
315
+ > Packages without their own `oxlint.config.ts` automatically use the root config.
316
+
317
+ > [!WARNING]
318
+ > Passing `-c` or `--config` explicitly on the CLI **disables** nested config lookup. Let oxlint auto-detect configs by running without `-c`.
319
+
320
+ ## Format (Oxfmt)
43
321
 
44
322
  Create `oxfmt.config.ts`:
45
323
 
46
324
  ```ts
47
- import { format, tailwindFormat } from '@hooshid/ox-config/format'
325
+ import { format } from '@hooshid/ox-config/format'
48
326
  import { defineConfig } from 'oxfmt'
49
327
 
328
+ export default defineConfig({ ...format() })
329
+ ```
330
+
331
+ ### Defaults
332
+
333
+ | Option | Value |
334
+ | -------------------- | --------------------- |
335
+ | `semi` | `false` |
336
+ | `singleQuote` | `true` |
337
+ | `trailingComma` | `all` |
338
+ | `printWidth` | `100` |
339
+ | `tabWidth` | `2` |
340
+ | `endOfLine` | `lf` |
341
+ | Import sorting | Grouped with newlines |
342
+ | Package.json sorting | Enabled |
343
+ | Ignore patterns | Build outputs, lockfiles, generated files |
344
+
345
+ ### Override
346
+
347
+ ```ts
348
+ export default defineConfig({
349
+ ...format({ printWidth: 120, semi: true }),
350
+ })
351
+ ```
352
+
353
+ ### Tailwind class sorting
354
+
355
+ ```ts
356
+ import { format, tailwindFormat } from '@hooshid/ox-config/format'
357
+
50
358
  export default defineConfig({
51
359
  ...format(),
52
360
  ...tailwindFormat({ stylesheet: 'src/styles/globals.css' }),
53
361
  })
54
362
  ```
55
363
 
56
- ## Available Presets
364
+ ### Editor setup (recommended)
57
365
 
58
- ### `@hooshid/ox-config/lint`
366
+ To keep line endings consistent and avoid the "final newline flip-flop" problem, add an `.editorconfig` at the root of every project:
59
367
 
60
- | Preset | Purpose |
61
- | :--- | :--- |
62
- | `base()` | TypeScript + Import rules — always include first |
63
- | `unicorn()` | Code quality rules |
64
- | `depend()` | Dependency optimization |
65
- | `typeAware()` | Type-aware rules via tsgolint |
66
- | `react()` | React + react-refresh |
67
- | `tanstackRouter()` | TanStack Router rules |
68
- | `tailwind()` | Tailwind class rules |
69
- | `vitest()` | Vitest test rules |
70
- | `node()` | Node.js environment |
71
- | `promise()` | Promise rules |
72
- | `nestjs()` | NestJS rules |
73
- | `drizzle()` | Drizzle ORM rules |
368
+ ```ini
369
+ root = true
74
370
 
75
- ### `@hooshid/ox-config/format`
371
+ [*]
372
+ charset = utf-8
373
+ end_of_line = lf
374
+ insert_final_newline = true
375
+ trim_trailing_whitespace = true
376
+ indent_style = space
377
+ indent_size = 2
378
+ max_line_length = 100
76
379
 
77
- | Export | Purpose |
78
- | :--- | :--- |
79
- | `format()` | Base formatting config |
80
- | `tailwindFormat()` | Tailwind class sorting |
380
+ [*.md]
381
+ trim_trailing_whitespace = false
382
+
383
+ [*.{yml,yaml}]
384
+ indent_size = 2
385
+ ```
386
+
387
+ Most modern editors support EditorConfig natively or via a plugin. This ensures LF endings and a single trailing newline across every file.
388
+
389
+ ## Scripts
390
+
391
+ ```json
392
+ {
393
+ "scripts": {
394
+ "lint": "oxlint .",
395
+ "lint:fix": "oxlint . --fix",
396
+ "format": "oxfmt .",
397
+ "format:check": "oxfmt --check .",
398
+ "typecheck": "tsc --noEmit"
399
+ }
400
+ }
401
+ ```
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
+ ```
81
442
 
82
443
  ## License
83
444
 
84
- 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
@@ -21,7 +21,10 @@ export declare const GLOB_MARKDOWN = "**/*.md";
21
21
  * Always include first.
22
22
  */
23
23
  export declare function base(overrides?: Partial<OxlintConfig>): OxlintConfig;
24
- /** Type-aware lint preset — enables 59 type-aware rules via tsgolint. */
24
+ /**
25
+ * Type-aware lint preset — enables 59 type-aware rules via tsgolint + type checking.
26
+ * Requires TypeScript 7.0+ and `oxlint-tsgolint` (bundled as dependency).
27
+ */
25
28
  export declare function typeAware(overrides?: Partial<OxlintConfig>): OxlintConfig;
26
29
  /** Unicorn lint preset — 100+ code quality rules. */
27
30
  export declare function unicorn(overrides?: Partial<OxlintConfig>): OxlintConfig;
@@ -31,15 +34,42 @@ export declare function depend(overrides?: Partial<OxlintConfig>): OxlintConfig;
31
34
  export declare function node(overrides?: Partial<OxlintConfig>): OxlintConfig;
32
35
  /** Promise lint preset — native promise plugin. */
33
36
  export declare function promise(overrides?: Partial<OxlintConfig>): OxlintConfig;
34
- /**
35
- * React lint preset — React + react-refresh (for Vite/TanStack Start).
36
- */
37
+ /** React lint preset — core React + Hooks rules. */
37
38
  export declare function react(overrides?: Partial<OxlintConfig>): OxlintConfig;
39
+ /** React + react-refresh preset (for Vite, TanStack Start, etc.). */
40
+ export declare function reactVite(overrides?: Partial<OxlintConfig>): OxlintConfig;
41
+ /** Next.js lint preset — enables native nextjs plugin. */
42
+ export declare function nextjs(overrides?: Partial<OxlintConfig>): OxlintConfig;
38
43
  /**
39
- * TanStack Router lint preset — loads @tanstack/eslint-plugin-router.
40
- * 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()`
41
52
  */
42
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;
63
+ /** Accessibility lint preset — enables native jsx-a11y plugin. */
64
+ export declare function a11y(overrides?: Partial<OxlintConfig>): OxlintConfig;
65
+ /** JSDoc lint preset — enables native jsdoc plugin. */
66
+ export declare function jsdoc(overrides?: Partial<OxlintConfig>): OxlintConfig;
67
+ interface VitestOptions extends Partial<OxlintConfig> {
68
+ /** Test file glob patterns. Replaces the default GLOB_TESTS. */
69
+ files?: string[];
70
+ }
71
+ /** Vitest lint preset — native vitest plugin with test-file scoping. */
72
+ export declare function vitest(options?: VitestOptions): OxlintConfig;
43
73
  interface TailwindOptions extends Partial<OxlintConfig> {
44
74
  entryPoint?: string;
45
75
  rootFontSize?: number;
@@ -48,12 +78,10 @@ interface TailwindOptions extends Partial<OxlintConfig> {
48
78
  }
49
79
  /** Tailwind CSS lint preset — eslint-plugin-better-tailwindcss. */
50
80
  export declare function tailwind(options?: TailwindOptions): OxlintConfig;
51
- interface VitestOptions extends Partial<OxlintConfig> {
52
- files?: string[];
53
- }
54
- /** Vitest lint preset — native vitest plugin with test-file scoping. */
55
- export declare function vitest(options?: VitestOptions): OxlintConfig;
56
- /** NestJS lint preset — @darraghor/eslint-plugin-nestjs-typed. */
81
+ /**
82
+ * NestJS lint preset — loads @darraghor/eslint-plugin-nestjs-typed via jsPlugin.
83
+ * Covers DI validation, Swagger consistency, decorator bug prevention (19 AST rules).
84
+ */
57
85
  export declare function nestjs(overrides?: Partial<OxlintConfig>): OxlintConfig;
58
86
  /** Drizzle ORM lint preset — eslint-plugin-drizzle. */
59
87
  export declare function drizzle(overrides?: Partial<OxlintConfig>): OxlintConfig;
@@ -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;;;;;;;wBC8BG,KAAK,YAAY,QAAQ,gBAAgB;;wBA+FzC,UAAU,YAAY,QAAQ,gBAAgB;;wBAa9C,QAAQ,YAAY,QAAQ,gBAAgB;;wBA6B5C,OAAO,YAAY,QAAQ,gBAAgB;;wBAwB3C,KAAK,YAAY,QAAQ,gBAAgB;;wBAKzC,QAAQ,YAAY,QAAQ,gBAAgB;;;;wBAoB5C,MAAM,YAAY,QAAQ,gBAAgB;;;;;wBAkB1C,eAAe,YAAY,QAAQ,gBAAgB;UAmBzD,wBAAwB,QAAQ;EACxC;EACA;;EAEA;;;wBAIc,SAAS,UAAS,kBAAuB;UAyB/C,sBAAsB,QAAQ;EACtC;;;wBAIc,OAAO,UAAU,gBAAgB;;wBA2CjC,OAAO,YAAY,QAAQ,gBAAgB;;wBA4B3C,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
@@ -70,6 +70,9 @@ const DEFAULT_IGNORES = [
70
70
  "**/.tanstack/**",
71
71
  "**/.vinxi/**",
72
72
  "**/.git/**",
73
+ "**/.svn/**",
74
+ "**/.hg/**",
75
+ "**/.pnp.*",
73
76
  "**/public/**",
74
77
  "**/*.d.ts"
75
78
  ];
@@ -87,6 +90,11 @@ function loadGitignorePatterns() {
87
90
  function preset(defaults, overrides) {
88
91
  return defineConfig$1(defu(overrides ?? {}, defaults));
89
92
  }
93
+ /**
94
+ * Resolve a jsPlugin package name to its absolute path.
95
+ * This allows oxlint to load plugins directly without relying on
96
+ * Node module resolution from the consumer's CWD — fixes pnpm strict mode.
97
+ */
90
98
  function resolvePlugin(name) {
91
99
  try {
92
100
  return require.resolve(name);
@@ -195,7 +203,10 @@ function base(overrides) {
195
203
  ]
196
204
  }, overrides);
197
205
  }
198
- /** Type-aware lint preset — enables 59 type-aware rules via tsgolint. */
206
+ /**
207
+ * Type-aware lint preset — enables 59 type-aware rules via tsgolint + type checking.
208
+ * Requires TypeScript 7.0+ and `oxlint-tsgolint` (bundled as dependency).
209
+ */
199
210
  function typeAware(overrides) {
200
211
  return preset({ options: {
201
212
  typeAware: true,
@@ -250,30 +261,78 @@ function node(overrides) {
250
261
  function promise(overrides) {
251
262
  return preset({ plugins: ["promise"] }, overrides);
252
263
  }
253
- const reactStyleRules = {
254
- "react/jsx-pascal-case": "error",
255
- "react/jsx-boolean-value": "error",
256
- "react/jsx-curly-brace-presence": "error",
257
- "react/jsx-fragments": "error",
258
- "react/self-closing-comp": "error",
259
- "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"
260
304
  };
261
- /**
262
- * React lint preset — React + react-refresh (for Vite/TanStack Start).
263
- */
305
+ /** React lint preset — core React + Hooks rules. */
264
306
  function react(overrides) {
307
+ return preset({
308
+ plugins: ["react"],
309
+ rules: reactRules
310
+ }, overrides);
311
+ }
312
+ /** React + react-refresh preset (for Vite, TanStack Start, etc.). */
313
+ function reactVite(overrides) {
265
314
  return preset({
266
315
  plugins: ["react"],
267
316
  jsPlugins: resolvePlugins(["eslint-plugin-react-refresh"]),
268
317
  rules: {
269
- "react/react-in-jsx-scope": "off",
270
- ...reactStyleRules
318
+ ...reactRules,
319
+ "react-refresh/only-export-components": ["warn", { allowConstantExport: true }]
271
320
  }
272
321
  }, overrides);
273
322
  }
323
+ /** Next.js lint preset — enables native nextjs plugin. */
324
+ function nextjs(overrides) {
325
+ return preset({ plugins: ["nextjs"] }, overrides);
326
+ }
274
327
  /**
275
- * TanStack Router lint preset — loads @tanstack/eslint-plugin-router.
276
- * 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()`
277
336
  */
278
337
  function tanstackRouter(overrides) {
279
338
  return preset({
@@ -283,28 +342,125 @@ function tanstackRouter(overrides) {
283
342
  }]),
284
343
  rules: {
285
344
  "tanstack-router/route-param-names": "error",
286
- "tanstack-router/create-route-property-order": "error"
287
- }
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
+ ]
288
373
  }, overrides);
289
374
  }
290
- /** Tailwind CSS lint preset — eslint-plugin-better-tailwindcss. */
291
- function tailwind(options = {}) {
292
- const { entryPoint = "src/styles/globals.css", rootFontSize = 16, files, ...overrides } = options;
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) {
293
384
  return preset({
294
- jsPlugins: resolvePlugins(["eslint-plugin-better-tailwindcss"]),
295
- settings: { "better-tailwindcss": {
296
- entryPoint,
297
- rootFontSize
298
- } },
299
- overrides: [{
300
- files: files ?? ["**/*.{jsx,tsx}"],
301
- rules: {
302
- "better-tailwindcss/enforce-consistent-line-wrapping": ["error", { printWidth: 0 }],
303
- "better-tailwindcss/enforce-canonical-classes": "error"
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
+ }
304
452
  }
305
- }]
453
+ ]
306
454
  }, overrides);
307
455
  }
456
+ /** Accessibility lint preset — enables native jsx-a11y plugin. */
457
+ function a11y(overrides) {
458
+ return preset({ plugins: ["jsx-a11y"] }, overrides);
459
+ }
460
+ /** JSDoc lint preset — enables native jsdoc plugin. */
461
+ function jsdoc(overrides) {
462
+ return preset({ plugins: ["jsdoc"] }, overrides);
463
+ }
308
464
  /** Vitest lint preset — native vitest plugin with test-file scoping. */
309
465
  function vitest(options) {
310
466
  const { files, ...overrides } = options ?? {};
@@ -340,7 +496,28 @@ function vitest(options) {
340
496
  }]
341
497
  }, overrides);
342
498
  }
343
- /** NestJS lint preset — @darraghor/eslint-plugin-nestjs-typed. */
499
+ /** Tailwind CSS lint preset — eslint-plugin-better-tailwindcss. */
500
+ function tailwind(options = {}) {
501
+ const { entryPoint = "src/styles/globals.css", rootFontSize = 16, files, ...overrides } = options;
502
+ return preset({
503
+ jsPlugins: resolvePlugins(["eslint-plugin-better-tailwindcss"]),
504
+ settings: { "better-tailwindcss": {
505
+ entryPoint,
506
+ rootFontSize
507
+ } },
508
+ overrides: [{
509
+ files: files ?? ["**/*.{jsx,tsx}"],
510
+ rules: {
511
+ "better-tailwindcss/enforce-consistent-line-wrapping": ["error", { printWidth: 0 }],
512
+ "better-tailwindcss/enforce-canonical-classes": "error"
513
+ }
514
+ }]
515
+ }, overrides);
516
+ }
517
+ /**
518
+ * NestJS lint preset — loads @darraghor/eslint-plugin-nestjs-typed via jsPlugin.
519
+ * Covers DI validation, Swagger consistency, decorator bug prevention (19 AST rules).
520
+ */
344
521
  function nestjs(overrides) {
345
522
  return preset({
346
523
  jsPlugins: resolvePlugins([{
@@ -376,6 +553,6 @@ function drizzle(overrides) {
376
553
  }, overrides);
377
554
  }
378
555
  //#endregion
379
- export { GLOB_JS, GLOB_JSON, GLOB_JSX, GLOB_MARKDOWN, GLOB_SRC, GLOB_TESTS, GLOB_TS, base, defineConfig, depend, drizzle, nestjs, node, promise, react, 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 };
380
557
 
381
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 '**/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\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 'no-await-in-loop': 'off',\n 'typescript/prefer-readonly-parameter-types': 'off',\n 'typescript/strict-boolean-expressions': 'off',\n 'max-lines': 'off',\n 'max-lines-per-function': 'off',\n 'no-inline-comments': 'off',\n 'no-warning-comments': 'off',\n 'import/max-dependencies': 'off',\n 'react/no-unescaped-entities': 'off',\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 '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 '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 files: ['**/*.config.{ts,mts,cts,js,mjs,cjs}'],\n rules: {\n 'import/no-relative-parent-imports': 'off',\n },\n },\n {\n files: GLOB_TESTS,\n rules: {\n 'import/first': 'off',\n 'import/no-duplicates': 'off',\n 'import/consistent-type-specifier-style': 'off',\n 'unicorn/no-useless-undefined': 'off',\n 'typescript/no-empty-function': 'off',\n 'unicorn/prefer-string-replace-all': 'off',\n 'unicorn/no-array-callback-reference': 'off',\n 'unicorn/prefer-spread': 'off',\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 'react/no-array-index-key': 'off',\n },\n },\n ],\n },\n overrides,\n )\n}\n\n/** Type-aware lint preset — enables 59 type-aware rules via tsgolint. */\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/**\n * React lint preset — React + react-refresh (for Vite/TanStack Start).\n */\nexport function react(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/**\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// 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// Testing\n// ============================================================================\n\ninterface VitestOptions extends Partial<OxlintConfig> {\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// Backend / ORM\n// ============================================================================\n\n/** NestJS lint preset — @darraghor/eslint-plugin-nestjs-typed. */\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 '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 '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 '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.2.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",