@letstri/oxc-config 0.1.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 +247 -0
- package/dist/index.d.mts +61 -0
- package/dist/index.mjs +588 -0
- package/package.json +70 -0
package/README.md
ADDED
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
# Oxlint and Oxfmt configs
|
|
2
|
+
|
|
3
|
+
Opinionated, shared [oxlint](https://oxc.rs/docs/guide/usage/linter.html) and [oxfmt](https://oxc.rs) config, in the spirit of [@antfu/eslint-config](https://github.com/antfu/eslint-config).
|
|
4
|
+
|
|
5
|
+
> [!NOTE]
|
|
6
|
+
> This is an **opinionated** config — it ships a curated set of rules and
|
|
7
|
+
> formatting defaults meant to work out of the box. Override anything you
|
|
8
|
+
> disagree with via the [`override`](#overrides) option.
|
|
9
|
+
|
|
10
|
+
## Install
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
pnpm add -D @letstri/oxc-config oxlint oxfmt
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## AI setup prompt
|
|
17
|
+
|
|
18
|
+
Paste this into Claude Code, Cursor, or any coding agent to wire everything up:
|
|
19
|
+
|
|
20
|
+
<details>
|
|
21
|
+
<summary>Show prompt</summary>
|
|
22
|
+
|
|
23
|
+
````text
|
|
24
|
+
Set up @letstri/oxc-config (oxlint + oxfmt) in this project:
|
|
25
|
+
|
|
26
|
+
1. Install dev deps: `@letstri/oxc-config oxlint oxfmt`.
|
|
27
|
+
2. Remove ESLint and Prettier: their configs, deps, and scripts.
|
|
28
|
+
3. Create `oxlint.config.ts`:
|
|
29
|
+
```ts
|
|
30
|
+
import { oxlintConfig } from '@letstri/oxc-config'
|
|
31
|
+
|
|
32
|
+
export default oxlintConfig()
|
|
33
|
+
```
|
|
34
|
+
4. Create `oxfmt.config.ts`:
|
|
35
|
+
```ts
|
|
36
|
+
import { oxfmtConfig } from '@letstri/oxc-config'
|
|
37
|
+
|
|
38
|
+
export default oxfmtConfig()
|
|
39
|
+
```
|
|
40
|
+
5. Add package.json scripts:
|
|
41
|
+
- "lint": "oxlint"
|
|
42
|
+
- "lint:fix": "oxlint --fix"
|
|
43
|
+
- "format": "oxfmt"
|
|
44
|
+
- "format:check": "oxfmt --check"
|
|
45
|
+
6. Framework plugins auto-enable from the nearest package.json. If a framework
|
|
46
|
+
dep (react/vue/next/vitest/jest/typescript) lives in a nested workspace,
|
|
47
|
+
enable it manually, e.g. `oxlintConfig({ vue: true })`.
|
|
48
|
+
7. Add the VS Code and Zed editor settings from the @letstri/oxc-config README.
|
|
49
|
+
8. Run `pnpm lint` and `pnpm format` and fix anything reported.
|
|
50
|
+
````
|
|
51
|
+
|
|
52
|
+
</details>
|
|
53
|
+
|
|
54
|
+
## Usage
|
|
55
|
+
|
|
56
|
+
`oxlint.config.ts`:
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
import { oxlintConfig } from '@letstri/oxc-config'
|
|
60
|
+
|
|
61
|
+
export default oxlintConfig()
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
`oxfmt.config.ts`:
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
import { oxfmtConfig } from '@letstri/oxc-config'
|
|
68
|
+
|
|
69
|
+
export default oxfmtConfig()
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Plugins
|
|
73
|
+
|
|
74
|
+
Framework plugins are enabled automatically by detecting dependencies in the
|
|
75
|
+
nearest `package.json` (`typescript`, `react`, `vue`, `next`, `vitest`, `jest`,
|
|
76
|
+
`tailwind`). Toggle any of them manually — useful when the dependency lives in a
|
|
77
|
+
nested workspace such as `apps/web/package.json`:
|
|
78
|
+
|
|
79
|
+
```ts
|
|
80
|
+
export default oxlintConfig({
|
|
81
|
+
vue: true, // force on
|
|
82
|
+
jest: false, // force off
|
|
83
|
+
})
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Tailwind
|
|
87
|
+
|
|
88
|
+
`tailwind: true` enables [`eslint-plugin-better-tailwindcss`](https://github.com/schoero/eslint-plugin-better-tailwindcss)
|
|
89
|
+
(auto-detected from a `tailwindcss` dependency). The plugin is an **optional peer
|
|
90
|
+
dependency** — install it yourself:
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
pnpm add -D eslint-plugin-better-tailwindcss
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
If Tailwind is enabled but the plugin is missing, the config logs a reminder and
|
|
97
|
+
skips Tailwind linting instead of crashing. Point the plugin at your Tailwind
|
|
98
|
+
entry CSS so it can resolve class names:
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
export default oxlintConfig({
|
|
102
|
+
tailwind: true,
|
|
103
|
+
override: {
|
|
104
|
+
settings: {
|
|
105
|
+
'better-tailwindcss': {
|
|
106
|
+
entryPoint: 'src/styles/globals.css',
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
})
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Overrides
|
|
114
|
+
|
|
115
|
+
`override` is deep-merged over the base config via [defu](https://github.com/unjs/defu):
|
|
116
|
+
|
|
117
|
+
```ts
|
|
118
|
+
export default oxlintConfig({
|
|
119
|
+
override: {
|
|
120
|
+
rules: {
|
|
121
|
+
'no-console': 'off',
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
})
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Editor setup
|
|
128
|
+
|
|
129
|
+
Both editors use the official [oxc](https://oxc.rs) tooling — `oxlint` for
|
|
130
|
+
linting and `oxfmt` for formatting — replacing ESLint and Prettier.
|
|
131
|
+
|
|
132
|
+
### VS Code
|
|
133
|
+
|
|
134
|
+
Install the [`oxc.oxc-vscode`](https://marketplace.visualstudio.com/items?itemName=oxc.oxc-vscode)
|
|
135
|
+
extension.
|
|
136
|
+
|
|
137
|
+
<details>
|
|
138
|
+
<summary>Show VS Code config</summary>
|
|
139
|
+
|
|
140
|
+
`.vscode/extensions.json`:
|
|
141
|
+
|
|
142
|
+
```json
|
|
143
|
+
{
|
|
144
|
+
"recommendations": ["oxc.oxc-vscode"]
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
`.vscode/settings.json`:
|
|
149
|
+
|
|
150
|
+
```jsonc
|
|
151
|
+
{
|
|
152
|
+
"oxc.configPath": "oxlint.config.ts",
|
|
153
|
+
"oxc.fmt.configPath": "oxfmt.config.ts",
|
|
154
|
+
"oxc.typeAware": true,
|
|
155
|
+
"oxc.unusedDisableDirectives": "deny",
|
|
156
|
+
"oxc.enable": true,
|
|
157
|
+
"prettier.enable": false,
|
|
158
|
+
"editor.defaultFormatter": "oxc.oxc-vscode",
|
|
159
|
+
"editor.formatOnSave": true,
|
|
160
|
+
"editor.formatOnSaveMode": "file", // oxfmt can only format whole files
|
|
161
|
+
"editor.codeActionsOnSave": {
|
|
162
|
+
"source.fixAll.oxc": "explicit",
|
|
163
|
+
"source.organizeImports": "never", // let oxfmt handle import organization
|
|
164
|
+
},
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
</details>
|
|
169
|
+
|
|
170
|
+
### Zed
|
|
171
|
+
|
|
172
|
+
Zed ships with the oxc language servers built in.
|
|
173
|
+
|
|
174
|
+
<details>
|
|
175
|
+
<summary>Show Zed config</summary>
|
|
176
|
+
|
|
177
|
+
`.zed/settings.json`:
|
|
178
|
+
|
|
179
|
+
```jsonc
|
|
180
|
+
{
|
|
181
|
+
"lsp": {
|
|
182
|
+
"oxlint": {
|
|
183
|
+
"initialization_options": {
|
|
184
|
+
"settings": {
|
|
185
|
+
"configPath": null,
|
|
186
|
+
"run": "onType",
|
|
187
|
+
"disableNestedConfig": false,
|
|
188
|
+
"fixKind": "safe_fix",
|
|
189
|
+
"unusedDisableDirectives": "deny",
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
"oxfmt": {
|
|
194
|
+
"initialization_options": {
|
|
195
|
+
"settings": {
|
|
196
|
+
"fmt.configPath": null,
|
|
197
|
+
"run": "onSave",
|
|
198
|
+
},
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
},
|
|
202
|
+
"languages": {
|
|
203
|
+
"TypeScript": {
|
|
204
|
+
"format_on_save": "on",
|
|
205
|
+
"prettier": { "allowed": false },
|
|
206
|
+
"language_servers": ["...", "oxlint", "oxfmt"],
|
|
207
|
+
"formatter": [
|
|
208
|
+
{ "language_server": { "name": "oxfmt" } },
|
|
209
|
+
{ "code_action": "source.fixAll.oxc" },
|
|
210
|
+
],
|
|
211
|
+
},
|
|
212
|
+
"TSX": {
|
|
213
|
+
"format_on_save": "on",
|
|
214
|
+
"prettier": { "allowed": false },
|
|
215
|
+
"language_servers": ["...", "oxlint", "oxfmt"],
|
|
216
|
+
"formatter": [
|
|
217
|
+
{ "language_server": { "name": "oxfmt" } },
|
|
218
|
+
{ "code_action": "source.fixAll.oxc" },
|
|
219
|
+
],
|
|
220
|
+
},
|
|
221
|
+
"JavaScript": {
|
|
222
|
+
"format_on_save": "on",
|
|
223
|
+
"prettier": { "allowed": false },
|
|
224
|
+
"language_servers": ["...", "oxlint", "oxfmt"],
|
|
225
|
+
"formatter": [
|
|
226
|
+
{ "language_server": { "name": "oxfmt" } },
|
|
227
|
+
{ "code_action": "source.fixAll.oxc" },
|
|
228
|
+
],
|
|
229
|
+
},
|
|
230
|
+
"JSON": {
|
|
231
|
+
"format_on_save": "on",
|
|
232
|
+
"prettier": { "allowed": false },
|
|
233
|
+
"formatter": [{ "language_server": { "name": "oxfmt" } }],
|
|
234
|
+
},
|
|
235
|
+
"Markdown": {
|
|
236
|
+
"format_on_save": "on",
|
|
237
|
+
"prettier": { "allowed": false },
|
|
238
|
+
"formatter": [{ "language_server": { "name": "oxfmt" } }],
|
|
239
|
+
},
|
|
240
|
+
},
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
Apply the same `languages` block to any other file types you want oxfmt to
|
|
245
|
+
format (`JSONC`, `CSS`, `HTML`, `YAML`, …).
|
|
246
|
+
|
|
247
|
+
</details>
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { defineConfig } from "oxfmt";
|
|
2
|
+
import { defineConfig as defineConfig$1 } from "oxlint";
|
|
3
|
+
//#region src/index.d.ts
|
|
4
|
+
type OxlintOptions = Parameters<typeof defineConfig$1>[0];
|
|
5
|
+
type OxfmtOptions = Parameters<typeof defineConfig>[0];
|
|
6
|
+
declare const pluginToggles: {
|
|
7
|
+
typescript: {
|
|
8
|
+
packages: string[];
|
|
9
|
+
plugins: "typescript"[];
|
|
10
|
+
};
|
|
11
|
+
react: {
|
|
12
|
+
packages: string[];
|
|
13
|
+
plugins: ("react" | "jsx-a11y" | "react-perf")[];
|
|
14
|
+
};
|
|
15
|
+
vue: {
|
|
16
|
+
packages: string[];
|
|
17
|
+
plugins: "vue"[];
|
|
18
|
+
};
|
|
19
|
+
next: {
|
|
20
|
+
packages: string[];
|
|
21
|
+
plugins: "nextjs"[];
|
|
22
|
+
};
|
|
23
|
+
vitest: {
|
|
24
|
+
packages: string[];
|
|
25
|
+
plugins: "vitest"[];
|
|
26
|
+
};
|
|
27
|
+
jest: {
|
|
28
|
+
packages: string[];
|
|
29
|
+
plugins: "jest"[];
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
type ToggleName = keyof typeof pluginToggles;
|
|
33
|
+
interface OxlintConfigOptions extends Partial<Record<ToggleName, boolean>> {
|
|
34
|
+
/**
|
|
35
|
+
* Enable `eslint-plugin-better-tailwindcss`. Auto-detected from a `tailwindcss`
|
|
36
|
+
* dependency; set it explicitly when Tailwind lives in a nested workspace.
|
|
37
|
+
*
|
|
38
|
+
* The plugin is an optional peer dependency — install it yourself
|
|
39
|
+
* (`pnpm add -D eslint-plugin-better-tailwindcss`). If it is missing, a warning
|
|
40
|
+
* is logged and Tailwind linting is skipped. Point the plugin at your entry
|
|
41
|
+
* CSS via `override.settings`.
|
|
42
|
+
*/
|
|
43
|
+
tailwind?: boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Deep-merged over the base config via defu.
|
|
46
|
+
*/
|
|
47
|
+
override?: OxlintOptions;
|
|
48
|
+
/**
|
|
49
|
+
* Directory whose `package.json` is scanned to auto-detect plugins.
|
|
50
|
+
*
|
|
51
|
+
* @default process.cwd()
|
|
52
|
+
*/
|
|
53
|
+
cwd?: string;
|
|
54
|
+
}
|
|
55
|
+
interface OxfmtConfigOptions {
|
|
56
|
+
override?: OxfmtOptions;
|
|
57
|
+
}
|
|
58
|
+
declare function oxlintConfig(options?: OxlintConfigOptions): OxlintOptions;
|
|
59
|
+
declare function oxfmtConfig({ override }?: OxfmtConfigOptions): OxfmtOptions;
|
|
60
|
+
//#endregion
|
|
61
|
+
export { oxfmtConfig, oxlintConfig };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,588 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import process from "node:process";
|
|
4
|
+
import { defu } from "defu";
|
|
5
|
+
import { defineConfig } from "oxfmt";
|
|
6
|
+
import { defineConfig as defineConfig$1 } from "oxlint";
|
|
7
|
+
//#region src/index.ts
|
|
8
|
+
const baseOxlintConfig = defineConfig$1({
|
|
9
|
+
categories: {
|
|
10
|
+
correctness: "error",
|
|
11
|
+
suspicious: "warn",
|
|
12
|
+
perf: "warn"
|
|
13
|
+
},
|
|
14
|
+
env: {
|
|
15
|
+
builtin: true,
|
|
16
|
+
es2026: true,
|
|
17
|
+
browser: true,
|
|
18
|
+
node: true
|
|
19
|
+
},
|
|
20
|
+
globals: {
|
|
21
|
+
AudioPlaybackStats: "readonly",
|
|
22
|
+
CSSFontFaceDescriptors: "readonly",
|
|
23
|
+
CSSPseudoElement: "readonly",
|
|
24
|
+
LanguageModel: "readonly",
|
|
25
|
+
ModelContext: "readonly",
|
|
26
|
+
Sanitizer: "readonly",
|
|
27
|
+
TimelineTrigger: "readonly",
|
|
28
|
+
TimelineTriggerRange: "readonly",
|
|
29
|
+
TimelineTriggerRangeList: "readonly",
|
|
30
|
+
WebMCPEvent: "readonly",
|
|
31
|
+
XRCompositionLayer: "readonly",
|
|
32
|
+
XRCubeLayer: "readonly",
|
|
33
|
+
XRCylinderLayer: "readonly",
|
|
34
|
+
XREquirectLayer: "readonly",
|
|
35
|
+
XRLayerEvent: "readonly",
|
|
36
|
+
XRPlane: "readonly",
|
|
37
|
+
XRPlaneSet: "readonly",
|
|
38
|
+
XRProjectionLayer: "readonly",
|
|
39
|
+
XRQuadLayer: "readonly",
|
|
40
|
+
XRSubImage: "readonly",
|
|
41
|
+
XRWebGLSubImage: "readonly"
|
|
42
|
+
},
|
|
43
|
+
ignorePatterns: [
|
|
44
|
+
"**/.DS_Store",
|
|
45
|
+
"**/node_modules",
|
|
46
|
+
"**/.turbo",
|
|
47
|
+
"**/*.tsbuildinfo",
|
|
48
|
+
"**/.idea",
|
|
49
|
+
"**/.node-modules-inspector",
|
|
50
|
+
"**/.pnpm-store",
|
|
51
|
+
"**/dist",
|
|
52
|
+
"**/package-lock.json",
|
|
53
|
+
"**/yarn.lock",
|
|
54
|
+
"**/pnpm-lock.yaml",
|
|
55
|
+
"**/bun.lockb",
|
|
56
|
+
"**/output",
|
|
57
|
+
"**/coverage",
|
|
58
|
+
"**/temp",
|
|
59
|
+
"**/.temp",
|
|
60
|
+
"**/tmp",
|
|
61
|
+
"**/.tmp",
|
|
62
|
+
"**/.history",
|
|
63
|
+
"**/.vitepress/cache",
|
|
64
|
+
"**/.nuxt",
|
|
65
|
+
"**/.next",
|
|
66
|
+
"**/.svelte-kit",
|
|
67
|
+
"**/.vercel",
|
|
68
|
+
"**/.changeset",
|
|
69
|
+
"**/.cache",
|
|
70
|
+
"**/.output",
|
|
71
|
+
"**/.vite-inspect",
|
|
72
|
+
"**/.yarn",
|
|
73
|
+
"**/CHANGELOG*.md",
|
|
74
|
+
"**/LICENSE*",
|
|
75
|
+
"**/*.min.*",
|
|
76
|
+
"**/__snapshots__",
|
|
77
|
+
"**/vite.config.*.timestamp-*",
|
|
78
|
+
"**/auto-import?(s).d.ts",
|
|
79
|
+
"**/components.d.ts",
|
|
80
|
+
"**/.context",
|
|
81
|
+
"**/.claude",
|
|
82
|
+
"**/.agents",
|
|
83
|
+
"**/.*/skills",
|
|
84
|
+
"**/*.md",
|
|
85
|
+
"**/routeTree.gen.ts",
|
|
86
|
+
"**/release/**/*",
|
|
87
|
+
"**/.tanstack/**/*",
|
|
88
|
+
"**/.nitro/**/*",
|
|
89
|
+
"**/.output/**/*",
|
|
90
|
+
"**/.source/**/*",
|
|
91
|
+
"**/dist-electron/**/*",
|
|
92
|
+
"**/dist-desktop/**/*",
|
|
93
|
+
"**/playwright-report/**/*",
|
|
94
|
+
"**/test-results/**/*",
|
|
95
|
+
"**/.types/**/*",
|
|
96
|
+
"**/migrations/**/*",
|
|
97
|
+
"**/migrations.json"
|
|
98
|
+
],
|
|
99
|
+
rules: {
|
|
100
|
+
"accessor-pairs": ["error", {
|
|
101
|
+
enforceForClassMembers: true,
|
|
102
|
+
setWithoutGet: true
|
|
103
|
+
}],
|
|
104
|
+
"array-callback-return": "error",
|
|
105
|
+
"block-scoped-var": "error",
|
|
106
|
+
"constructor-super": "error",
|
|
107
|
+
"default-case-last": "error",
|
|
108
|
+
"eqeqeq": ["error", "smart"],
|
|
109
|
+
"new-cap": ["error", {
|
|
110
|
+
capIsNew: false,
|
|
111
|
+
newIsCap: true,
|
|
112
|
+
properties: true
|
|
113
|
+
}],
|
|
114
|
+
"no-alert": "error",
|
|
115
|
+
"no-array-constructor": "error",
|
|
116
|
+
"no-async-promise-executor": "error",
|
|
117
|
+
"no-caller": "error",
|
|
118
|
+
"no-case-declarations": "error",
|
|
119
|
+
"no-class-assign": "error",
|
|
120
|
+
"no-compare-neg-zero": "error",
|
|
121
|
+
"no-cond-assign": ["error", "always"],
|
|
122
|
+
"no-console": ["warn", { allow: ["warn", "error"] }],
|
|
123
|
+
"no-const-assign": "error",
|
|
124
|
+
"no-control-regex": "error",
|
|
125
|
+
"no-debugger": "error",
|
|
126
|
+
"no-delete-var": "error",
|
|
127
|
+
"no-dupe-class-members": "error",
|
|
128
|
+
"no-dupe-keys": "error",
|
|
129
|
+
"no-duplicate-case": "error",
|
|
130
|
+
"no-empty": ["error", { allowEmptyCatch: true }],
|
|
131
|
+
"no-empty-pattern": "error",
|
|
132
|
+
"no-eval": "error",
|
|
133
|
+
"no-ex-assign": "error",
|
|
134
|
+
"no-extend-native": "error",
|
|
135
|
+
"no-extra-bind": "error",
|
|
136
|
+
"no-extra-boolean-cast": "error",
|
|
137
|
+
"no-fallthrough": "error",
|
|
138
|
+
"no-func-assign": "error",
|
|
139
|
+
"no-global-assign": "error",
|
|
140
|
+
"no-implied-eval": "error",
|
|
141
|
+
"no-import-assign": "error",
|
|
142
|
+
"no-irregular-whitespace": "error",
|
|
143
|
+
"no-iterator": "error",
|
|
144
|
+
"no-labels": ["error", {
|
|
145
|
+
allowLoop: false,
|
|
146
|
+
allowSwitch: false
|
|
147
|
+
}],
|
|
148
|
+
"no-lone-blocks": "error",
|
|
149
|
+
"no-loss-of-precision": "error",
|
|
150
|
+
"no-misleading-character-class": "error",
|
|
151
|
+
"no-multi-str": "error",
|
|
152
|
+
"no-new": "error",
|
|
153
|
+
"no-new-func": "error",
|
|
154
|
+
"no-new-native-nonconstructor": "error",
|
|
155
|
+
"no-new-wrappers": "error",
|
|
156
|
+
"no-obj-calls": "error",
|
|
157
|
+
"no-proto": "error",
|
|
158
|
+
"no-prototype-builtins": "error",
|
|
159
|
+
"no-redeclare": ["error", { builtinGlobals: false }],
|
|
160
|
+
"no-regex-spaces": "error",
|
|
161
|
+
"no-restricted-globals": [
|
|
162
|
+
"error",
|
|
163
|
+
{
|
|
164
|
+
message: "Use `globalThis` instead.",
|
|
165
|
+
name: "global"
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
message: "Use `globalThis` instead.",
|
|
169
|
+
name: "self"
|
|
170
|
+
}
|
|
171
|
+
],
|
|
172
|
+
"no-restricted-properties": [
|
|
173
|
+
"error",
|
|
174
|
+
{
|
|
175
|
+
message: "Use `Object.getPrototypeOf` or `Object.setPrototypeOf` instead.",
|
|
176
|
+
property: "__proto__"
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
message: "Use `Object.defineProperty` instead.",
|
|
180
|
+
property: "__defineGetter__"
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
message: "Use `Object.defineProperty` instead.",
|
|
184
|
+
property: "__defineSetter__"
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
message: "Use `Object.getOwnPropertyDescriptor` instead.",
|
|
188
|
+
property: "__lookupGetter__"
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
message: "Use `Object.getOwnPropertyDescriptor` instead.",
|
|
192
|
+
property: "__lookupSetter__"
|
|
193
|
+
}
|
|
194
|
+
],
|
|
195
|
+
"no-self-assign": ["error", { props: true }],
|
|
196
|
+
"no-self-compare": "error",
|
|
197
|
+
"no-sequences": "error",
|
|
198
|
+
"no-shadow": "off",
|
|
199
|
+
"no-shadow-restricted-names": "error",
|
|
200
|
+
"no-sparse-arrays": "error",
|
|
201
|
+
"no-template-curly-in-string": "error",
|
|
202
|
+
"no-this-before-super": "error",
|
|
203
|
+
"no-throw-literal": "error",
|
|
204
|
+
"no-underscore-dangle": ["warn", { allow: [
|
|
205
|
+
"__filename",
|
|
206
|
+
"__dirname",
|
|
207
|
+
"_url",
|
|
208
|
+
"_URL"
|
|
209
|
+
] }],
|
|
210
|
+
"no-unexpected-multiline": "error",
|
|
211
|
+
"no-unmodified-loop-condition": "error",
|
|
212
|
+
"no-unneeded-ternary": ["error", { defaultAssignment: false }],
|
|
213
|
+
"no-unreachable": "error",
|
|
214
|
+
"no-unsafe-finally": "error",
|
|
215
|
+
"no-unsafe-negation": "error",
|
|
216
|
+
"no-unused-expressions": ["error", {
|
|
217
|
+
allowShortCircuit: true,
|
|
218
|
+
allowTaggedTemplates: true,
|
|
219
|
+
allowTernary: true
|
|
220
|
+
}],
|
|
221
|
+
"no-unused-vars": ["error", {
|
|
222
|
+
args: "none",
|
|
223
|
+
argsIgnorePattern: "^_",
|
|
224
|
+
caughtErrors: "none",
|
|
225
|
+
ignoreRestSiblings: true,
|
|
226
|
+
vars: "all",
|
|
227
|
+
varsIgnorePattern: "^_"
|
|
228
|
+
}],
|
|
229
|
+
"no-use-before-define": ["error", {
|
|
230
|
+
classes: false,
|
|
231
|
+
functions: false,
|
|
232
|
+
variables: true
|
|
233
|
+
}],
|
|
234
|
+
"no-useless-call": "error",
|
|
235
|
+
"no-useless-catch": "error",
|
|
236
|
+
"no-useless-computed-key": "error",
|
|
237
|
+
"no-useless-constructor": "error",
|
|
238
|
+
"no-useless-rename": "error",
|
|
239
|
+
"no-useless-return": "error",
|
|
240
|
+
"no-var": "error",
|
|
241
|
+
"no-with": "error",
|
|
242
|
+
"object-shorthand": [
|
|
243
|
+
"error",
|
|
244
|
+
"always",
|
|
245
|
+
{
|
|
246
|
+
avoidQuotes: true,
|
|
247
|
+
ignoreConstructors: false
|
|
248
|
+
}
|
|
249
|
+
],
|
|
250
|
+
"prefer-const": ["error", {
|
|
251
|
+
destructuring: "all",
|
|
252
|
+
ignoreReadBeforeAssign: true
|
|
253
|
+
}],
|
|
254
|
+
"prefer-exponentiation-operator": "error",
|
|
255
|
+
"prefer-promise-reject-errors": "error",
|
|
256
|
+
"prefer-regex-literals": ["error", { disallowRedundantWrapping: true }],
|
|
257
|
+
"prefer-rest-params": "error",
|
|
258
|
+
"prefer-spread": "error",
|
|
259
|
+
"prefer-template": "error",
|
|
260
|
+
"symbol-description": "error",
|
|
261
|
+
"unicode-bom": ["error", "never"],
|
|
262
|
+
"use-isnan": ["error", {
|
|
263
|
+
enforceForIndexOf: true,
|
|
264
|
+
enforceForSwitchCase: true
|
|
265
|
+
}],
|
|
266
|
+
"valid-typeof": ["error", { requireStringLiterals: true }],
|
|
267
|
+
"vars-on-top": "error",
|
|
268
|
+
"yoda": ["error", "never"],
|
|
269
|
+
"import/consistent-type-specifier-style": ["error", "prefer-top-level"],
|
|
270
|
+
"import/first": "error",
|
|
271
|
+
"import/no-duplicates": "error",
|
|
272
|
+
"import/no-mutable-exports": "error",
|
|
273
|
+
"import/no-named-default": "error",
|
|
274
|
+
"import/no-unassigned-import": "off",
|
|
275
|
+
"import/newline-after-import": ["error", { count: 1 }],
|
|
276
|
+
"no-unassigned-vars": "warn",
|
|
277
|
+
"preserve-caught-error": "warn",
|
|
278
|
+
"react/react-in-jsx-scope": "off",
|
|
279
|
+
"jsx-a11y/anchor-has-content": "warn",
|
|
280
|
+
"jsx-a11y/click-events-have-key-events": "warn",
|
|
281
|
+
"jsx-a11y/control-has-associated-label": "warn",
|
|
282
|
+
"jsx-a11y/interactive-supports-focus": "warn",
|
|
283
|
+
"jsx-a11y/label-has-associated-control": "warn",
|
|
284
|
+
"jsx-a11y/mouse-events-have-key-events": "warn",
|
|
285
|
+
"jsx-a11y/no-autofocus": "off",
|
|
286
|
+
"jsx-a11y/no-noninteractive-element-interactions": "warn",
|
|
287
|
+
"jsx-a11y/no-noninteractive-tabindex": "warn",
|
|
288
|
+
"jsx-a11y/no-redundant-roles": "warn",
|
|
289
|
+
"jsx-a11y/no-static-element-interactions": "warn",
|
|
290
|
+
"jsx-a11y/prefer-tag-over-role": "warn",
|
|
291
|
+
"react/rules-of-hooks": "error",
|
|
292
|
+
"react/exhaustive-deps": ["warn", { additionalHooks: "(useMountedEffect)" }],
|
|
293
|
+
"typescript/no-explicit-any": "error"
|
|
294
|
+
},
|
|
295
|
+
overrides: [
|
|
296
|
+
{
|
|
297
|
+
files: ["**/*.?([cm])[jt]s?(x)"],
|
|
298
|
+
rules: {
|
|
299
|
+
"node/handle-callback-err": ["error", "^(err|error)$"],
|
|
300
|
+
"node/no-exports-assign": "error",
|
|
301
|
+
"node/no-new-require": "error",
|
|
302
|
+
"node/no-path-concat": "error",
|
|
303
|
+
"jsdoc/check-access": "warn",
|
|
304
|
+
"jsdoc/check-property-names": "warn",
|
|
305
|
+
"jsdoc/empty-tags": "warn",
|
|
306
|
+
"jsdoc/implements-on-classes": "warn",
|
|
307
|
+
"jsdoc/no-defaults": "warn",
|
|
308
|
+
"jsdoc/require-param-name": "warn",
|
|
309
|
+
"jsdoc/require-property": "warn",
|
|
310
|
+
"jsdoc/require-property-description": "warn",
|
|
311
|
+
"jsdoc/require-property-name": "warn",
|
|
312
|
+
"jsdoc/require-returns-description": "warn",
|
|
313
|
+
"unicorn/consistent-empty-array-spread": "error",
|
|
314
|
+
"unicorn/error-message": "error",
|
|
315
|
+
"unicorn/escape-case": "error",
|
|
316
|
+
"unicorn/new-for-builtins": "error",
|
|
317
|
+
"unicorn/no-instanceof-builtins": "error",
|
|
318
|
+
"unicorn/no-new-array": "error",
|
|
319
|
+
"unicorn/no-new-buffer": "error",
|
|
320
|
+
"unicorn/number-literal-case": "error",
|
|
321
|
+
"unicorn/prefer-dom-node-text-content": "error",
|
|
322
|
+
"unicorn/prefer-includes": "error",
|
|
323
|
+
"unicorn/prefer-node-protocol": "error",
|
|
324
|
+
"unicorn/prefer-number-properties": "error",
|
|
325
|
+
"unicorn/prefer-string-starts-ends-with": "error",
|
|
326
|
+
"unicorn/prefer-type-error": "error",
|
|
327
|
+
"unicorn/throw-new-error": "error"
|
|
328
|
+
},
|
|
329
|
+
plugins: [
|
|
330
|
+
"node",
|
|
331
|
+
"jsdoc",
|
|
332
|
+
"unicorn"
|
|
333
|
+
]
|
|
334
|
+
},
|
|
335
|
+
{
|
|
336
|
+
files: ["**/*.?([cm])ts", "**/*.?([cm])tsx"],
|
|
337
|
+
rules: {
|
|
338
|
+
"constructor-super": "off",
|
|
339
|
+
"getter-return": "off",
|
|
340
|
+
"no-class-assign": "off",
|
|
341
|
+
"no-const-assign": "off",
|
|
342
|
+
"no-dupe-keys": "off",
|
|
343
|
+
"no-func-assign": "off",
|
|
344
|
+
"no-import-assign": "off",
|
|
345
|
+
"no-new-native-nonconstructor": "off",
|
|
346
|
+
"no-obj-calls": "off",
|
|
347
|
+
"no-redeclare": ["error", { builtinGlobals: false }],
|
|
348
|
+
"no-setter-return": "off",
|
|
349
|
+
"no-this-before-super": "off",
|
|
350
|
+
"no-unreachable": "off",
|
|
351
|
+
"no-unsafe-negation": "off",
|
|
352
|
+
"no-with": "off",
|
|
353
|
+
"prefer-const": ["error", {
|
|
354
|
+
destructuring: "all",
|
|
355
|
+
ignoreReadBeforeAssign: true
|
|
356
|
+
}],
|
|
357
|
+
"no-unused-expressions": ["error", {
|
|
358
|
+
allowShortCircuit: true,
|
|
359
|
+
allowTaggedTemplates: true,
|
|
360
|
+
allowTernary: true
|
|
361
|
+
}],
|
|
362
|
+
"no-unused-vars": "off",
|
|
363
|
+
"no-useless-constructor": "off",
|
|
364
|
+
"no-use-before-define": ["error", {
|
|
365
|
+
classes: false,
|
|
366
|
+
functions: false,
|
|
367
|
+
variables: true
|
|
368
|
+
}],
|
|
369
|
+
"typescript/ban-ts-comment": ["error", { "ts-expect-error": "allow-with-description" }],
|
|
370
|
+
"typescript/no-duplicate-enum-values": "error",
|
|
371
|
+
"typescript/no-dynamic-delete": "off",
|
|
372
|
+
"typescript/no-empty-object-type": ["error", { allowInterfaces: "always" }],
|
|
373
|
+
"typescript/no-extra-non-null-assertion": "error",
|
|
374
|
+
"typescript/no-extraneous-class": "off",
|
|
375
|
+
"typescript/no-invalid-void-type": "off",
|
|
376
|
+
"typescript/no-misused-new": "error",
|
|
377
|
+
"typescript/no-namespace": "error",
|
|
378
|
+
"typescript/no-non-null-asserted-nullish-coalescing": "error",
|
|
379
|
+
"typescript/no-non-null-asserted-optional-chain": "error",
|
|
380
|
+
"typescript/no-non-null-assertion": "off",
|
|
381
|
+
"typescript/no-require-imports": "error",
|
|
382
|
+
"typescript/no-this-alias": "error",
|
|
383
|
+
"typescript/no-unnecessary-type-constraint": "error",
|
|
384
|
+
"typescript/no-unsafe-declaration-merging": "error",
|
|
385
|
+
"typescript/no-unsafe-function-type": "error",
|
|
386
|
+
"typescript/no-wrapper-object-types": "error",
|
|
387
|
+
"typescript/prefer-as-const": "error",
|
|
388
|
+
"typescript/prefer-literal-enum-member": "error",
|
|
389
|
+
"typescript/prefer-namespace-keyword": "error",
|
|
390
|
+
"typescript/triple-slash-reference": "off",
|
|
391
|
+
"typescript/unified-signatures": "off",
|
|
392
|
+
"typescript/consistent-type-definitions": ["error", "interface"],
|
|
393
|
+
"typescript/consistent-type-imports": ["error", {
|
|
394
|
+
disallowTypeAnnotations: false,
|
|
395
|
+
fixStyle: "separate-type-imports",
|
|
396
|
+
prefer: "type-imports"
|
|
397
|
+
}],
|
|
398
|
+
"typescript/method-signature-style": ["error", "property"],
|
|
399
|
+
"typescript/no-import-type-side-effects": "error"
|
|
400
|
+
}
|
|
401
|
+
},
|
|
402
|
+
{
|
|
403
|
+
files: [
|
|
404
|
+
"**/__tests__/**/*.?([cm])[jt]s?(x)",
|
|
405
|
+
"**/*.spec.?([cm])[jt]s?(x)",
|
|
406
|
+
"**/*.test.?([cm])[jt]s?(x)",
|
|
407
|
+
"**/*.bench.?([cm])[jt]s?(x)",
|
|
408
|
+
"**/*.benchmark.?([cm])[jt]s?(x)"
|
|
409
|
+
],
|
|
410
|
+
rules: {
|
|
411
|
+
"vitest/consistent-test-it": ["error", {
|
|
412
|
+
fn: "it",
|
|
413
|
+
withinDescribe: "it"
|
|
414
|
+
}],
|
|
415
|
+
"vitest/no-identical-title": "error",
|
|
416
|
+
"vitest/no-import-node-test": "error",
|
|
417
|
+
"vitest/prefer-hooks-in-order": "error",
|
|
418
|
+
"vitest/prefer-lowercase-title": "error",
|
|
419
|
+
"no-unused-expressions": "off",
|
|
420
|
+
"typescript/explicit-function-return-type": "off"
|
|
421
|
+
},
|
|
422
|
+
plugins: ["vitest"]
|
|
423
|
+
},
|
|
424
|
+
{
|
|
425
|
+
files: ["**/*.?([cm])[jt]s?(x)"],
|
|
426
|
+
rules: {
|
|
427
|
+
"react/no-array-index-key": "warn",
|
|
428
|
+
"react/no-clone-element": "warn",
|
|
429
|
+
"react/no-direct-mutation-state": "error",
|
|
430
|
+
"react/jsx-no-comment-textnodes": "warn",
|
|
431
|
+
"react/only-export-components": ["error", {
|
|
432
|
+
allowConstantExport: false,
|
|
433
|
+
allowExportNames: []
|
|
434
|
+
}]
|
|
435
|
+
}
|
|
436
|
+
},
|
|
437
|
+
{
|
|
438
|
+
files: ["**/*.md/**/*.?([cm])[jt]s?(x)"],
|
|
439
|
+
rules: {
|
|
440
|
+
"no-alert": "off",
|
|
441
|
+
"no-labels": "off",
|
|
442
|
+
"no-lone-blocks": "off",
|
|
443
|
+
"no-unused-expressions": "off",
|
|
444
|
+
"no-unused-labels": "off",
|
|
445
|
+
"no-unused-vars": "off",
|
|
446
|
+
"unicode-bom": "off",
|
|
447
|
+
"no-redeclare": "off",
|
|
448
|
+
"no-use-before-define": "off",
|
|
449
|
+
"typescript/consistent-type-imports": "off",
|
|
450
|
+
"typescript/explicit-function-return-type": "off",
|
|
451
|
+
"typescript/no-namespace": "off",
|
|
452
|
+
"typescript/no-require-imports": "off"
|
|
453
|
+
}
|
|
454
|
+
},
|
|
455
|
+
{
|
|
456
|
+
files: ["**/scripts/**/*.?([cm])[jt]s?(x)"],
|
|
457
|
+
rules: { "typescript/explicit-function-return-type": "off" }
|
|
458
|
+
},
|
|
459
|
+
{
|
|
460
|
+
files: ["**/*.js", "**/*.cjs"],
|
|
461
|
+
rules: { "typescript/no-require-imports": "off" }
|
|
462
|
+
},
|
|
463
|
+
{
|
|
464
|
+
files: ["**/*.config.?([cm])[jt]s?(x)", "**/*.config.*.?([cm])[jt]s?(x)"],
|
|
465
|
+
rules: { "typescript/explicit-function-return-type": "off" }
|
|
466
|
+
},
|
|
467
|
+
{
|
|
468
|
+
files: ["**/e2e/**/*"],
|
|
469
|
+
rules: { "react/rules-of-hooks": "off" }
|
|
470
|
+
},
|
|
471
|
+
{
|
|
472
|
+
files: ["**/monaco-worker.ts"],
|
|
473
|
+
rules: { "import/default": "off" }
|
|
474
|
+
}
|
|
475
|
+
]
|
|
476
|
+
});
|
|
477
|
+
const baseOxfmtConfig = defineConfig({
|
|
478
|
+
singleQuote: true,
|
|
479
|
+
semi: false,
|
|
480
|
+
arrowParens: "avoid",
|
|
481
|
+
sortImports: true,
|
|
482
|
+
quoteProps: "consistent"
|
|
483
|
+
});
|
|
484
|
+
const basePlugins = [
|
|
485
|
+
"import",
|
|
486
|
+
"unicorn",
|
|
487
|
+
"jsdoc",
|
|
488
|
+
"node",
|
|
489
|
+
"promise",
|
|
490
|
+
"oxc"
|
|
491
|
+
];
|
|
492
|
+
const pluginToggles = {
|
|
493
|
+
typescript: {
|
|
494
|
+
packages: ["typescript"],
|
|
495
|
+
plugins: ["typescript"]
|
|
496
|
+
},
|
|
497
|
+
react: {
|
|
498
|
+
packages: ["react"],
|
|
499
|
+
plugins: [
|
|
500
|
+
"react",
|
|
501
|
+
"jsx-a11y",
|
|
502
|
+
"react-perf"
|
|
503
|
+
]
|
|
504
|
+
},
|
|
505
|
+
vue: {
|
|
506
|
+
packages: ["vue"],
|
|
507
|
+
plugins: ["vue"]
|
|
508
|
+
},
|
|
509
|
+
next: {
|
|
510
|
+
packages: ["next"],
|
|
511
|
+
plugins: ["nextjs"]
|
|
512
|
+
},
|
|
513
|
+
vitest: {
|
|
514
|
+
packages: ["vitest"],
|
|
515
|
+
plugins: ["vitest"]
|
|
516
|
+
},
|
|
517
|
+
jest: {
|
|
518
|
+
packages: ["jest"],
|
|
519
|
+
plugins: ["jest"]
|
|
520
|
+
}
|
|
521
|
+
};
|
|
522
|
+
const tailwindConfig = defineConfig$1({ jsPlugins: ["eslint-plugin-better-tailwindcss"] });
|
|
523
|
+
function getInstalledPackages(cwd) {
|
|
524
|
+
const names = /* @__PURE__ */ new Set();
|
|
525
|
+
try {
|
|
526
|
+
const pkg = JSON.parse(readFileSync(resolve(cwd, "package.json"), "utf-8"));
|
|
527
|
+
for (const field of [
|
|
528
|
+
pkg.dependencies,
|
|
529
|
+
pkg.devDependencies,
|
|
530
|
+
pkg.peerDependencies
|
|
531
|
+
]) for (const name of Object.keys(field ?? {})) names.add(name);
|
|
532
|
+
} catch {}
|
|
533
|
+
return names;
|
|
534
|
+
}
|
|
535
|
+
function resolvePlugins(options, installed) {
|
|
536
|
+
const plugins = [...basePlugins];
|
|
537
|
+
for (const name of Object.keys(pluginToggles)) {
|
|
538
|
+
const toggle = pluginToggles[name];
|
|
539
|
+
if (options[name] ?? toggle.packages.some((pkg) => installed.has(pkg))) plugins.push(...toggle.plugins);
|
|
540
|
+
}
|
|
541
|
+
return [...new Set(plugins)];
|
|
542
|
+
}
|
|
543
|
+
/**
|
|
544
|
+
* Build an oxlint config.
|
|
545
|
+
*
|
|
546
|
+
* Framework plugins (`typescript`, `react`, `vue`, `next`, `vitest`, `jest`,
|
|
547
|
+
* `tailwind`) are auto-enabled by detecting their package in the nearest
|
|
548
|
+
* `package.json`. If a dependency is not found there — e.g. it lives in a nested
|
|
549
|
+
* workspace like `apps/web/package.json` — its plugin stays off, so enable it
|
|
550
|
+
* manually:
|
|
551
|
+
*
|
|
552
|
+
* @example
|
|
553
|
+
* ```ts
|
|
554
|
+
* // auto-detect from the current package.json
|
|
555
|
+
* export default oxlintConfig()
|
|
556
|
+
* ```
|
|
557
|
+
* @example
|
|
558
|
+
* ```ts
|
|
559
|
+
* // dep lives in a nested workspace — turn the plugin on by hand
|
|
560
|
+
* export default oxlintConfig({ vue: true })
|
|
561
|
+
* ```
|
|
562
|
+
* @example
|
|
563
|
+
* ```ts
|
|
564
|
+
* // Tailwind, pointed at the entry CSS so classes can be resolved
|
|
565
|
+
* export default oxlintConfig({
|
|
566
|
+
* tailwind: true,
|
|
567
|
+
* override: {
|
|
568
|
+
* settings: { 'better-tailwindcss': { entryPoint: 'src/styles/globals.css' } },
|
|
569
|
+
* },
|
|
570
|
+
* })
|
|
571
|
+
* ```
|
|
572
|
+
*/
|
|
573
|
+
const TAILWIND_PLUGIN = "eslint-plugin-better-tailwindcss";
|
|
574
|
+
function oxlintConfig(options = {}) {
|
|
575
|
+
const { override = {} } = options;
|
|
576
|
+
const installed = getInstalledPackages(options.cwd ?? process.cwd());
|
|
577
|
+
let tailwind = options.tailwind ?? installed.has("tailwindcss");
|
|
578
|
+
if (tailwind && !installed.has(TAILWIND_PLUGIN)) {
|
|
579
|
+
console.warn(`[@letstri/oxc-config] Tailwind linting needs "${TAILWIND_PLUGIN}". Install it: pnpm add -D ${TAILWIND_PLUGIN}`);
|
|
580
|
+
tailwind = false;
|
|
581
|
+
}
|
|
582
|
+
return defu(override, { plugins: resolvePlugins(options, installed) }, tailwind ? tailwindConfig : {}, baseOxlintConfig);
|
|
583
|
+
}
|
|
584
|
+
function oxfmtConfig({ override = {} } = {}) {
|
|
585
|
+
return defu(override, baseOxfmtConfig);
|
|
586
|
+
}
|
|
587
|
+
//#endregion
|
|
588
|
+
export { oxfmtConfig, oxlintConfig };
|
package/package.json
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@letstri/oxc-config",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Opinionated Oxlint and Oxfmt configs",
|
|
5
|
+
"homepage": "https://github.com/letstri/oxc-config#readme",
|
|
6
|
+
"bugs": {
|
|
7
|
+
"url": "https://github.com/letstri/oxc-config/issues"
|
|
8
|
+
},
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"author": "Valerii Strilets",
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "git+https://github.com/letstri/oxc-config.git"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"type": "module",
|
|
19
|
+
"main": "./dist/index.mjs",
|
|
20
|
+
"types": "./dist/index.d.mts",
|
|
21
|
+
"exports": {
|
|
22
|
+
".": {
|
|
23
|
+
"types": "./dist/index.d.mts",
|
|
24
|
+
"import": "./dist/index.mjs"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"publishConfig": {
|
|
28
|
+
"access": "public"
|
|
29
|
+
},
|
|
30
|
+
"scripts": {
|
|
31
|
+
"build": "tsdown",
|
|
32
|
+
"dev": "tsdown --watch",
|
|
33
|
+
"check-types": "tsc --noEmit",
|
|
34
|
+
"lint": "oxlint -c oxlint.config.ts",
|
|
35
|
+
"lint:fix": "oxlint -c oxlint.config.ts --fix",
|
|
36
|
+
"format": "oxfmt -c oxfmt.config.ts",
|
|
37
|
+
"format:check": "oxfmt -c oxfmt.config.ts --check",
|
|
38
|
+
"check": "run-p lint check-types format:check",
|
|
39
|
+
"update": "taze -r -I major",
|
|
40
|
+
"prepare": "husky",
|
|
41
|
+
"prepublishOnly": "pnpm run build"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"defu": "^6.1.7"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@types/node": "^26.1.1",
|
|
48
|
+
"husky": "^9.1.7",
|
|
49
|
+
"npm-run-all2": "^9.0.2",
|
|
50
|
+
"oxfmt": "^0.58.0",
|
|
51
|
+
"oxlint": "^1.73.0",
|
|
52
|
+
"taze": "^19.14.1",
|
|
53
|
+
"tsdown": "^0.22.4",
|
|
54
|
+
"typescript": "^6.0.3"
|
|
55
|
+
},
|
|
56
|
+
"peerDependencies": {
|
|
57
|
+
"eslint-plugin-better-tailwindcss": ">=4",
|
|
58
|
+
"oxfmt": ">=0.58.0",
|
|
59
|
+
"oxlint": ">=1.73.0"
|
|
60
|
+
},
|
|
61
|
+
"peerDependenciesMeta": {
|
|
62
|
+
"eslint-plugin-better-tailwindcss": {
|
|
63
|
+
"optional": true
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
"engines": {
|
|
67
|
+
"node": ">=22"
|
|
68
|
+
},
|
|
69
|
+
"packageManager": "pnpm@11.11.0"
|
|
70
|
+
}
|