config-vp 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 +20 -0
- package/README.md +331 -0
- package/bin/vp-setup-vscode.mjs +85 -0
- package/dist/index.d.mts +22 -0
- package/dist/index.mjs +761 -0
- package/package.json +62 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) Orimay
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
|
7
|
+
the Software without restriction, including without limitation the rights to
|
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
|
10
|
+
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, FITNESS
|
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
# config-vp
|
|
2
|
+
|
|
3
|
+
One shared [vite-plus](https://viteplus.dev) config for all your packages. Pick a project type and get linting, formatting, testing, building, and ready-to-run tasks — with zero boilerplate per package.
|
|
4
|
+
|
|
5
|
+
## What you get
|
|
6
|
+
|
|
7
|
+
- **Linting** — a strict [oxlint](https://oxc.rs) ruleset (TypeScript, unicorn, import, jsdoc, promise) with stylistic and import-sorting rules.
|
|
8
|
+
- **Formatting** — an [oxfmt](https://oxc.rs) profile (single quotes, semicolons, trailing commas, Tailwind class sorting, import sorting).
|
|
9
|
+
- **Tasks** — `check`, `test`, `build`, `dev`, `release`, and more, tailored to your project type and runnable with `vp run <task>`.
|
|
10
|
+
- **Pre-commit checks** — staged files are checked and auto-fixed.
|
|
11
|
+
- **VSCode setup** — a one-command task to wire up the oxc extension at your workspace root.
|
|
12
|
+
|
|
13
|
+
Everything is opinionated and works out of the box. You can still override or extend any piece (see [Customizing](#customizing)).
|
|
14
|
+
|
|
15
|
+
## Prerequisites
|
|
16
|
+
|
|
17
|
+
This package is driven by [vite-plus](https://viteplus.dev) — the `vp` CLI that runs your whole dev lifecycle (install, dev server, lint, format, test, build). Install it once, globally:
|
|
18
|
+
|
|
19
|
+
**Linux / macOS**
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
curl -fsSL https://vite.plus | bash
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
**Windows**
|
|
26
|
+
|
|
27
|
+
```powershell
|
|
28
|
+
irm https://viteplus.dev/install.ps1 | iex
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Check it's available:
|
|
32
|
+
|
|
33
|
+
```sh
|
|
34
|
+
vp --version
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Quick start
|
|
38
|
+
|
|
39
|
+
**1. Add the config to your package:**
|
|
40
|
+
|
|
41
|
+
```sh
|
|
42
|
+
vp add -D config-vp
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
This also pulls in everything the config needs (`oxlint`, `oxfmt`, and the lint plugins). If a compatible `vite-plus` is already in your workspace, that one is reused.
|
|
46
|
+
|
|
47
|
+
**2. Create `vite.config.ts`:**
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
import { defineConfig } from 'config-vp';
|
|
51
|
+
|
|
52
|
+
const config = defineConfig({ type: 'lib' });
|
|
53
|
+
export default config;
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
> **Important:** Assign to a `const` and export it — don't write `export default defineConfig(...)` inline. `vp` reads your default export statically to discover tasks; a direct call hides them and `vp run` reports "Task not found". See [Troubleshooting](#troubleshooting).
|
|
57
|
+
|
|
58
|
+
**3. Run something:**
|
|
59
|
+
|
|
60
|
+
```sh
|
|
61
|
+
vp run check # lint + format, with autofix
|
|
62
|
+
vp run test # run tests
|
|
63
|
+
vp run build # build (vp pack / vite build / nuxt build, per type)
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
That's it. Pick the `type` that matches your package below for the right build/dev tasks.
|
|
67
|
+
|
|
68
|
+
## Project types
|
|
69
|
+
|
|
70
|
+
Set `type` to match what you're building. It drives Vue lint rules, library packaging, and the `build`/`dev`/`release` tasks.
|
|
71
|
+
|
|
72
|
+
| `type` | For | `build` | `dev` |
|
|
73
|
+
| --------------- | ------------------------------------ | --------------- | ----------------- |
|
|
74
|
+
| `lib` | A TypeScript library | `vp pack` | `vp pack --watch` |
|
|
75
|
+
| `lib:vue` | A Vue component library | `vp pack` | `vp pack --watch` |
|
|
76
|
+
| `lib:nuxt` | A Nuxt-targeted library | `vp pack` | `vp pack --watch` |
|
|
77
|
+
| `vue` | A Vue (Vite) application | `vite build` | `vite dev` |
|
|
78
|
+
| `nuxt:spa` | A Nuxt app, statically generated | `nuxt generate` | `nuxt dev` |
|
|
79
|
+
| `nuxt:ssr` | A Nuxt app, server-side rendered | `nuxt build` | `nuxt dev` |
|
|
80
|
+
| no `type` field | Shared root / non-buildable packages | _none_ | _none_ |
|
|
81
|
+
|
|
82
|
+
### Recipes
|
|
83
|
+
|
|
84
|
+
**Library** — dual ESM + CJS output:
|
|
85
|
+
|
|
86
|
+
```ts
|
|
87
|
+
import { defineConfig } from 'config-vp';
|
|
88
|
+
|
|
89
|
+
const config = defineConfig({
|
|
90
|
+
type: 'lib',
|
|
91
|
+
overrides: {
|
|
92
|
+
pack: {
|
|
93
|
+
entry: ['src/index.ts'],
|
|
94
|
+
format: ['esm', 'cjs'],
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
export default config;
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
**Vue library** — same, with `type: 'lib:vue'` for SFC/template lint rules.
|
|
102
|
+
|
|
103
|
+
```ts
|
|
104
|
+
import { defineConfig } from 'config-vp';
|
|
105
|
+
|
|
106
|
+
const config = defineConfig({
|
|
107
|
+
type: 'lib:vue',
|
|
108
|
+
overrides: {
|
|
109
|
+
pack: {
|
|
110
|
+
entry: ['src/index.ts'],
|
|
111
|
+
format: ['esm', 'cjs'],
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
});
|
|
115
|
+
export default config;
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
**Nuxt app.** Nuxt doesn't read `vite.config.ts` — its Vite settings live under the `vite` key of `nuxt.config.ts`. Build the config in a small `nuxt.config.vite.ts` and wire it in:
|
|
119
|
+
|
|
120
|
+
```ts
|
|
121
|
+
// nuxt.config.vite.ts
|
|
122
|
+
import type { NuxtConfig } from 'nuxt/schema';
|
|
123
|
+
import { defineConfig } from 'config-vp';
|
|
124
|
+
|
|
125
|
+
export const vite = defineConfig({
|
|
126
|
+
type: 'nuxt:spa', // or 'nuxt:ssr'
|
|
127
|
+
overrides: {
|
|
128
|
+
// any Vite/vite-plus options the app needs, e.g. plugins, define, test, …
|
|
129
|
+
},
|
|
130
|
+
}) as NuxtConfig['vite'];
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
```ts
|
|
134
|
+
// nuxt.config.ts
|
|
135
|
+
import { defineNuxtConfig } from 'nuxt/config';
|
|
136
|
+
import { vite } from './nuxt.config.vite';
|
|
137
|
+
|
|
138
|
+
export default defineNuxtConfig({ vite });
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
The `export const vite = …` form is itself a const export, so `vp` discovers any `run.tasks` you add through `overrides.run`.
|
|
142
|
+
|
|
143
|
+
**Plain package** — lint + format + tests only, no build/dev (e.g. a config or scripts-only package). Just call `defineConfig()` with no `type`:
|
|
144
|
+
|
|
145
|
+
```ts
|
|
146
|
+
import { defineConfig } from 'config-vp';
|
|
147
|
+
|
|
148
|
+
const config = defineConfig();
|
|
149
|
+
export default config;
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Tasks
|
|
153
|
+
|
|
154
|
+
Run any task with `vp run <task>`. Tasks are cached and run in dependency order across your workspace.
|
|
155
|
+
|
|
156
|
+
**Always available:**
|
|
157
|
+
|
|
158
|
+
| Task | Command | Purpose |
|
|
159
|
+
| --------------- | -------------------------------------- | -------------------------------- |
|
|
160
|
+
| `check` | `vp check --fix` | Lint + format, with autofix |
|
|
161
|
+
| `test` | `vp test --run --passWithNoTests` | Run the test suite once |
|
|
162
|
+
| `test:watch` | `vp test --passWithNoTests` | Run tests in watch mode |
|
|
163
|
+
| `test:coverage` | `vp test --coverage --passWithNoTests` | Run tests with a coverage report |
|
|
164
|
+
|
|
165
|
+
> `--passWithNoTests` means a package with no test files passes instead of failing — so `test`/`release` don't break in packages that don't have tests yet.
|
|
166
|
+
|
|
167
|
+
**Added by `type`:**
|
|
168
|
+
|
|
169
|
+
| Task | When | Command |
|
|
170
|
+
| --- | --- | --- |
|
|
171
|
+
| `build` | any `type` | see [Project types](#project-types) |
|
|
172
|
+
| `dev` | any `type` | see [Project types](#project-types) |
|
|
173
|
+
| `release` | `lib*` types | `vp check --fix && vp test --run --passWithNoTests && vp pack && vpx bumpp && pnpm publish` |
|
|
174
|
+
|
|
175
|
+
**Workspace root only:**
|
|
176
|
+
|
|
177
|
+
| Task | Command |
|
|
178
|
+
| -------------- | ----------------- |
|
|
179
|
+
| `setup:vscode` | `vp-setup-vscode` |
|
|
180
|
+
|
|
181
|
+
`setup:vscode` is added automatically to **workspace roots** (any package with a `pnpm-workspace.yaml` or a `workspaces` field, plus standalone projects). Nested sub-workspaces each get their own. It:
|
|
182
|
+
|
|
183
|
+
1. Merges oxc settings into `.vscode/settings.json` (preserving your comments).
|
|
184
|
+
2. Adds the `VoidZero.vite-plus-extension-pack` recommendation to `.vscode/extensions.json`.
|
|
185
|
+
3. Installs the extension via the `code` CLI if available.
|
|
186
|
+
|
|
187
|
+
> For a whole-workspace lint/format, use the built-in `vp check`. To build every package, use `vp run -r build`.
|
|
188
|
+
|
|
189
|
+
## Customizing
|
|
190
|
+
|
|
191
|
+
Two knobs, same shape — they differ only in how they merge:
|
|
192
|
+
|
|
193
|
+
- **`overrides`** — _replace_ semantics. Your values overwrite the defaults. Applied first.
|
|
194
|
+
- **`extends`** — _additive_ semantics. Arrays concatenate, objects deep-merge. Applied last, so it's never clobbered by an override.
|
|
195
|
+
|
|
196
|
+
```ts
|
|
197
|
+
const config = defineConfig({
|
|
198
|
+
type: 'lib',
|
|
199
|
+
overrides: {
|
|
200
|
+
// Replace the pack entry point entirely
|
|
201
|
+
pack: {
|
|
202
|
+
entry: ['src/index.ts'],
|
|
203
|
+
format: ['esm', 'cjs'],
|
|
204
|
+
},
|
|
205
|
+
},
|
|
206
|
+
extends: {
|
|
207
|
+
// Add to the lint config without losing built-ins
|
|
208
|
+
lint: {
|
|
209
|
+
rules: { 'no-console': 'error' },
|
|
210
|
+
},
|
|
211
|
+
},
|
|
212
|
+
});
|
|
213
|
+
export default config;
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
> `lint` is **always** deep-merged (never fully replaced), even under `overrides` — so you can't accidentally wipe the base ruleset.
|
|
217
|
+
|
|
218
|
+
### Your existing Vite config goes here
|
|
219
|
+
|
|
220
|
+
`overrides` and `extends` accept **any** vite-plus `UserConfig` field, not just config-vp's own keys. So a whole normal Vite config — `plugins`, `resolve`, `define`, `server`, `optimizeDeps`, `worker`, `test`, `build`, `run.tasks`, … — drops straight into `extends` (additive) or `overrides` (replacing). There's nothing config-vp-specific to learn: keep writing Vite config, just nest it.
|
|
221
|
+
|
|
222
|
+
```ts
|
|
223
|
+
const config = defineConfig({
|
|
224
|
+
type: 'nuxt:spa',
|
|
225
|
+
extends: {
|
|
226
|
+
plugins: [tailwindcss()],
|
|
227
|
+
define: { 'import.meta.env.VITE_RELEASE': JSON.stringify(release) },
|
|
228
|
+
optimizeDeps: { exclude: ['some-wasm-dep'] },
|
|
229
|
+
server: { fs: { allow: ['../..'] } },
|
|
230
|
+
test, // your vitest config
|
|
231
|
+
run: {
|
|
232
|
+
tasks: {
|
|
233
|
+
preview: { command: 'nuxt preview', cache: false },
|
|
234
|
+
deploy: { command: 'vpx tsx scripts/deploy.ts' },
|
|
235
|
+
},
|
|
236
|
+
},
|
|
237
|
+
},
|
|
238
|
+
});
|
|
239
|
+
export default config;
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
Your entire app-specific Vite setup lives in `extends`, on top of config-vp's `nuxt:spa` defaults.
|
|
243
|
+
|
|
244
|
+
### Ignore patterns (lint + format)
|
|
245
|
+
|
|
246
|
+
A top-level `ignorePatterns` is forwarded to **both** the linter and the formatter:
|
|
247
|
+
|
|
248
|
+
```ts
|
|
249
|
+
defineConfig({
|
|
250
|
+
type: 'lib',
|
|
251
|
+
// Replace the built-in ignore list:
|
|
252
|
+
overrides: { ignorePatterns: ['only-this/**'] },
|
|
253
|
+
// …or add to it, keeping the defaults:
|
|
254
|
+
extends: { ignorePatterns: ['generated/**', 'vendor/**'] },
|
|
255
|
+
});
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### Disable packaging
|
|
259
|
+
|
|
260
|
+
A `lib*` type includes packaging by default. Turn it off with `pack: false`:
|
|
261
|
+
|
|
262
|
+
```ts
|
|
263
|
+
defineConfig({
|
|
264
|
+
type: 'lib',
|
|
265
|
+
overrides: { pack: false },
|
|
266
|
+
});
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
## Options
|
|
270
|
+
|
|
271
|
+
| Option | Type | Description |
|
|
272
|
+
| --- | --- | --- |
|
|
273
|
+
| `type` | `ProjectType` | `'lib' \| 'lib:vue' \| 'lib:nuxt' \| 'vue' \| 'nuxt:spa' \| 'nuxt:ssr'`. Omit for shared/root packages. |
|
|
274
|
+
| `overrides` | object | Replace-semantics customizations. Accepts `ignorePatterns` and `pack: false`. |
|
|
275
|
+
| `extends` | object | Additive customizations, applied after `overrides`. Same shape. |
|
|
276
|
+
|
|
277
|
+
### Merge reference
|
|
278
|
+
|
|
279
|
+
Order: `base → overrides (replace) → extends (additive)`.
|
|
280
|
+
|
|
281
|
+
| Key | Under `overrides` | Under `extends` |
|
|
282
|
+
| --------------- | ------------------------------------- | -------------------- |
|
|
283
|
+
| `lint` | arrays concat, rules deep-merge | same |
|
|
284
|
+
| `fmt` | shallow-merge | recursive deep-merge |
|
|
285
|
+
| `pack` | shallow-merge (or `false` to disable) | recursive deep-merge |
|
|
286
|
+
| `staged` | shallow-merge | recursive deep-merge |
|
|
287
|
+
| `run` | shallow-merge, tasks combined | recursive deep-merge |
|
|
288
|
+
| arrays (others) | replace | concatenate |
|
|
289
|
+
|
|
290
|
+
## Default ignore patterns
|
|
291
|
+
|
|
292
|
+
The base list applied to both linting and formatting (override or extend it via the [ignore-patterns shortcut](#ignore-patterns-lint--format)):
|
|
293
|
+
|
|
294
|
+
```
|
|
295
|
+
*.log* **/.output **/.vp-tsconfig
|
|
296
|
+
**/.nuxt-storybook **/node_modules **/.vp-tmp-vite
|
|
297
|
+
**/.nuxt **/dist .env
|
|
298
|
+
**/.nitro **/.vue-types package-lock.json
|
|
299
|
+
**/.cache pnpm-lock.yaml
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
## API
|
|
303
|
+
|
|
304
|
+
The package exports a single function, `defineConfig`, along with its `ProjectType` and `ConfigOptions` types for annotation.
|
|
305
|
+
|
|
306
|
+
## Troubleshooting
|
|
307
|
+
|
|
308
|
+
### `vp run <task>` says "Task not found" (but `vp pack` works)
|
|
309
|
+
|
|
310
|
+
Your config almost certainly uses an inline default export. `vp` discovers tasks by statically reading the default export, and a direct call expression hides them. Use the `const` form:
|
|
311
|
+
|
|
312
|
+
```ts
|
|
313
|
+
// ❌ tasks are invisible to `vp run`
|
|
314
|
+
export default defineConfig({ type: 'lib' });
|
|
315
|
+
|
|
316
|
+
// ✅ assign, then export
|
|
317
|
+
const config = defineConfig({ type: 'lib' });
|
|
318
|
+
export default config;
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
### Tasks show up duplicated or ambiguous across the workspace
|
|
322
|
+
|
|
323
|
+
Every workspace package needs a unique `name` in its `package.json`. An unnamed package (commonly the repo root) registers its tasks without a namespace, colliding with others. Give the root a name, e.g. `"name": "my-workspace-root"`.
|
|
324
|
+
|
|
325
|
+
### `vp` crashes with `Cannot convert undefined or null to object`
|
|
326
|
+
|
|
327
|
+
The globally-installed `vp` and your workspace's `vite-plus` are different versions. Match the workspace `vite-plus` (in `package.json` and any `pnpm.overrides`) to `vp --version`, then run `vp install`.
|
|
328
|
+
|
|
329
|
+
## License
|
|
330
|
+
|
|
331
|
+
MIT
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/* eslint-disable typescript-eslint/no-unsafe-assignment, typescript-eslint/no-unsafe-argument, typescript-eslint/no-unsafe-member-access, typescript-eslint/no-unsafe-call, typescript-eslint/no-unsafe-return */
|
|
3
|
+
|
|
4
|
+
import { applyEdits, modify, parse } from 'jsonc-parser';
|
|
5
|
+
import { execSync } from 'node:child_process';
|
|
6
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
7
|
+
import { dirname, join } from 'node:path';
|
|
8
|
+
|
|
9
|
+
const EXTENSION_ID = 'VoidZero.vite-plus-extension-pack';
|
|
10
|
+
|
|
11
|
+
/** Walk up from cwd until a directory containing .vscode/ is found, or return cwd. */
|
|
12
|
+
function findVscodeRoot() {
|
|
13
|
+
let dir = process.cwd();
|
|
14
|
+
while (true) {
|
|
15
|
+
if (existsSync(join(dir, '.vscode'))) break;
|
|
16
|
+
const parent = dirname(dir);
|
|
17
|
+
if (parent === dir) break;
|
|
18
|
+
dir = parent;
|
|
19
|
+
}
|
|
20
|
+
return dir;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const vscodeDir = join(findVscodeRoot(), '.vscode');
|
|
24
|
+
|
|
25
|
+
const OXC_SETTINGS = {
|
|
26
|
+
'editor.defaultFormatter': 'oxc.oxc-vscode',
|
|
27
|
+
'editor.formatOnSave': true,
|
|
28
|
+
'editor.formatOnSaveMode': 'file',
|
|
29
|
+
'editor.codeActionsOnSave': {
|
|
30
|
+
'source.fixAll.oxc': 'explicit',
|
|
31
|
+
},
|
|
32
|
+
'oxc.enable': true,
|
|
33
|
+
'oxc.typeAware': true,
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const FORMAT_OPTIONS = { tabSize: 2, insertSpaces: true };
|
|
37
|
+
|
|
38
|
+
/** Apply key-value pairs to a JSONC file in-place, preserving comments. */
|
|
39
|
+
function mergeJsonc(filePath, entries) {
|
|
40
|
+
let text = existsSync(filePath) ? readFileSync(filePath, 'utf8') : '{}';
|
|
41
|
+
for (const [path, value] of entries) {
|
|
42
|
+
const edits = modify(text, path, value, { formattingOptions: FORMAT_OPTIONS });
|
|
43
|
+
text = applyEdits(text, edits);
|
|
44
|
+
}
|
|
45
|
+
writeFileSync(filePath, text);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// 1. Ensure .vscode dir exists
|
|
49
|
+
if (!existsSync(vscodeDir)) mkdirSync(vscodeDir);
|
|
50
|
+
|
|
51
|
+
// 2. Update .vscode/settings.json with oxc settings
|
|
52
|
+
const settingsEntries = Object.entries(OXC_SETTINGS).flatMap(([key, value]) => {
|
|
53
|
+
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
|
|
54
|
+
return Object.entries(value).map(([subKey, subValue]) => [[key, subKey], subValue]);
|
|
55
|
+
}
|
|
56
|
+
return [[[key], value]];
|
|
57
|
+
});
|
|
58
|
+
mergeJsonc(join(vscodeDir, 'settings.json'), settingsEntries);
|
|
59
|
+
console.log('VSCode settings updated with oxc configuration.');
|
|
60
|
+
|
|
61
|
+
// 3. Add extension to .vscode/extensions.json recommendations
|
|
62
|
+
const extensionsPath = join(vscodeDir, 'extensions.json');
|
|
63
|
+
let extText = existsSync(extensionsPath)
|
|
64
|
+
? readFileSync(extensionsPath, 'utf8')
|
|
65
|
+
: '{"recommendations":[]}';
|
|
66
|
+
const extJson = parse(extText);
|
|
67
|
+
const recs = extJson.recommendations ?? [];
|
|
68
|
+
if (!recs.includes(EXTENSION_ID)) {
|
|
69
|
+
const edits = modify(extText, ['recommendations', recs.length], EXTENSION_ID, {
|
|
70
|
+
formattingOptions: FORMAT_OPTIONS,
|
|
71
|
+
isArrayInsertion: true,
|
|
72
|
+
});
|
|
73
|
+
extText = applyEdits(extText, edits);
|
|
74
|
+
writeFileSync(extensionsPath, extText);
|
|
75
|
+
console.log(`Added ${EXTENSION_ID} to extensions.json recommendations.`);
|
|
76
|
+
} else {
|
|
77
|
+
console.log(`${EXTENSION_ID} already in extensions.json recommendations.`);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// 4. Install extension if `code` CLI is available
|
|
81
|
+
try {
|
|
82
|
+
execSync(`code --install-extension ${EXTENSION_ID} --force`, { stdio: 'inherit' });
|
|
83
|
+
} catch {
|
|
84
|
+
console.log(`Could not install extension automatically. Install it manually: ${EXTENSION_ID}`);
|
|
85
|
+
}
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { UserConfig } from "vite-plus";
|
|
2
|
+
|
|
3
|
+
//#region src/index.d.ts
|
|
4
|
+
type ProjectType = 'lib' | 'lib:nuxt' | 'lib:vue' | 'nuxt:spa' | 'nuxt:ssr' | 'vue';
|
|
5
|
+
type DeepPartial<T> = T extends ((...args: never[]) => unknown) ? T : T extends (infer U)[] ? DeepPartial<U>[] : T extends object ? { [K in keyof T]?: DeepPartial<T[K]> } : T;
|
|
6
|
+
interface ConfigOptions {
|
|
7
|
+
/** Project type — drives vue lint, pack inclusion, and dev/build/release tasks. */
|
|
8
|
+
type?: ProjectType;
|
|
9
|
+
/** Replace semantics: values replace defaults, objects shallow-merge at known keys. Exception: lint is always additive (deep-merged). Pass `pack: false` to suppress pack inclusion. */
|
|
10
|
+
overrides?: DeepPartial<UserConfig> & {
|
|
11
|
+
ignorePatterns?: string[];
|
|
12
|
+
pack?: unknown;
|
|
13
|
+
};
|
|
14
|
+
/** Additive semantics: arrays concatenate, objects deep-merge. Applied AFTER overrides. Pass `pack: false` to suppress pack inclusion. */
|
|
15
|
+
extends?: DeepPartial<UserConfig> & {
|
|
16
|
+
ignorePatterns?: string[];
|
|
17
|
+
pack?: unknown;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
declare function defineConfig(options?: ConfigOptions): UserConfig;
|
|
21
|
+
//#endregion
|
|
22
|
+
export { ConfigOptions, ProjectType, defineConfig };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,761 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
//#region src/ignore.ts
|
|
4
|
+
const ignorePatterns = [
|
|
5
|
+
"*.log*",
|
|
6
|
+
"**/.nuxt-storybook",
|
|
7
|
+
"**/.nuxt",
|
|
8
|
+
"**/.nitro",
|
|
9
|
+
"**/.cache",
|
|
10
|
+
"**/.output",
|
|
11
|
+
"**/node_modules",
|
|
12
|
+
"**/dist",
|
|
13
|
+
"**/.vue-types",
|
|
14
|
+
"**/.vp-tsconfig",
|
|
15
|
+
"**/.vp-tmp-vite",
|
|
16
|
+
".env",
|
|
17
|
+
"package-lock.json",
|
|
18
|
+
"pnpm-lock.yaml"
|
|
19
|
+
];
|
|
20
|
+
//#endregion
|
|
21
|
+
//#region src/fmt.ts
|
|
22
|
+
const fmt = {
|
|
23
|
+
ignorePatterns,
|
|
24
|
+
tabWidth: 2,
|
|
25
|
+
useTabs: false,
|
|
26
|
+
singleQuote: true,
|
|
27
|
+
semi: true,
|
|
28
|
+
proseWrap: "always",
|
|
29
|
+
arrowParens: "avoid",
|
|
30
|
+
bracketSameLine: false,
|
|
31
|
+
bracketSpacing: true,
|
|
32
|
+
vueIndentScriptAndStyle: true,
|
|
33
|
+
printWidth: 100,
|
|
34
|
+
endOfLine: "lf",
|
|
35
|
+
trailingComma: "all",
|
|
36
|
+
singleAttributePerLine: true,
|
|
37
|
+
experimentalTailwindcss: { attributes: [
|
|
38
|
+
"class",
|
|
39
|
+
"appear-from-class",
|
|
40
|
+
"appear-active-class",
|
|
41
|
+
"appear-to-class",
|
|
42
|
+
"enter-from-class",
|
|
43
|
+
"enter-active-class",
|
|
44
|
+
"enter-to-class",
|
|
45
|
+
"leave-from-class",
|
|
46
|
+
"leave-active-class",
|
|
47
|
+
"leave-to-class"
|
|
48
|
+
] },
|
|
49
|
+
experimentalSortImports: {
|
|
50
|
+
groups: [
|
|
51
|
+
"type-import",
|
|
52
|
+
["value-builtin", "value-external"],
|
|
53
|
+
"type-internal",
|
|
54
|
+
"value-internal",
|
|
55
|
+
[
|
|
56
|
+
"type-parent",
|
|
57
|
+
"type-sibling",
|
|
58
|
+
"type-index"
|
|
59
|
+
],
|
|
60
|
+
[
|
|
61
|
+
"value-parent",
|
|
62
|
+
"value-sibling",
|
|
63
|
+
"value-index"
|
|
64
|
+
],
|
|
65
|
+
"unknown"
|
|
66
|
+
],
|
|
67
|
+
ignoreCase: false,
|
|
68
|
+
newlinesBetween: false
|
|
69
|
+
},
|
|
70
|
+
embeddedLanguageFormatting: "auto",
|
|
71
|
+
insertFinalNewline: true,
|
|
72
|
+
objectWrap: "preserve",
|
|
73
|
+
quoteProps: "consistent",
|
|
74
|
+
sortPackageJson: true,
|
|
75
|
+
overrides: [{
|
|
76
|
+
files: ["*.md"],
|
|
77
|
+
options: { proseWrap: "never" }
|
|
78
|
+
}]
|
|
79
|
+
};
|
|
80
|
+
//#endregion
|
|
81
|
+
//#region src/lint.ts
|
|
82
|
+
const lint = {
|
|
83
|
+
plugins: [
|
|
84
|
+
"typescript",
|
|
85
|
+
"unicorn",
|
|
86
|
+
"oxc",
|
|
87
|
+
"eslint",
|
|
88
|
+
"import",
|
|
89
|
+
"jsdoc",
|
|
90
|
+
"node",
|
|
91
|
+
"promise"
|
|
92
|
+
],
|
|
93
|
+
jsPlugins: ["@stylistic/eslint-plugin", "eslint-plugin-perfectionist"],
|
|
94
|
+
categories: { correctness: "off" },
|
|
95
|
+
env: { builtin: true },
|
|
96
|
+
ignorePatterns,
|
|
97
|
+
options: {
|
|
98
|
+
typeCheck: true,
|
|
99
|
+
typeAware: true,
|
|
100
|
+
reportUnusedDisableDirectives: "deny",
|
|
101
|
+
denyWarnings: true,
|
|
102
|
+
maxWarnings: 0
|
|
103
|
+
},
|
|
104
|
+
rules: {
|
|
105
|
+
"constructor-super": "error",
|
|
106
|
+
"for-direction": "error",
|
|
107
|
+
"no-async-promise-executor": "error",
|
|
108
|
+
"no-case-declarations": "error",
|
|
109
|
+
"no-class-assign": "error",
|
|
110
|
+
"no-compare-neg-zero": "error",
|
|
111
|
+
"no-cond-assign": "error",
|
|
112
|
+
"no-const-assign": "error",
|
|
113
|
+
"no-constant-binary-expression": "error",
|
|
114
|
+
"no-constant-condition": "error",
|
|
115
|
+
"no-control-regex": "error",
|
|
116
|
+
"no-debugger": "error",
|
|
117
|
+
"no-delete-var": "error",
|
|
118
|
+
"no-dupe-class-members": "error",
|
|
119
|
+
"no-dupe-else-if": "error",
|
|
120
|
+
"no-dupe-keys": "error",
|
|
121
|
+
"no-duplicate-case": "error",
|
|
122
|
+
"no-empty": "error",
|
|
123
|
+
"no-empty-character-class": "error",
|
|
124
|
+
"no-empty-pattern": "error",
|
|
125
|
+
"no-empty-static-block": "error",
|
|
126
|
+
"no-ex-assign": "error",
|
|
127
|
+
"no-extra-boolean-cast": "error",
|
|
128
|
+
"no-fallthrough": "error",
|
|
129
|
+
"no-func-assign": "error",
|
|
130
|
+
"no-global-assign": "error",
|
|
131
|
+
"no-import-assign": "error",
|
|
132
|
+
"no-invalid-regexp": "error",
|
|
133
|
+
"no-irregular-whitespace": "error",
|
|
134
|
+
"no-loss-of-precision": "error",
|
|
135
|
+
"no-misleading-character-class": "error",
|
|
136
|
+
"no-new-native-nonconstructor": "error",
|
|
137
|
+
"no-nonoctal-decimal-escape": "error",
|
|
138
|
+
"no-obj-calls": "error",
|
|
139
|
+
"no-prototype-builtins": "error",
|
|
140
|
+
"no-redeclare": "error",
|
|
141
|
+
"no-regex-spaces": "error",
|
|
142
|
+
"no-self-assign": "error",
|
|
143
|
+
"no-setter-return": "error",
|
|
144
|
+
"no-shadow-restricted-names": "error",
|
|
145
|
+
"no-sparse-arrays": "error",
|
|
146
|
+
"no-this-before-super": "error",
|
|
147
|
+
"no-unexpected-multiline": "error",
|
|
148
|
+
"no-unsafe-finally": "error",
|
|
149
|
+
"no-unsafe-negation": "error",
|
|
150
|
+
"no-unsafe-optional-chaining": "error",
|
|
151
|
+
"no-unused-labels": "error",
|
|
152
|
+
"no-unused-private-class-members": "error",
|
|
153
|
+
"no-unused-vars": ["error", {
|
|
154
|
+
args: "all",
|
|
155
|
+
argsIgnorePattern: "^_",
|
|
156
|
+
caughtErrors: "all",
|
|
157
|
+
caughtErrorsIgnorePattern: "^_",
|
|
158
|
+
destructuredArrayIgnorePattern: "^_",
|
|
159
|
+
ignoreRestSiblings: true,
|
|
160
|
+
varsIgnorePattern: "^_"
|
|
161
|
+
}],
|
|
162
|
+
"no-useless-backreference": "error",
|
|
163
|
+
"no-useless-catch": "error",
|
|
164
|
+
"no-useless-escape": "error",
|
|
165
|
+
"no-with": "error",
|
|
166
|
+
"require-yield": "error",
|
|
167
|
+
"use-isnan": "error",
|
|
168
|
+
"valid-typeof": "error",
|
|
169
|
+
"@stylistic/array-bracket-spacing": ["error", "never"],
|
|
170
|
+
"@stylistic/arrow-parens": ["error", "as-needed"],
|
|
171
|
+
"@stylistic/arrow-spacing": ["error", {
|
|
172
|
+
after: true,
|
|
173
|
+
before: true
|
|
174
|
+
}],
|
|
175
|
+
"@stylistic/block-spacing": ["error", "always"],
|
|
176
|
+
"@stylistic/brace-style": ["error", "1tbs"],
|
|
177
|
+
"@stylistic/comma-dangle": ["error", "always-multiline"],
|
|
178
|
+
"@stylistic/comma-spacing": ["error", {
|
|
179
|
+
after: true,
|
|
180
|
+
before: false
|
|
181
|
+
}],
|
|
182
|
+
"@stylistic/comma-style": ["error", "last"],
|
|
183
|
+
"@stylistic/computed-property-spacing": [
|
|
184
|
+
"error",
|
|
185
|
+
"never",
|
|
186
|
+
{ enforceForClassMembers: true }
|
|
187
|
+
],
|
|
188
|
+
"@stylistic/dot-location": ["error", "property"],
|
|
189
|
+
"@stylistic/eol-last": "error",
|
|
190
|
+
"@stylistic/generator-star-spacing": ["error", {
|
|
191
|
+
after: true,
|
|
192
|
+
before: false
|
|
193
|
+
}],
|
|
194
|
+
"@stylistic/key-spacing": ["error", {
|
|
195
|
+
afterColon: true,
|
|
196
|
+
beforeColon: false
|
|
197
|
+
}],
|
|
198
|
+
"@stylistic/keyword-spacing": ["error", {
|
|
199
|
+
after: true,
|
|
200
|
+
before: true
|
|
201
|
+
}],
|
|
202
|
+
"@stylistic/lines-between-class-members": [
|
|
203
|
+
"error",
|
|
204
|
+
"always",
|
|
205
|
+
{ exceptAfterSingleLine: true }
|
|
206
|
+
],
|
|
207
|
+
"@stylistic/max-statements-per-line": ["error", { max: 1 }],
|
|
208
|
+
"@stylistic/multiline-ternary": ["error", "always-multiline"],
|
|
209
|
+
"@stylistic/new-parens": "error",
|
|
210
|
+
"@stylistic/no-extra-parens": ["error", "functions"],
|
|
211
|
+
"@stylistic/no-floating-decimal": "error",
|
|
212
|
+
"@stylistic/no-mixed-spaces-and-tabs": "error",
|
|
213
|
+
"@stylistic/no-multi-spaces": "error",
|
|
214
|
+
"@stylistic/no-multiple-empty-lines": ["error", {
|
|
215
|
+
max: 1,
|
|
216
|
+
maxBOF: 0,
|
|
217
|
+
maxEOF: 0
|
|
218
|
+
}],
|
|
219
|
+
"@stylistic/no-tabs": "error",
|
|
220
|
+
"@stylistic/no-trailing-spaces": "error",
|
|
221
|
+
"@stylistic/no-whitespace-before-property": "error",
|
|
222
|
+
"@stylistic/object-curly-spacing": ["error", "always"],
|
|
223
|
+
"@stylistic/operator-linebreak": [
|
|
224
|
+
"error",
|
|
225
|
+
"after",
|
|
226
|
+
{ overrides: {
|
|
227
|
+
":": "before",
|
|
228
|
+
"?": "before",
|
|
229
|
+
"|": "before",
|
|
230
|
+
"&": "before"
|
|
231
|
+
} }
|
|
232
|
+
],
|
|
233
|
+
"@stylistic/padded-blocks": ["error", {
|
|
234
|
+
blocks: "never",
|
|
235
|
+
classes: "never",
|
|
236
|
+
switches: "never"
|
|
237
|
+
}],
|
|
238
|
+
"@stylistic/quote-props": ["error", "consistent-as-needed"],
|
|
239
|
+
"@stylistic/quotes": [
|
|
240
|
+
"error",
|
|
241
|
+
"single",
|
|
242
|
+
{ avoidEscape: true }
|
|
243
|
+
],
|
|
244
|
+
"@stylistic/rest-spread-spacing": ["error", "never"],
|
|
245
|
+
"@stylistic/semi": ["error", "always"],
|
|
246
|
+
"@stylistic/semi-spacing": ["error", {
|
|
247
|
+
after: true,
|
|
248
|
+
before: false
|
|
249
|
+
}],
|
|
250
|
+
"@stylistic/space-before-blocks": ["error", "always"],
|
|
251
|
+
"@stylistic/space-before-function-paren": ["error", {
|
|
252
|
+
anonymous: "always",
|
|
253
|
+
asyncArrow: "always",
|
|
254
|
+
named: "never"
|
|
255
|
+
}],
|
|
256
|
+
"@stylistic/space-in-parens": ["error", "never"],
|
|
257
|
+
"@stylistic/space-infix-ops": "error",
|
|
258
|
+
"@stylistic/space-unary-ops": ["error", {
|
|
259
|
+
nonwords: false,
|
|
260
|
+
words: true
|
|
261
|
+
}],
|
|
262
|
+
"@stylistic/spaced-comment": [
|
|
263
|
+
"error",
|
|
264
|
+
"always",
|
|
265
|
+
{
|
|
266
|
+
block: {
|
|
267
|
+
balanced: true,
|
|
268
|
+
exceptions: ["*"],
|
|
269
|
+
markers: ["!"]
|
|
270
|
+
},
|
|
271
|
+
line: {
|
|
272
|
+
exceptions: ["/", "#"],
|
|
273
|
+
markers: ["/"]
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
],
|
|
277
|
+
"@stylistic/template-curly-spacing": "error",
|
|
278
|
+
"@stylistic/template-tag-spacing": ["error", "never"],
|
|
279
|
+
"@stylistic/type-annotation-spacing": ["error", {}],
|
|
280
|
+
"@stylistic/type-generic-spacing": "error",
|
|
281
|
+
"@stylistic/type-named-tuple-spacing": "error",
|
|
282
|
+
"@stylistic/wrap-iife": [
|
|
283
|
+
"error",
|
|
284
|
+
"any",
|
|
285
|
+
{ functionPrototypeMethods: true }
|
|
286
|
+
],
|
|
287
|
+
"@stylistic/yield-star-spacing": ["error", {
|
|
288
|
+
after: true,
|
|
289
|
+
before: false
|
|
290
|
+
}],
|
|
291
|
+
"@stylistic/jsx-closing-bracket-location": "error",
|
|
292
|
+
"@stylistic/jsx-closing-tag-location": "error",
|
|
293
|
+
"@stylistic/jsx-curly-brace-presence": ["error", { propElementValues: "always" }],
|
|
294
|
+
"@stylistic/jsx-curly-newline": "error",
|
|
295
|
+
"@stylistic/jsx-curly-spacing": ["error", "never"],
|
|
296
|
+
"@stylistic/jsx-equals-spacing": "error",
|
|
297
|
+
"@stylistic/jsx-first-prop-new-line": "error",
|
|
298
|
+
"@stylistic/jsx-function-call-newline": ["error", "multiline"],
|
|
299
|
+
"@stylistic/jsx-indent-props": ["error", 2],
|
|
300
|
+
"@stylistic/jsx-max-props-per-line": ["error", {
|
|
301
|
+
maximum: 1,
|
|
302
|
+
when: "multiline"
|
|
303
|
+
}],
|
|
304
|
+
"@stylistic/jsx-one-expression-per-line": ["error", { allow: "single-child" }],
|
|
305
|
+
"@stylistic/jsx-quotes": "error",
|
|
306
|
+
"@stylistic/jsx-tag-spacing": ["error", {
|
|
307
|
+
afterOpening: "never",
|
|
308
|
+
beforeClosing: "never",
|
|
309
|
+
beforeSelfClosing: "always",
|
|
310
|
+
closingSlash: "never"
|
|
311
|
+
}],
|
|
312
|
+
"@stylistic/jsx-wrap-multilines": ["error", {
|
|
313
|
+
arrow: "parens-new-line",
|
|
314
|
+
assignment: "parens-new-line",
|
|
315
|
+
condition: "parens-new-line",
|
|
316
|
+
declaration: "parens-new-line",
|
|
317
|
+
logical: "parens-new-line",
|
|
318
|
+
prop: "parens-new-line",
|
|
319
|
+
propertyValue: "parens-new-line",
|
|
320
|
+
return: "parens-new-line"
|
|
321
|
+
}],
|
|
322
|
+
"@typescript-eslint/await-thenable": "error",
|
|
323
|
+
"@typescript-eslint/ban-ts-comment": ["error", { minimumDescriptionLength: 10 }],
|
|
324
|
+
"no-array-constructor": "error",
|
|
325
|
+
"@typescript-eslint/no-array-delete": "error",
|
|
326
|
+
"@typescript-eslint/no-base-to-string": "error",
|
|
327
|
+
"@typescript-eslint/no-confusing-void-expression": "error",
|
|
328
|
+
"@typescript-eslint/no-deprecated": "error",
|
|
329
|
+
"@typescript-eslint/no-duplicate-enum-values": "error",
|
|
330
|
+
"@typescript-eslint/no-duplicate-type-constituents": "error",
|
|
331
|
+
"@typescript-eslint/no-dynamic-delete": "error",
|
|
332
|
+
"@typescript-eslint/no-empty-object-type": ["error", {
|
|
333
|
+
allowInterfaces: "with-single-extends",
|
|
334
|
+
allowObjectTypes: "never"
|
|
335
|
+
}],
|
|
336
|
+
"@typescript-eslint/no-explicit-any": "error",
|
|
337
|
+
"@typescript-eslint/no-extra-non-null-assertion": "error",
|
|
338
|
+
"@typescript-eslint/no-extraneous-class": "error",
|
|
339
|
+
"@typescript-eslint/no-floating-promises": "error",
|
|
340
|
+
"@typescript-eslint/no-for-in-array": "error",
|
|
341
|
+
"@typescript-eslint/no-implied-eval": "error",
|
|
342
|
+
"@typescript-eslint/no-invalid-void-type": ["error", { allowAsThisParameter: true }],
|
|
343
|
+
"@typescript-eslint/no-meaningless-void-operator": "error",
|
|
344
|
+
"@typescript-eslint/no-misused-new": "error",
|
|
345
|
+
"@typescript-eslint/no-misused-promises": "error",
|
|
346
|
+
"@typescript-eslint/no-misused-spread": "error",
|
|
347
|
+
"@typescript-eslint/no-mixed-enums": "error",
|
|
348
|
+
"@typescript-eslint/no-namespace": "error",
|
|
349
|
+
"@typescript-eslint/no-non-null-asserted-nullish-coalescing": "error",
|
|
350
|
+
"@typescript-eslint/no-non-null-asserted-optional-chain": "error",
|
|
351
|
+
"@typescript-eslint/no-redundant-type-constituents": "error",
|
|
352
|
+
"@typescript-eslint/no-require-imports": "error",
|
|
353
|
+
"@typescript-eslint/no-this-alias": "error",
|
|
354
|
+
"@typescript-eslint/no-unnecessary-boolean-literal-compare": "error",
|
|
355
|
+
"@typescript-eslint/no-unnecessary-template-expression": "error",
|
|
356
|
+
"@typescript-eslint/no-unnecessary-type-arguments": "error",
|
|
357
|
+
"@typescript-eslint/no-unnecessary-type-assertion": "error",
|
|
358
|
+
"@typescript-eslint/no-unnecessary-type-constraint": "error",
|
|
359
|
+
"@typescript-eslint/no-unsafe-argument": "error",
|
|
360
|
+
"@typescript-eslint/no-unsafe-assignment": "error",
|
|
361
|
+
"@typescript-eslint/no-unsafe-call": "error",
|
|
362
|
+
"@typescript-eslint/no-unsafe-declaration-merging": "error",
|
|
363
|
+
"@typescript-eslint/no-unsafe-enum-comparison": "error",
|
|
364
|
+
"@typescript-eslint/no-unsafe-function-type": "error",
|
|
365
|
+
"@typescript-eslint/no-unsafe-member-access": "error",
|
|
366
|
+
"@typescript-eslint/no-unsafe-return": "error",
|
|
367
|
+
"@typescript-eslint/no-unsafe-unary-minus": "error",
|
|
368
|
+
"no-unused-expressions": ["error", {
|
|
369
|
+
allowShortCircuit: true,
|
|
370
|
+
allowTernary: true,
|
|
371
|
+
allowTaggedTemplates: true
|
|
372
|
+
}],
|
|
373
|
+
"no-useless-constructor": "error",
|
|
374
|
+
"@typescript-eslint/no-wrapper-object-types": "error",
|
|
375
|
+
"@typescript-eslint/only-throw-error": "error",
|
|
376
|
+
"@typescript-eslint/prefer-as-const": "error",
|
|
377
|
+
"@typescript-eslint/prefer-literal-enum-member": "error",
|
|
378
|
+
"@typescript-eslint/prefer-namespace-keyword": "error",
|
|
379
|
+
"@typescript-eslint/prefer-promise-reject-errors": "error",
|
|
380
|
+
"@typescript-eslint/prefer-reduce-type-parameter": "error",
|
|
381
|
+
"@typescript-eslint/prefer-return-this-type": "error",
|
|
382
|
+
"@typescript-eslint/related-getter-setter-pairs": "error",
|
|
383
|
+
"@typescript-eslint/require-await": "error",
|
|
384
|
+
"@typescript-eslint/restrict-plus-operands": ["error", {
|
|
385
|
+
allowAny: false,
|
|
386
|
+
allowBoolean: false,
|
|
387
|
+
allowNullish: false,
|
|
388
|
+
allowNumberAndString: false,
|
|
389
|
+
allowRegExp: false
|
|
390
|
+
}],
|
|
391
|
+
"@typescript-eslint/return-await": ["error", "error-handling-correctness-only"],
|
|
392
|
+
"@typescript-eslint/triple-slash-reference": "error",
|
|
393
|
+
"@typescript-eslint/unbound-method": ["error", { ignoreStatic: true }],
|
|
394
|
+
"@typescript-eslint/use-unknown-in-catch-callback-variable": "error",
|
|
395
|
+
"@typescript-eslint/adjacent-overload-signatures": "error",
|
|
396
|
+
"@typescript-eslint/array-type": "error",
|
|
397
|
+
"@typescript-eslint/ban-tslint-comment": "error",
|
|
398
|
+
"@typescript-eslint/class-literal-property-style": "error",
|
|
399
|
+
"@typescript-eslint/consistent-generic-constructors": "error",
|
|
400
|
+
"@typescript-eslint/consistent-indexed-object-style": "error",
|
|
401
|
+
"@typescript-eslint/consistent-type-assertions": "error",
|
|
402
|
+
"@typescript-eslint/consistent-type-definitions": "error",
|
|
403
|
+
"@typescript-eslint/no-confusing-non-null-assertion": "error",
|
|
404
|
+
"no-empty-function": "error",
|
|
405
|
+
"@typescript-eslint/no-inferrable-types": "error",
|
|
406
|
+
"@typescript-eslint/non-nullable-type-assertion-style": "error",
|
|
407
|
+
"@typescript-eslint/prefer-for-of": "error",
|
|
408
|
+
"@typescript-eslint/prefer-function-type": "error",
|
|
409
|
+
"@typescript-eslint/prefer-includes": "error",
|
|
410
|
+
"@typescript-eslint/prefer-nullish-coalescing": ["error", { ignoreTernaryTests: true }],
|
|
411
|
+
"perfectionist/sort-variable-declarations": ["error", {
|
|
412
|
+
type: "natural",
|
|
413
|
+
order: "asc"
|
|
414
|
+
}],
|
|
415
|
+
"perfectionist/sort-intersection-types": ["error", {
|
|
416
|
+
type: "natural",
|
|
417
|
+
order: "asc"
|
|
418
|
+
}],
|
|
419
|
+
"perfectionist/sort-heritage-clauses": ["error", {
|
|
420
|
+
type: "natural",
|
|
421
|
+
order: "asc"
|
|
422
|
+
}],
|
|
423
|
+
"perfectionist/sort-array-includes": ["error", {
|
|
424
|
+
type: "natural",
|
|
425
|
+
order: "asc"
|
|
426
|
+
}],
|
|
427
|
+
"perfectionist/sort-named-imports": ["error", {
|
|
428
|
+
type: "natural",
|
|
429
|
+
order: "asc"
|
|
430
|
+
}],
|
|
431
|
+
"perfectionist/sort-named-exports": ["error", {
|
|
432
|
+
type: "natural",
|
|
433
|
+
order: "asc"
|
|
434
|
+
}],
|
|
435
|
+
"perfectionist/sort-union-types": ["error", {
|
|
436
|
+
type: "natural",
|
|
437
|
+
order: "asc"
|
|
438
|
+
}],
|
|
439
|
+
"perfectionist/sort-switch-case": ["error", {
|
|
440
|
+
type: "natural",
|
|
441
|
+
order: "asc"
|
|
442
|
+
}],
|
|
443
|
+
"perfectionist/sort-decorators": ["error", {
|
|
444
|
+
type: "natural",
|
|
445
|
+
order: "asc"
|
|
446
|
+
}],
|
|
447
|
+
"perfectionist/sort-jsx-props": ["error", {
|
|
448
|
+
type: "natural",
|
|
449
|
+
order: "asc"
|
|
450
|
+
}],
|
|
451
|
+
"perfectionist/sort-exports": ["error", {
|
|
452
|
+
type: "natural",
|
|
453
|
+
order: "asc"
|
|
454
|
+
}],
|
|
455
|
+
"perfectionist/sort-enums": ["error", {
|
|
456
|
+
type: "natural",
|
|
457
|
+
order: "asc"
|
|
458
|
+
}],
|
|
459
|
+
"perfectionist/sort-sets": ["error", {
|
|
460
|
+
type: "natural",
|
|
461
|
+
order: "asc"
|
|
462
|
+
}],
|
|
463
|
+
"perfectionist/sort-maps": ["error", {
|
|
464
|
+
type: "natural",
|
|
465
|
+
order: "asc"
|
|
466
|
+
}],
|
|
467
|
+
"@typescript-eslint/consistent-type-imports": ["error", { fixStyle: "separate-type-imports" }],
|
|
468
|
+
"prefer-const": ["error", {
|
|
469
|
+
destructuring: "all",
|
|
470
|
+
ignoreReadBeforeAssign: false
|
|
471
|
+
}]
|
|
472
|
+
},
|
|
473
|
+
overrides: [{
|
|
474
|
+
files: [
|
|
475
|
+
"**/*.ts",
|
|
476
|
+
"**/*.tsx",
|
|
477
|
+
"**/*.mts",
|
|
478
|
+
"**/*.cts"
|
|
479
|
+
],
|
|
480
|
+
rules: {
|
|
481
|
+
"constructor-super": "off",
|
|
482
|
+
"no-class-assign": "off",
|
|
483
|
+
"no-const-assign": "off",
|
|
484
|
+
"no-dupe-class-members": "off",
|
|
485
|
+
"no-dupe-keys": "off",
|
|
486
|
+
"no-func-assign": "off",
|
|
487
|
+
"no-import-assign": "off",
|
|
488
|
+
"no-new-native-nonconstructor": "off",
|
|
489
|
+
"no-obj-calls": "off",
|
|
490
|
+
"no-redeclare": "off",
|
|
491
|
+
"no-setter-return": "off",
|
|
492
|
+
"no-this-before-super": "off",
|
|
493
|
+
"no-unsafe-negation": "off",
|
|
494
|
+
"no-var": "error",
|
|
495
|
+
"no-with": "off",
|
|
496
|
+
"prefer-rest-params": "error",
|
|
497
|
+
"prefer-spread": "error"
|
|
498
|
+
}
|
|
499
|
+
}]
|
|
500
|
+
};
|
|
501
|
+
//#endregion
|
|
502
|
+
//#region src/pack.ts
|
|
503
|
+
const pack = {
|
|
504
|
+
dts: true,
|
|
505
|
+
format: ["esm"],
|
|
506
|
+
sourcemap: false
|
|
507
|
+
};
|
|
508
|
+
//#endregion
|
|
509
|
+
//#region src/run.ts
|
|
510
|
+
function hasWorkspaceMarker(dir) {
|
|
511
|
+
if (existsSync(join(dir, "pnpm-workspace.yaml")) || existsSync(join(dir, "pnpm-workspace.yml"))) return true;
|
|
512
|
+
try {
|
|
513
|
+
const pkg = JSON.parse(readFileSync(join(dir, "package.json"), "utf8"));
|
|
514
|
+
return Array.isArray(pkg.workspaces);
|
|
515
|
+
} catch {
|
|
516
|
+
return false;
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
/**
|
|
520
|
+
* Directory of the vite config that called us. process.cwd() is unreliable — vp
|
|
521
|
+
* evaluates every package's config from the invocation cwd — so we recover the
|
|
522
|
+
* caller's location from the stack instead. vp bundles each config to
|
|
523
|
+
* `<pkg>/node_modules/.vite-temp/...`; the package dir is the part before that.
|
|
524
|
+
*/
|
|
525
|
+
function callerPackageDir() {
|
|
526
|
+
const stack = (/* @__PURE__ */ new Error()).stack ?? "";
|
|
527
|
+
for (const line of stack.split("\n")) {
|
|
528
|
+
const temp = line.match(/(\/.+?)\/node_modules\/\.vite-temp\//);
|
|
529
|
+
if (temp) return temp[1];
|
|
530
|
+
const direct = line.match(/(\/.+?)\/[^/]*\.config\.[^/\s:)]+/);
|
|
531
|
+
if (direct && !direct[1].includes("/node_modules/")) return direct[1];
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
/** True when the calling config's package is the workspace root (or a standalone project). */
|
|
535
|
+
function isProjectRoot() {
|
|
536
|
+
const dir = callerPackageDir() ?? process.cwd();
|
|
537
|
+
if (hasWorkspaceMarker(dir)) return true;
|
|
538
|
+
let parent = dirname(dir);
|
|
539
|
+
while (parent !== dirname(parent)) {
|
|
540
|
+
if (hasWorkspaceMarker(parent)) return false;
|
|
541
|
+
parent = dirname(parent);
|
|
542
|
+
}
|
|
543
|
+
return true;
|
|
544
|
+
}
|
|
545
|
+
function buildRunConfig(options = {}) {
|
|
546
|
+
const tasks = {
|
|
547
|
+
"check": { command: "vp check --fix" },
|
|
548
|
+
"test": { command: "vp test --run --passWithNoTests" },
|
|
549
|
+
"test:watch": {
|
|
550
|
+
command: "vp test --passWithNoTests",
|
|
551
|
+
cache: false
|
|
552
|
+
},
|
|
553
|
+
"test:coverage": { command: "vp test --coverage --passWithNoTests" }
|
|
554
|
+
};
|
|
555
|
+
switch (true) {
|
|
556
|
+
case options.lib:
|
|
557
|
+
tasks.build = { command: "vp pack" };
|
|
558
|
+
tasks.dev = {
|
|
559
|
+
command: "vp pack --watch",
|
|
560
|
+
cache: false
|
|
561
|
+
};
|
|
562
|
+
tasks.release = {
|
|
563
|
+
command: "vp check --fix && vp test --run --passWithNoTests && vp pack && vpx bumpp && pnpm publish",
|
|
564
|
+
cache: false
|
|
565
|
+
};
|
|
566
|
+
break;
|
|
567
|
+
case options.nuxt === "spa":
|
|
568
|
+
tasks.build = { command: "nuxt generate" };
|
|
569
|
+
tasks.dev = {
|
|
570
|
+
command: "nuxt dev",
|
|
571
|
+
cache: false
|
|
572
|
+
};
|
|
573
|
+
break;
|
|
574
|
+
case options.nuxt === "ssr":
|
|
575
|
+
tasks.build = { command: "nuxt build" };
|
|
576
|
+
tasks.dev = {
|
|
577
|
+
command: "nuxt dev",
|
|
578
|
+
cache: false
|
|
579
|
+
};
|
|
580
|
+
break;
|
|
581
|
+
case options.vueApp:
|
|
582
|
+
tasks.build = { command: "vite build" };
|
|
583
|
+
tasks.dev = {
|
|
584
|
+
command: "vite dev",
|
|
585
|
+
cache: false
|
|
586
|
+
};
|
|
587
|
+
break;
|
|
588
|
+
}
|
|
589
|
+
if (isProjectRoot()) tasks["setup:vscode"] = {
|
|
590
|
+
command: "vp-setup-vscode",
|
|
591
|
+
cache: false
|
|
592
|
+
};
|
|
593
|
+
return { tasks };
|
|
594
|
+
}
|
|
595
|
+
//#endregion
|
|
596
|
+
//#region src/staged.ts
|
|
597
|
+
const staged = { "*.{js,ts,tsx,vue}": "vp check --fix" };
|
|
598
|
+
//#endregion
|
|
599
|
+
//#region src/vue-lint.ts
|
|
600
|
+
const vueLint = {
|
|
601
|
+
plugins: ["vue"],
|
|
602
|
+
overrides: [{
|
|
603
|
+
files: ["**/*.vue"],
|
|
604
|
+
rules: { "@stylistic/no-multiple-empty-lines": ["error", {
|
|
605
|
+
max: 1,
|
|
606
|
+
maxBOF: 1,
|
|
607
|
+
maxEOF: 0
|
|
608
|
+
}] }
|
|
609
|
+
}, {
|
|
610
|
+
files: ["**/*.stories.ts", "**/*.stories.tsx"],
|
|
611
|
+
rules: {
|
|
612
|
+
"@typescript-eslint/no-unsafe-assignment": "off",
|
|
613
|
+
"@typescript-eslint/no-unsafe-argument": "off",
|
|
614
|
+
"@typescript-eslint/no-unsafe-call": "off",
|
|
615
|
+
"@typescript-eslint/no-unsafe-member-access": "off",
|
|
616
|
+
"@typescript-eslint/no-unsafe-return": "off"
|
|
617
|
+
}
|
|
618
|
+
}],
|
|
619
|
+
rules: {
|
|
620
|
+
"vue/define-emits-declaration": ["error", "type-based"],
|
|
621
|
+
"vue/define-props-declaration": ["error", "type-based"],
|
|
622
|
+
"vue/define-props-destructuring": "allow",
|
|
623
|
+
"vue/no-export-in-script-setup": "error",
|
|
624
|
+
"vue/no-import-compiler-macros": "error",
|
|
625
|
+
"vue/no-lifecycle-after-await": "error",
|
|
626
|
+
"vue/no-multiple-slot-args": "error",
|
|
627
|
+
"vue/no-required-prop-with-default": "error",
|
|
628
|
+
"vue/no-this-in-before-route-enter": "error",
|
|
629
|
+
"vue/prefer-import-from-vue": "error",
|
|
630
|
+
"vue/require-default-export": "error",
|
|
631
|
+
"vue/require-typed-ref": "error",
|
|
632
|
+
"vue/valid-define-emits": "error",
|
|
633
|
+
"vue/valid-define-props": "error"
|
|
634
|
+
}
|
|
635
|
+
};
|
|
636
|
+
//#endregion
|
|
637
|
+
//#region src/index.ts
|
|
638
|
+
const DEEP_MERGE_KEYS = new Set([
|
|
639
|
+
"fmt",
|
|
640
|
+
"pack",
|
|
641
|
+
"staged"
|
|
642
|
+
]);
|
|
643
|
+
function deepExtend(target, source) {
|
|
644
|
+
if (source === void 0) return target;
|
|
645
|
+
if (Array.isArray(target) && Array.isArray(source)) return [...target, ...source];
|
|
646
|
+
if (target !== null && typeof target === "object" && !Array.isArray(target) && source !== null && typeof source === "object" && !Array.isArray(source)) {
|
|
647
|
+
const result = { ...target };
|
|
648
|
+
for (const [key, value] of Object.entries(source)) result[key] = key in result ? deepExtend(result[key], value) : value;
|
|
649
|
+
return result;
|
|
650
|
+
}
|
|
651
|
+
return source;
|
|
652
|
+
}
|
|
653
|
+
function mergeLayers(base, ...layers) {
|
|
654
|
+
const result = { ...base };
|
|
655
|
+
for (const layer of layers) {
|
|
656
|
+
if (layer.lint) {
|
|
657
|
+
const { extends: layerExtends, ...layerLintRest } = layer.lint;
|
|
658
|
+
const baseArr = result.lint ? [result.lint] : [];
|
|
659
|
+
const combined = layerExtends !== void 0 ? [...baseArr, ...Array.isArray(layerExtends) ? layerExtends : [layerExtends]] : baseArr;
|
|
660
|
+
result.lint = combined.length > 0 ? {
|
|
661
|
+
extends: combined,
|
|
662
|
+
...layerLintRest
|
|
663
|
+
} : { ...layerLintRest };
|
|
664
|
+
}
|
|
665
|
+
if (layer.run) result.run = {
|
|
666
|
+
...result.run,
|
|
667
|
+
...layer.run,
|
|
668
|
+
tasks: {
|
|
669
|
+
...result.run?.tasks,
|
|
670
|
+
...layer.run.tasks
|
|
671
|
+
}
|
|
672
|
+
};
|
|
673
|
+
for (const [key, value] of Object.entries(layer)) {
|
|
674
|
+
if (key === "lint" || key === "run") continue;
|
|
675
|
+
if (DEEP_MERGE_KEYS.has(key)) result[key] = {
|
|
676
|
+
...result[key],
|
|
677
|
+
...value
|
|
678
|
+
};
|
|
679
|
+
else result[key] = value;
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
return result;
|
|
683
|
+
}
|
|
684
|
+
function mergeLintConfigs(...configs) {
|
|
685
|
+
if (configs.length === 0) return {};
|
|
686
|
+
if (configs.length === 1) return { ...configs[0] };
|
|
687
|
+
return configs.reduce((acc, config) => {
|
|
688
|
+
const merged = { ...acc };
|
|
689
|
+
for (const [key, value] of Object.entries(config)) {
|
|
690
|
+
const existing = merged[key];
|
|
691
|
+
if (Array.isArray(existing) && Array.isArray(value)) merged[key] = [...existing, ...value];
|
|
692
|
+
else if (existing && typeof existing === "object" && !Array.isArray(existing) && value && typeof value === "object" && !Array.isArray(value)) merged[key] = {
|
|
693
|
+
...existing,
|
|
694
|
+
...value
|
|
695
|
+
};
|
|
696
|
+
else merged[key] = value;
|
|
697
|
+
}
|
|
698
|
+
return merged;
|
|
699
|
+
});
|
|
700
|
+
}
|
|
701
|
+
function defineConfig(options = {}) {
|
|
702
|
+
const t = options.type;
|
|
703
|
+
const isVue = t === "lib:vue" || t === "lib:nuxt" || t === "vue" || t === "nuxt:spa" || t === "nuxt:ssr";
|
|
704
|
+
const isLib = t === "lib" || t === "lib:vue" || t === "lib:nuxt";
|
|
705
|
+
const overridesPack = options.overrides?.pack;
|
|
706
|
+
const extendsPack = options.extends?.pack;
|
|
707
|
+
const isPack = (isLib || !!overridesPack || !!extendsPack) && overridesPack !== false && extendsPack !== false;
|
|
708
|
+
const lintLayers = [lint];
|
|
709
|
+
if (isVue) lintLayers.push(vueLint);
|
|
710
|
+
if (options.overrides?.lint) lintLayers.push(options.overrides.lint);
|
|
711
|
+
if (options.extends?.lint) lintLayers.push(options.extends.lint);
|
|
712
|
+
let mergedLint = mergeLintConfigs(...lintLayers);
|
|
713
|
+
if (options.overrides?.ignorePatterns) mergedLint = {
|
|
714
|
+
...mergedLint,
|
|
715
|
+
ignorePatterns: options.overrides.ignorePatterns
|
|
716
|
+
};
|
|
717
|
+
if (options.extends?.ignorePatterns) mergedLint = {
|
|
718
|
+
...mergedLint,
|
|
719
|
+
ignorePatterns: [...mergedLint.ignorePatterns ?? [], ...options.extends.ignorePatterns]
|
|
720
|
+
};
|
|
721
|
+
let mergedFmt = fmt;
|
|
722
|
+
if (options.overrides?.ignorePatterns) mergedFmt = {
|
|
723
|
+
...mergedFmt,
|
|
724
|
+
ignorePatterns: options.overrides.ignorePatterns
|
|
725
|
+
};
|
|
726
|
+
if (options.extends?.ignorePatterns) mergedFmt = {
|
|
727
|
+
...mergedFmt,
|
|
728
|
+
ignorePatterns: [...mergedFmt?.ignorePatterns ?? [], ...options.extends.ignorePatterns]
|
|
729
|
+
};
|
|
730
|
+
const run = buildRunConfig({
|
|
731
|
+
lib: isLib,
|
|
732
|
+
nuxt: t === "nuxt:spa" ? "spa" : t === "nuxt:ssr" ? "ssr" : void 0,
|
|
733
|
+
vueApp: t === "vue"
|
|
734
|
+
});
|
|
735
|
+
let result = {
|
|
736
|
+
lint: mergedLint,
|
|
737
|
+
fmt: mergedFmt,
|
|
738
|
+
staged,
|
|
739
|
+
run,
|
|
740
|
+
...isPack && { pack }
|
|
741
|
+
};
|
|
742
|
+
if (options.overrides) {
|
|
743
|
+
const { lint: _l, ignorePatterns: _ip, pack: _p, ...rest } = options.overrides;
|
|
744
|
+
const layer = overridesPack !== void 0 && overridesPack !== false ? {
|
|
745
|
+
...rest,
|
|
746
|
+
pack: overridesPack
|
|
747
|
+
} : rest;
|
|
748
|
+
if (Object.keys(layer).length > 0) result = mergeLayers(result, layer);
|
|
749
|
+
}
|
|
750
|
+
if (options.extends) {
|
|
751
|
+
const { lint: _l, ignorePatterns: _ip, pack: _p, ...rest } = options.extends;
|
|
752
|
+
const layer = extendsPack !== void 0 && extendsPack !== false ? {
|
|
753
|
+
...rest,
|
|
754
|
+
pack: extendsPack
|
|
755
|
+
} : rest;
|
|
756
|
+
if (Object.keys(layer).length > 0) result = deepExtend(result, layer);
|
|
757
|
+
}
|
|
758
|
+
return result;
|
|
759
|
+
}
|
|
760
|
+
//#endregion
|
|
761
|
+
export { defineConfig };
|
package/package.json
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "config-vp",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Shared vite-plus configuration — opinionated defaults for linting, formatting, task running, staged checks, and VSCode setup. Optional Vue and pack layers with deep-merge overrides.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"config",
|
|
7
|
+
"eslint",
|
|
8
|
+
"formatter",
|
|
9
|
+
"linter",
|
|
10
|
+
"monorepo",
|
|
11
|
+
"oxfmt",
|
|
12
|
+
"oxlint",
|
|
13
|
+
"perfectionist",
|
|
14
|
+
"stylistic",
|
|
15
|
+
"typescript",
|
|
16
|
+
"vite-plus",
|
|
17
|
+
"vscode",
|
|
18
|
+
"vue"
|
|
19
|
+
],
|
|
20
|
+
"homepage": "https://github.com/orimay/config-vp#readme",
|
|
21
|
+
"bugs": {
|
|
22
|
+
"url": "https://github.com/orimay/config-vp/issues"
|
|
23
|
+
},
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"author": "Dmitrii Baranov <dmitrii.a.baranov@gmail.com>",
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "git+https://github.com/orimay/config-vp.git"
|
|
29
|
+
},
|
|
30
|
+
"bin": {
|
|
31
|
+
"vp-setup-vscode": "./bin/vp-setup-vscode.mjs"
|
|
32
|
+
},
|
|
33
|
+
"files": [
|
|
34
|
+
"bin",
|
|
35
|
+
"dist"
|
|
36
|
+
],
|
|
37
|
+
"type": "module",
|
|
38
|
+
"main": "./dist/index.mjs",
|
|
39
|
+
"module": "./dist/index.mjs",
|
|
40
|
+
"types": "./dist/index.d.mts",
|
|
41
|
+
"exports": {
|
|
42
|
+
".": {
|
|
43
|
+
"types": "./dist/index.d.mts",
|
|
44
|
+
"import": "./dist/index.mjs"
|
|
45
|
+
},
|
|
46
|
+
"./package.json": "./package.json"
|
|
47
|
+
},
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"@stylistic/eslint-plugin": "^5.10.0",
|
|
50
|
+
"eslint-plugin-perfectionist": "^5.8.0",
|
|
51
|
+
"jsonc-parser": "^3.3.1",
|
|
52
|
+
"oxfmt": "^0.45.0",
|
|
53
|
+
"oxlint": "^1.60.0"
|
|
54
|
+
},
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"@types/node": "^24.10.1",
|
|
57
|
+
"typescript": "^6.0.2"
|
|
58
|
+
},
|
|
59
|
+
"peerDependencies": {
|
|
60
|
+
"vite-plus": ">=0.1.24"
|
|
61
|
+
}
|
|
62
|
+
}
|