@himynameisdave/oxlint-config 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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Dave Lunny
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,203 @@
1
+ # @himynameisdave/oxlint-config
2
+
3
+ [![npm version](https://img.shields.io/npm/v/%40himynameisdave%2Foxlint-config.svg)](https://www.npmjs.com/package/@himynameisdave/oxlint-config)
4
+ [![license](https://img.shields.io/npm/l/%40himynameisdave%2Foxlint-config.svg)](./LICENSE)
5
+ [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fhimynameisdave%2Foxlint-config.svg?type=shield&issueType=license)](https://app.fossa.com/projects/git%2Bgithub.com%2Fhimynameisdave%2Foxlint-config?ref=badge_shield&issueType=license)
6
+ [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fhimynameisdave%2Foxlint-config.svg?type=shield&issueType=security)](https://app.fossa.com/projects/git%2Bgithub.com%2Fhimynameisdave%2Foxlint-config?ref=badge_shield&issueType=security)
7
+
8
+ > An opinionated [oxlint](https://oxc.rs/docs/guide/usage/linter.html) config, by and for [himynameisdave](https://github.com/himynameisdave).
9
+
10
+ The spiritual successor to [eslint-config-himynameisdave](https://github.com/himynameisdave/eslint-config-himynameisdave), rebuilt for the oxc era. Every rule from every enabled plugin (all ~610 of them) is listed explicitly with a severity and a one-line reason. No category-level magic, no "recommended" black boxes.
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ bun add -D oxlint @himynameisdave/oxlint-config
16
+ ```
17
+
18
+ For type-aware linting (you want this), also grab [`oxlint-tsgolint`](https://github.com/oxc-project/tsgolint):
19
+
20
+ ```bash
21
+ bun add -D oxlint-tsgolint
22
+ ```
23
+
24
+ Not a bun user? It's a regular npm package, so any package manager works:
25
+
26
+ ```bash
27
+ npm install -D oxlint @himynameisdave/oxlint-config
28
+ pnpm add -D oxlint @himynameisdave/oxlint-config
29
+ yarn add -D oxlint @himynameisdave/oxlint-config
30
+ ```
31
+
32
+ - Requires `oxlint >=1.76.0 <2`. Why that range, and how it moves: [Versioning & compatibility](#versioning--compatibility).
33
+ - Type-aware linting requires TypeScript 7+ and a `strict` tsconfig.
34
+
35
+ ## Configurations
36
+
37
+ | Config | Import | What it is |
38
+ | ------------ | ------------------------------------------ | --------------------------------------------------------------------- |
39
+ | `base` | `@himynameisdave/oxlint-config/base` | Core JS/TS rules. No framework assumptions. Start here. |
40
+ | `svelte` | `@himynameisdave/oxlint-config/svelte` | Svelte 5 (runes) overrides for `.svelte`/`.svelte.ts` files. |
41
+ | `type-aware` | `@himynameisdave/oxlint-config/type-aware` | Rules needing type info. Requires `oxlint-tsgolint` + `--type-aware`. |
42
+ | `vitest` | `@himynameisdave/oxlint-config/vitest` | Test-suite rules for Vitest projects (`.only` in CI, etc). |
43
+ | _(default)_ | `@himynameisdave/oxlint-config` | Kitchen sink: all of the above. |
44
+
45
+ ## Usage
46
+
47
+ Composable (a SvelteKit project with type-aware linting):
48
+
49
+ ```ts
50
+ // oxlint.config.ts
51
+ import { defineConfig } from 'oxlint';
52
+ import base from '@himynameisdave/oxlint-config/base';
53
+ import svelte from '@himynameisdave/oxlint-config/svelte';
54
+ import typeAware from '@himynameisdave/oxlint-config/type-aware';
55
+
56
+ export default defineConfig({
57
+ extends: [base, svelte, typeAware],
58
+ rules: {
59
+ // Project-specific overrides go here
60
+ }
61
+ });
62
+ ```
63
+
64
+ All-in-one:
65
+
66
+ ```ts
67
+ // oxlint.config.ts
68
+ import { defineConfig } from 'oxlint';
69
+ import config from '@himynameisdave/oxlint-config';
70
+
71
+ export default defineConfig({
72
+ extends: [config]
73
+ });
74
+ ```
75
+
76
+ Then lint:
77
+
78
+ ```bash
79
+ oxlint -c oxlint.config.ts --deny-warnings
80
+ ```
81
+
82
+ ## Philosophy
83
+
84
+ 1. **Error, never warn.** A rule is either enforced or it's off. Warnings are noise that scrolls by unfixed forever, so run with `--deny-warnings` and nothing can.
85
+ 2. **Explicit over implicit.** Every category is set to `"off"`; every active rule is listed by name. What's enforced is greppable, and rule-change diffs read like changelogs.
86
+ 3. **Comments are mandatory.** Every rule (on _or_ off) has a one-line comment saying _why_. If a decision can't justify itself in one line, it's not a decision yet.
87
+ 4. **Strict by default, escape hatches documented.** The base config assumes you want to be told. Common overrides are listed below, not baked in.
88
+ 5. **No formatting rules.** Whitespace is [oxfmt](https://oxc.rs/docs/guide/usage/formatter.html)'s job. Anything purely about layout is off.
89
+
90
+ ## Versioning & compatibility
91
+
92
+ Version bumps describe what a release does to _your_ CI:
93
+
94
+ - **major**: structural change to what this package _is_. An oxlint major bump, a new plugin enabled, an entry point renamed or removed.
95
+ - **minor**: rule decisions. New rules decided (usually after an oxlint release adds them), an existing rule flipped between `error` and `off`, or options tightened. New errors can appear in code that passed before.
96
+ - **patch**: docs, comments, tooling. No behavior change.
97
+
98
+ Rule churn is deliberately _not_ a major bump. A newly-decided rule and a rule flipped from `off` to `error` break your build in exactly the same way, so pretending one is riskier than the other would just inflate the major number without telling you anything. New errors are the point of the package.
99
+
100
+ `^` accepts new errors on update. Don't want that? Use `~` (patch only) with a committed lockfile, and upgrade deliberately.
101
+
102
+ **Supported oxlint: `>=1.76.0 <2`.** The floor is the version this release's rule inventory was certified against, so it moves whenever new rules are decided. Older oxlint skips rules it doesn't know instead of erroring, which means a stale binary quietly under-lints. The `<2` ceiling is there because an oxlint 2.0 needs a release here anyway.
103
+
104
+ **Type-aware assumes a strict tsconfig.** The `type-aware` config expects `"strict": true`, and does its best work with `"noUncheckedIndexedAccess"`. Without them, rules like `typescript/no-unnecessary-condition` both over- and under-report.
105
+
106
+ **Plugins you add start off.** Every category is `"off"` by design, so adding `plugins: ['react']` to your own config enables zero react rules until you name each one. Surprising once, then greppable forever.
107
+
108
+ ## Enabled plugins
109
+
110
+ `typescript` · `unicorn` · `oxc` · `import` · `promise` · `node` · `jsdoc` (plus the core `eslint` rules) · `vitest` (via the opt-in `vitest` add-on)
111
+
112
+ The `vitest` stance: test suites deserve the same rigor as app code. The flagship rule is `no-focused-tests`: a committed `it.only` makes CI silently green while skipping every other test. The add-on's rules only fire on test-shaped syntax, so extending it is harmless for non-test files. **Not for `bun:test` suites:** oxlint recognizes test functions by import source (`vitest`, `@jest/globals`) or bare globals, and `import { it } from 'bun:test'` is invisible to it (verified empirically; see `src/vitest.ts`). Bun-native suites get no lint coverage until oxlint supports `bun:test` upstream.
113
+
114
+ The `jsdoc` stance: exported symbols should be documented; internal code doesn't have to be. Any JSDoc you _do_ write must be complete and descriptive (a partial `@param` list or a bare `@returns` errors), and types never go in JSDoc (TypeScript owns them). oxlint has no `require-jsdoc` rule yet, so _existence_ of docs on exports stays a review expectation until upstream ships one (this config will adopt it with `publicOnly` when it lands).
115
+
116
+ ## Svelte support
117
+
118
+ The `svelte` config targets **Svelte 5 (runes)**. Svelte 4 / legacy-mode syntax errors by design (nothing here is relaxed to accommodate it), so the base rules flag it like any other unwanted pattern:
119
+
120
+ | Svelte 4 pattern | What errors |
121
+ | --------------------------------- | --------------------------------------------------------------- |
122
+ | `$: doubled = count * 2;` | `eslint/no-labels` (`$:` is a labeled statement to a JS parser) |
123
+ | `$: sideEffect();` | `eslint/no-labels` |
124
+ | `$: someValue;` (bare identifier) | `eslint/no-labels` **and** `eslint/no-unused-expressions` |
125
+ | `export let count = 0;` (props) | `import/no-mutable-exports` |
126
+
127
+ Still shipping legacy components? Relax those three rules in _your_ config, scoped to `.svelte` files so the rest of the codebase keeps the enforcement:
128
+
129
+ ```ts
130
+ // oxlint.config.ts
131
+ import { defineConfig } from 'oxlint';
132
+ import base from '@himynameisdave/oxlint-config/base';
133
+ import svelte from '@himynameisdave/oxlint-config/svelte';
134
+
135
+ export default defineConfig({
136
+ extends: [base, svelte],
137
+ overrides: [
138
+ {
139
+ files: ['**/*.svelte'],
140
+ rules: {
141
+ // Svelte 4 `$:` reactive statements are labeled statements.
142
+ 'eslint/no-labels': 'off',
143
+ // Bare `$: someValue;` reads as an unused expression.
144
+ 'eslint/no-unused-expressions': 'off',
145
+ // `export let` is how Svelte 4 declares component props.
146
+ 'import/no-mutable-exports': 'off'
147
+ }
148
+ }
149
+ ]
150
+ });
151
+ ```
152
+
153
+ `eslint/no-unused-labels` is _not_ in that list: as of oxlint 1.76 it doesn't fire inside `.svelte` files at all (it does in `.ts`). Add it if a future oxlint starts flagging `$:`.
154
+
155
+ SvelteKit route files need no override. `unicorn/filename-case` skips the leading `+` and checks the rest, so `+page.svelte`, `+layout.server.ts` and friends all pass. Only genuinely bad casing after the `+` (`+Bad_Name.ts`) errors.
156
+
157
+ ## Common overrides
158
+
159
+ Things real projects legitimately relax. Add these to _your_ config's `rules`/`overrides`; they don't belong in the shared one:
160
+
161
+ ```ts
162
+ rules: {
163
+ // ORM/bundler underscore conventions (Prisma _count, Vite __APP_VERSION__):
164
+ "eslint/no-underscore-dangle": ["error", { allow: ["__APP_VERSION__", "_count"] }],
165
+ // Framework types that can't be deeply readonly (SvelteKit RequestEvent, Playwright
166
+ // Page/APIRequestContext). Overriding a rule replaces its options wholesale — it does
167
+ // NOT merge — so restate the base config's platform exemptions alongside your additions:
168
+ "typescript/prefer-readonly-parameter-types": ["error", {
169
+ ignoreInferredTypes: true,
170
+ allow: [
171
+ { from: "lib", name: "Date" },
172
+ { from: "lib", name: "URL" },
173
+ { from: "lib", name: "URLSearchParams" },
174
+ { from: "lib", name: "FormData" },
175
+ { from: "lib", name: "Request" },
176
+ { from: "lib", name: "Response" },
177
+ { from: "lib", name: "Headers" },
178
+ { from: "lib", name: "RegExp" },
179
+ "RequestEvent", "Page", "APIRequestContext",
180
+ ],
181
+ }],
182
+ // Codebases that talk to sequential APIs:
183
+ "eslint/no-await-in-loop": "off",
184
+ },
185
+ overrides: [
186
+ // CLI scripts and DB seeds print to stdout and set exit codes by design:
187
+ {
188
+ files: ["scripts/**", "prisma/seed.ts"],
189
+ rules: {
190
+ "eslint/no-console": "off",
191
+ "unicorn/no-process-exit": "off",
192
+ },
193
+ },
194
+ ],
195
+ ```
196
+
197
+ Vendored component code (e.g. shadcn-svelte's `src/lib/components/ui`) predates your lint config. Run `oxlint --fix` over it once (`unicorn/prefer-export-from` and `import/consistent-type-specifier-style` are both auto-fixable), or add the directory to `ignorePatterns` if you'd rather not touch scaffolded files.
198
+
199
+ Generated code and framework configs go in `ignorePatterns` (the base config only ignores build artifacts: `node_modules`, `dist`, `build`, `.svelte-kit`).
200
+
201
+ ## License
202
+
203
+ [MIT](./LICENSE) © [Dave Lunny](https://github.com/himynameisdave)