@qstanay/eslint-config 1.0.0 → 1.0.2

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/CHANGELOG.md ADDED
@@ -0,0 +1,48 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented in this file.
4
+
5
+ ## [1.0.2] - 2026-07-18
6
+
7
+ ### Added
8
+
9
+ - `@eslint/js` recommended as the JavaScript baseline in `defineConfig()`
10
+ - Autofixable `import/order` (grouped + alphabetized)
11
+ - `strict` option for `defineConfig()` / `nuxt()` to opt into stricter TypeScript rules (e.g. `no-magic-numbers`)
12
+ - `ignores` option on the Nuxt preset (`nuxt({ ignores: [...] })`)
13
+ - npm `keywords` for discoverability
14
+
15
+ ### Changed
16
+
17
+ - `no-magic-numbers` is no longer enabled by default (use `strict: true`)
18
+ - When TypeScript is enabled, turn off conflicting base rules (`no-unused-vars`, `no-undef`)
19
+
20
+ ## [1.0.1] - 2026-07-18
21
+
22
+ ### Fixed
23
+
24
+ - Correctly apply the full `eslint-plugin-vue` `flat/recommended` preset (previously only `[0].rules` was used, which contained no rules)
25
+ - Include TypeScript shared rules only when TypeScript is enabled (JS-only projects no longer crash on a missing `@typescript-eslint` plugin)
26
+ - Apply `overrides` in a trailing config block so they win over shared/Vue rules in both `defineConfig()` and `nuxt()`
27
+
28
+ ### Added
29
+
30
+ - Honor project `.gitignore` in ignores and add `coverage` to default ignores
31
+ - Browser `globals` for Vue; load TypeScript rules from `flat/recommended`
32
+ - `prepublishOnly` build hook
33
+ - Expanded README for humans and agents
34
+ - Tests for JS-only setups, Vue recommended rules, and overrides behavior
35
+
36
+ ### Removed
37
+
38
+ - Unused dependency `eslint-processor-vue-blocks`
39
+
40
+ ## [1.0.0] - 2026-07-13
41
+
42
+ ### Added
43
+
44
+ - Initial release of `@qstanay/eslint-config`
45
+ - `defineConfig()` for Vue and TypeScript projects
46
+ - `@qstanay/eslint-config/nuxt` layer for use with `@nuxt/eslint` + `withNuxt()`
47
+ - Stylistic formatting via `@stylistic` (`eslint --fix`)
48
+ - Shared opinionated JS/TS rules, import hygiene, and Vue opinionated extras
package/README.md CHANGED
@@ -1,17 +1,24 @@
1
1
  # @qstanay/eslint-config
2
2
 
3
- Opinionated ESLint **flat config** for:
3
+ Opinionated ESLint **flat config** for Nuxt apps, Vue apps, and TypeScript packages.
4
4
 
5
- - Nuxt applications
6
- - Vue applications
7
- - TypeScript packages
5
+ Formatting is handled by ESLint via **@stylistic** (`eslint --fix`). Do **not** use Prettier alongside this preset unless you disable stylistic rules.
8
6
 
9
- This preset uses **@stylistic** for formatting through ESLint (single toolchain: `eslint --fix`).
7
+ ## Quick pick
8
+
9
+ | Project type | Use this |
10
+ |---|---|
11
+ | **Nuxt** | `@qstanay/eslint-config/nuxt` with `@nuxt/eslint` + `withNuxt()` |
12
+ | **Vue (Vite / SPA)** | `defineConfig()` from `@qstanay/eslint-config` |
13
+ | **TypeScript package / library** | `defineConfig()` from `@qstanay/eslint-config` |
14
+
15
+ For Nuxt, prefer the `/nuxt` entry. It only adds opinionated rules + formatting on top of Nuxt's own TypeScript/Vue setup. It does **not** replace `@nuxt/eslint`.
10
16
 
11
17
  ## Requirements
12
18
 
13
- - Node.js 18+ recommended
19
+ - Node.js 18+
14
20
  - ESLint `^9 || ^10`
21
+ - Flat config only (`eslint.config.js` / `.mjs` / `.ts`)
15
22
 
16
23
  ## Install
17
24
 
@@ -19,13 +26,17 @@ This preset uses **@stylistic** for formatting through ESLint (single toolchain:
19
26
  npm i -D eslint @qstanay/eslint-config
20
27
  ```
21
28
 
29
+ For Nuxt also install and enable the Nuxt ESLint module:
30
+
31
+ ```bash
32
+ npm i -D @nuxt/eslint
33
+ ```
34
+
22
35
  ## Usage
23
36
 
24
37
  ### Nuxt (recommended)
25
38
 
26
- In a Nuxt app, use `@nuxt/eslint` module and layer this preset on top of Nuxt generated config.
27
-
28
- 1) Ensure Nuxt ESLint module is enabled in `nuxt.config.ts`:
39
+ 1. Enable the module in `nuxt.config.ts`:
29
40
 
30
41
  ```ts
31
42
  export default defineNuxtConfig({
@@ -33,7 +44,7 @@ export default defineNuxtConfig({
33
44
  })
34
45
  ```
35
46
 
36
- 2) Create `eslint.config.mjs`:
47
+ 2. Create `eslint.config.mjs` in the project root:
37
48
 
38
49
  ```js
39
50
  import withNuxt from './.nuxt/eslint.config.mjs'
@@ -51,6 +62,17 @@ export default withNuxt(
51
62
  )
52
63
  ```
53
64
 
65
+ Run `nuxt prepare` (or start the dev server once) so `.nuxt/eslint.config.mjs` exists before linting.
66
+
67
+ Minimal form (defaults are fine for most projects):
68
+
69
+ ```js
70
+ import withNuxt from './.nuxt/eslint.config.mjs'
71
+ import { nuxt } from '@qstanay/eslint-config/nuxt'
72
+
73
+ export default withNuxt(...nuxt())
74
+ ```
75
+
54
76
  ### Vue (Vite) app
55
77
 
56
78
  Create `eslint.config.mjs`:
@@ -64,6 +86,14 @@ export default defineConfig({
64
86
  })
65
87
  ```
66
88
 
89
+ If `vue` and `typescript` are already installed, auto-detection is enough:
90
+
91
+ ```js
92
+ import { defineConfig } from '@qstanay/eslint-config'
93
+
94
+ export default defineConfig()
95
+ ```
96
+
67
97
  ### TypeScript package
68
98
 
69
99
  Create `eslint.config.mjs`:
@@ -72,17 +102,71 @@ Create `eslint.config.mjs`:
72
102
  import { defineConfig } from '@qstanay/eslint-config'
73
103
 
74
104
  export default defineConfig({
75
- vue: false,
76
- nuxt: false,
77
105
  typescript: true,
78
106
  })
79
107
  ```
80
108
 
109
+ Or rely on auto-detection when `typescript` is a dependency:
110
+
111
+ ```js
112
+ import { defineConfig } from '@qstanay/eslint-config'
113
+
114
+ export default defineConfig()
115
+ ```
116
+
81
117
  ## Options
82
118
 
119
+ ### `defineConfig(options, ...userConfigs)`
120
+
121
+ Main entry for Vue / TypeScript projects.
122
+
123
+ | Option | Type | Default | Description |
124
+ |---|---|---|---|
125
+ | `vue` | `boolean` | auto (`vue` or `nuxt` installed) | Enable Vue rules |
126
+ | `typescript` | `boolean` | auto (`typescript` installed) | Enable TypeScript rules |
127
+ | `nuxt` | `boolean` | auto (`nuxt` installed) | Enable Nuxt plugin rule(s). Prefer `/nuxt` for Nuxt apps |
128
+ | `strict` | `boolean` | `false` | Stricter TS rules (e.g. `no-magic-numbers`) |
129
+ | `stylistic` | `false \| object` | enabled | Formatting rules (see below) |
130
+ | `overrides` | `Linter.RulesRecord` | `{}` | Custom rules merged last over shared rules |
131
+ | `ignores` | `string[]` | `[]` | Extra ignore globs |
132
+
133
+ Extra flat-config blocks can be passed as additional arguments:
134
+
135
+ ```js
136
+ export default defineConfig(
137
+ { typescript: true },
138
+ {
139
+ files: ['scripts/**/*.ts'],
140
+ rules: {
141
+ 'no-console': 'off',
142
+ },
143
+ },
144
+ )
145
+ ```
146
+
147
+ ### `nuxt(options)` — `@qstanay/eslint-config/nuxt`
148
+
149
+ Layer for Nuxt apps used with `withNuxt(...nuxt())`.
150
+
151
+ | Option | Type | Default | Description |
152
+ |---|---|---|---|
153
+ | `stylistic` | `false \| object` | enabled | Formatting rules (see below) |
154
+ | `strict` | `boolean` | `false` | Stricter TS rules (e.g. `no-magic-numbers`) |
155
+ | `overrides` | `Linter.RulesRecord` | `{}` | Custom rules merged last over shared rules |
156
+ | `ignores` | `string[]` | `[]` | Extra ignore globs (plus defaults / `.gitignore`) |
157
+
158
+ There are no `vue` / `typescript` flags here — `@nuxt/eslint` already provides that stack. This preset adds shared opinionated rules, Vue opinionated rules, and stylistic formatting.
159
+
83
160
  ### `stylistic`
84
161
 
85
- Enable/disable formatting rules (enabled by default).
162
+ Enabled by default. Defaults:
163
+
164
+ | Key | Default |
165
+ |---|---|
166
+ | `indent` | `2` |
167
+ | `quotes` | `'single'` |
168
+ | `semi` | `true` |
169
+ | `maxLen` | `100` |
86
170
 
87
171
  ```js
88
172
  defineConfig({
@@ -95,33 +179,65 @@ defineConfig({
95
179
  })
96
180
  ```
97
181
 
98
- Set `stylistic: false` to disable all stylistic rules.
182
+ Disable formatting rules entirely:
99
183
 
100
- ### `overrides`
184
+ ```js
185
+ defineConfig({ stylistic: false })
186
+ // or for Nuxt:
187
+ nuxt({ stylistic: false })
188
+ ```
101
189
 
102
- Merge custom rules last.
190
+ ### `overrides`
103
191
 
104
192
  ```js
105
193
  defineConfig({
106
194
  overrides: {
107
195
  '@typescript-eslint/no-explicit-any': 'off',
196
+ 'no-console': 'off',
108
197
  },
109
198
  })
110
199
  ```
111
200
 
201
+ Same option works in `nuxt({ overrides: { ... } })`.
202
+
112
203
  ### `ignores`
113
204
 
114
- Add extra ignore globs.
205
+ Built-in ignores cover `node_modules`, `dist`, `.output`, `.nuxt`, `.nitro`, `coverage`, and the project `.gitignore` (when present).
115
206
 
116
207
  ```js
117
208
  defineConfig({
118
- ignores: ['**/coverage/**'],
209
+ ignores: ['**/fixtures/**'],
210
+ })
211
+
212
+ // Nuxt:
213
+ nuxt({
214
+ ignores: ['**/fixtures/**'],
119
215
  })
120
216
  ```
121
217
 
218
+ ## Prettier
219
+
220
+ **Do not use Prettier with this preset while `stylistic` is enabled.** Both tools format the same things (quotes, semicolons, indentation, line length) and will conflict.
221
+
222
+ Recommended setup:
223
+
224
+ - Keep `@stylistic` enabled
225
+ - Format with `eslint . --fix`
226
+ - Use ESLint as the editor formatter
227
+
228
+ If you must keep Prettier:
229
+
230
+ ```js
231
+ defineConfig({ stylistic: false })
232
+ // Nuxt:
233
+ nuxt({ stylistic: false })
234
+ ```
235
+
236
+ Then let Prettier own formatting and keep ESLint for logic/quality rules only.
237
+
122
238
  ## Scripts
123
239
 
124
- Suggested `package.json` scripts:
240
+ Add to `package.json`:
125
241
 
126
242
  ```json
127
243
  {
@@ -132,9 +248,9 @@ Suggested `package.json` scripts:
132
248
  }
133
249
  ```
134
250
 
135
- ## VS Code setup
251
+ ## VS Code / Cursor
136
252
 
137
- Use ESLint as the formatter and apply fixes on save.
253
+ Use ESLint as the formatter and fix on save.
138
254
 
139
255
  `.vscode/settings.json`:
140
256
 
@@ -144,12 +260,39 @@ Use ESLint as the formatter and apply fixes on save.
144
260
  "editor.formatOnSave": true,
145
261
  "editor.codeActionsOnSave": {
146
262
  "source.fixAll.eslint": "explicit"
147
- }
263
+ },
264
+ "eslint.useFlatConfig": true
148
265
  }
149
266
  ```
150
267
 
151
- ## Notes
268
+ Disable Prettier for the same file types (or uninstall / disable the Prettier extension in the project) to avoid fights on save.
269
+
270
+ ## What this preset enforces (high level)
271
+
272
+ - `@eslint/js` recommended as the JS baseline in `defineConfig()`
273
+ - Shared opinionated JS rules always; TypeScript opinionated rules only when TypeScript is enabled
274
+ - Official `eslint-plugin-vue` `flat/recommended` when Vue is enabled, plus a small opinionated Vue layer
275
+ - Stylistic formatting via `@stylistic` (rule namespace: `style/*`)
276
+ - Import hygiene + autofixable `import/order` via `eslint-plugin-import-x` in `defineConfig` (Nuxt relies on `@nuxt/eslint` for its own import/TS/Vue stack)
277
+ - `overrides` are applied in a trailing config block so they win over shared/Vue rules
278
+ - Optional `strict: true` for noisier TypeScript checks like `no-magic-numbers`
152
279
 
153
- - For Nuxt projects, this package intentionally does **not** replace `@nuxt/eslint` project-aware config. It extends it.
154
- - This package focuses on Nuxt/Vue/TypeScript. JSON/YAML/Markdown/CSS formatting can be added later if needed.
280
+ ## Agent / setup checklist
281
+
282
+ When adding this package to a project:
283
+
284
+ 1. Install `eslint` + `@qstanay/eslint-config` as devDependencies.
285
+ 2. Choose the correct entry:
286
+ - Nuxt → `@qstanay/eslint-config/nuxt` + `@nuxt/eslint` + `withNuxt(...nuxt())`
287
+ - Vue / TS → `defineConfig(...)`
288
+ 3. Create root `eslint.config.mjs` (or `.ts` if the project already supports it).
289
+ 4. Add `lint` / `lint:fix` scripts.
290
+ 5. Do **not** add Prettier for JS/TS/Vue unless `stylistic: false`.
291
+ 6. For Nuxt, ensure `@nuxt/eslint` is in `modules` and `.nuxt/eslint.config.mjs` exists (`nuxt prepare`).
292
+ 7. Prefer `overrides` for project-specific exceptions instead of forking the preset.
293
+
294
+ ## Notes
155
295
 
296
+ - Flat config only. Legacy `.eslintrc*` is not supported.
297
+ - Scope is Nuxt / Vue / TypeScript JS-like sources. JSON, YAML, Markdown, and CSS formatting are out of scope for now.
298
+ - License: MIT
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as StylisticOptions, i as OptionsConfig, n as nuxt, o as TypedFlatConfigItem, r as Awaitable } from "./nuxt-CehpYBa3.mjs";
1
+ import { a as StylisticOptions, i as OptionsConfig, n as nuxt, o as TypedFlatConfigItem, r as Awaitable } from "./nuxt-B4vvMBlj.mjs";
2
2
  import { FlatConfigComposer } from "eslint-flat-config-utils";
3
3
  //#region src/index.d.ts
4
4
  declare function defineConfig(options?: OptionsConfig, ...userConfigs: (Awaitable<TypedFlatConfigItem | TypedFlatConfigItem[]>)[]): FlatConfigComposer<TypedFlatConfigItem, never>;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/index.ts"],"mappings":";;;iBAegB,aACd,UAAS,kBACN,cAAc,UAAU,sBAAsB,4BAAyB,mBAAA"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/index.ts"],"mappings":";;;iBAiBgB,aACd,UAAS,kBACN,cAAc,UAAU,sBAAsB,4BAAyB,mBAAA"}
package/dist/index.mjs CHANGED
@@ -1,26 +1,113 @@
1
- import { a as nuxt$1, i as stylistic, n as vue, o as imports, r as typescript, s as sharedRules, t as nuxt } from "./nuxt-Cz6LtoZ_.mjs";
1
+ import { a as VUE_FILES, c as resolveStylisticOptions, d as ignores, i as TYPESCRIPT_FILES, l as stylistic, n as vueRules, o as has, r as SOURCE_FILES, s as resolveEnabled, t as nuxt, u as sharedRules } from "./nuxt-B6cDasrO.mjs";
2
2
  import { FlatConfigComposer } from "eslint-flat-config-utils";
3
- import { isPackageExists } from "local-pkg";
4
- //#region src/utils.ts
5
- function resolveEnabled(explicit, detected) {
6
- return explicit ?? detected;
3
+ //#region src/configs/imports.ts
4
+ async function imports() {
5
+ const mod = await import("eslint-plugin-import-x");
6
+ return [{
7
+ name: "qstanay/imports",
8
+ plugins: { import: mod.default ?? mod },
9
+ rules: {
10
+ "import/first": "error",
11
+ "import/no-duplicates": "error",
12
+ "import/no-mutable-exports": "error",
13
+ "import/no-named-default": "error",
14
+ "import/order": ["error", {
15
+ "groups": [
16
+ "builtin",
17
+ "external",
18
+ "internal",
19
+ [
20
+ "parent",
21
+ "sibling",
22
+ "index"
23
+ ],
24
+ "object",
25
+ "type"
26
+ ],
27
+ "newlines-between": "always",
28
+ "alphabetize": {
29
+ order: "asc",
30
+ caseInsensitive: true
31
+ }
32
+ }]
33
+ }
34
+ }];
7
35
  }
8
- function has(pkg) {
9
- return isPackageExists(pkg);
36
+ //#endregion
37
+ //#region src/configs/javascript.ts
38
+ /**
39
+ * Base JS quality rules from `@eslint/js` recommended.
40
+ */
41
+ async function javascript() {
42
+ const mod = await import("@eslint/js");
43
+ return [{
44
+ name: "qstanay/javascript",
45
+ rules: { ...(mod.default ?? mod).configs?.recommended?.rules ?? {} }
46
+ }];
10
47
  }
11
48
  //#endregion
12
- //#region src/configs/ignores.ts
13
- function ignores(extraIgnores = []) {
49
+ //#region src/configs/nuxt.ts
50
+ async function nuxt$1() {
51
+ const mod = await import("@nuxt/eslint-plugin");
14
52
  return [{
15
- name: "qstanay/ignores",
16
- ignores: [
17
- "**/node_modules/**",
18
- "**/dist/**",
19
- "**/.output/**",
20
- "**/.nuxt/**",
21
- "**/.nitro/**",
22
- ...extraIgnores
23
- ]
53
+ name: "qstanay/nuxt",
54
+ plugins: { nuxt: mod.default ?? mod },
55
+ rules: { "nuxt/prefer-import-meta": "error" }
56
+ }];
57
+ }
58
+ //#endregion
59
+ //#region src/configs/typescript.ts
60
+ function collectRules(configs) {
61
+ return Object.assign({}, ...configs.filter((config) => config.rules).map((config) => config.rules));
62
+ }
63
+ async function typescript() {
64
+ const parserMod = await import("@typescript-eslint/parser");
65
+ const pluginMod = await import("@typescript-eslint/eslint-plugin");
66
+ const parser = parserMod.default ?? parserMod;
67
+ const plugin = pluginMod.default ?? pluginMod;
68
+ const recommended = plugin.configs?.["flat/recommended"] ?? [];
69
+ return [{
70
+ name: "qstanay/typescript",
71
+ files: [...TYPESCRIPT_FILES],
72
+ languageOptions: {
73
+ parser,
74
+ parserOptions: {
75
+ sourceType: "module",
76
+ ecmaVersion: "latest",
77
+ extraFileExtensions: [".vue"]
78
+ }
79
+ },
80
+ plugins: { "@typescript-eslint": plugin },
81
+ rules: collectRules(recommended)
82
+ }];
83
+ }
84
+ //#endregion
85
+ //#region src/configs/vue.ts
86
+ /**
87
+ * Vue layer based on the official flat recommended preset.
88
+ * Must spread the full array — it includes setup, processor, and rule packs.
89
+ */
90
+ async function vue() {
91
+ const vuePluginMod = await import("eslint-plugin-vue");
92
+ const globalsMod = await import("globals");
93
+ const vuePlugin = vuePluginMod.default ?? vuePluginMod;
94
+ const globals = globalsMod.default ?? globalsMod;
95
+ return [...vuePlugin.configs?.["flat/recommended"] ?? [], {
96
+ name: "qstanay/vue/rules",
97
+ files: [...VUE_FILES],
98
+ languageOptions: {
99
+ globals: { ...globals.browser },
100
+ parserOptions: {
101
+ parser: {
102
+ ts: "@typescript-eslint/parser",
103
+ js: "espree"
104
+ },
105
+ ecmaVersion: "latest",
106
+ sourceType: "module",
107
+ extraFileExtensions: [".vue"]
108
+ }
109
+ },
110
+ rules: { ...vueRules() }
24
111
  }];
25
112
  }
26
113
  //#endregion
@@ -29,9 +116,10 @@ function defineConfig(options = {}, ...userConfigs) {
29
116
  const enableTs = resolveEnabled(options.typescript, has("typescript"));
30
117
  const enableVue = resolveEnabled(options.vue, has("vue") || has("nuxt"));
31
118
  const enableNuxt = resolveEnabled(options.nuxt, has("nuxt"));
32
- const stylisticOptions = options.stylistic === false ? false : typeof options.stylistic === "object" ? options.stylistic : {};
119
+ const stylisticOptions = resolveStylisticOptions(options.stylistic);
33
120
  const configs = [];
34
121
  configs.push(Promise.resolve(ignores(options.ignores)));
122
+ configs.push(javascript());
35
123
  if (enableTs) configs.push(typescript());
36
124
  configs.push(imports());
37
125
  if (stylisticOptions) configs.push(stylistic(stylisticOptions));
@@ -39,11 +127,16 @@ function defineConfig(options = {}, ...userConfigs) {
39
127
  if (enableNuxt) configs.push(nuxt$1());
40
128
  configs.push(Promise.resolve([{
41
129
  name: "qstanay/shared-rules",
42
- rules: {
43
- ...sharedRules(),
44
- ...options.overrides ?? {}
45
- },
46
- files: ["**/*.{js,jsx,ts,tsx,cts,mts,vue}"]
130
+ files: [...SOURCE_FILES],
131
+ rules: sharedRules({
132
+ typescript: enableTs,
133
+ strict: options.strict
134
+ })
135
+ }]));
136
+ if (options.overrides) configs.push(Promise.resolve([{
137
+ name: "qstanay/overrides",
138
+ files: [...SOURCE_FILES],
139
+ rules: options.overrides
47
140
  }]));
48
141
  const composer = new FlatConfigComposer();
49
142
  composer.append(...configs, ...userConfigs);
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["typescriptConfig","stylisticConfig","vueConfig","nuxtConfig"],"sources":["../src/utils.ts","../src/configs/ignores.ts","../src/index.ts"],"sourcesContent":["import { isPackageExists } from 'local-pkg';\n\nexport function resolveEnabled(explicit: boolean | undefined, detected: boolean) {\n return explicit ?? detected;\n}\n\nexport function has(pkg: string) {\n return isPackageExists(pkg);\n}\n","import type { TypedFlatConfigItem } from '../types';\n\nexport function ignores(extraIgnores: string[] = []): TypedFlatConfigItem[] {\n return [\n {\n name: 'qstanay/ignores',\n ignores: [\n '**/node_modules/**',\n '**/dist/**',\n '**/.output/**',\n '**/.nuxt/**',\n '**/.nitro/**',\n ...extraIgnores,\n ],\n },\n ];\n}\n","import type { Awaitable, OptionsConfig, TypedFlatConfigItem } from './types';\n\nimport { FlatConfigComposer } from 'eslint-flat-config-utils';\nimport { has, resolveEnabled } from './utils';\nimport { ignores } from './configs/ignores';\nimport { sharedRules } from './configs/shared-rules';\nimport { imports } from './configs/imports';\nimport { nuxt as nuxtConfig } from './configs/nuxt';\nimport { stylistic as stylisticConfig } from './configs/stylistic';\nimport { typescript as typescriptConfig } from './configs/typescript';\nimport { vue as vueConfig } from './configs/vue';\n\nexport { nuxt } from './nuxt';\nexport * from './types';\n\nexport function defineConfig(\n options: OptionsConfig = {},\n ...userConfigs: (Awaitable<TypedFlatConfigItem | TypedFlatConfigItem[]>)[]\n) {\n const enableTs = resolveEnabled(options.typescript, has('typescript'));\n const enableVue = resolveEnabled(options.vue, has('vue') || has('nuxt'));\n const enableNuxt = resolveEnabled(options.nuxt, has('nuxt'));\n\n const stylisticOptions = options.stylistic === false\n ? false\n : typeof options.stylistic === 'object'\n ? options.stylistic\n : {};\n\n const configs: (Awaitable<TypedFlatConfigItem[]>)[] = [];\n\n configs.push(Promise.resolve(ignores(options.ignores)));\n\n if (enableTs) {\n configs.push(typescriptConfig());\n }\n\n configs.push(imports());\n\n if (stylisticOptions) {\n configs.push(stylisticConfig(stylisticOptions));\n }\n\n if (enableVue) {\n configs.push(vueConfig());\n }\n\n if (enableNuxt) {\n configs.push(nuxtConfig());\n }\n\n configs.push(Promise.resolve([\n {\n name: 'qstanay/shared-rules',\n rules: {\n ...sharedRules(),\n ...(options.overrides ?? {}),\n },\n files: ['**/*.{js,jsx,ts,tsx,cts,mts,vue}'],\n },\n ]));\n\n const composer = new FlatConfigComposer<TypedFlatConfigItem>();\n composer.append(...configs, ...userConfigs as any);\n return composer;\n}\n"],"mappings":";;;;AAEA,SAAgB,eAAe,UAA+B,UAAmB;CAC/E,OAAO,YAAY;AACrB;AAEA,SAAgB,IAAI,KAAa;CAC/B,OAAO,gBAAgB,GAAG;AAC5B;;;ACNA,SAAgB,QAAQ,eAAyB,CAAC,GAA0B;CAC1E,OAAO,CACL;EACE,MAAM;EACN,SAAS;GACP;GACA;GACA;GACA;GACA;GACA,GAAG;EACL;CACF,CACF;AACF;;;ACDA,SAAgB,aACd,UAAyB,CAAC,GAC1B,GAAG,aACH;CACA,MAAM,WAAW,eAAe,QAAQ,YAAY,IAAI,YAAY,CAAC;CACrE,MAAM,YAAY,eAAe,QAAQ,KAAK,IAAI,KAAK,KAAK,IAAI,MAAM,CAAC;CACvE,MAAM,aAAa,eAAe,QAAQ,MAAM,IAAI,MAAM,CAAC;CAE3D,MAAM,mBAAmB,QAAQ,cAAc,QAC3C,QACA,OAAO,QAAQ,cAAc,WAC3B,QAAQ,YACR,CAAC;CAEP,MAAM,UAAgD,CAAC;CAEvD,QAAQ,KAAK,QAAQ,QAAQ,QAAQ,QAAQ,OAAO,CAAC,CAAC;CAEtD,IAAI,UACF,QAAQ,KAAKA,WAAiB,CAAC;CAGjC,QAAQ,KAAK,QAAQ,CAAC;CAEtB,IAAI,kBACF,QAAQ,KAAKC,UAAgB,gBAAgB,CAAC;CAGhD,IAAI,WACF,QAAQ,KAAKC,IAAU,CAAC;CAG1B,IAAI,YACF,QAAQ,KAAKC,OAAW,CAAC;CAG3B,QAAQ,KAAK,QAAQ,QAAQ,CAC3B;EACE,MAAM;EACN,OAAO;GACL,GAAG,YAAY;GACf,GAAI,QAAQ,aAAa,CAAC;EAC5B;EACA,OAAO,CAAC,kCAAkC;CAC5C,CACF,CAAC,CAAC;CAEF,MAAM,WAAW,IAAI,mBAAwC;CAC7D,SAAS,OAAO,GAAG,SAAS,GAAG,WAAkB;CACjD,OAAO;AACT"}
1
+ {"version":3,"file":"index.mjs","names":["nuxt","javascriptConfig","typescriptConfig","stylisticConfig","vueConfig","nuxtConfig"],"sources":["../src/configs/imports.ts","../src/configs/javascript.ts","../src/configs/nuxt.ts","../src/configs/typescript.ts","../src/configs/vue.ts","../src/index.ts"],"sourcesContent":["import type { TypedFlatConfigItem } from '../types';\n\nexport async function imports(): Promise<TypedFlatConfigItem[]> {\n const mod = await import('eslint-plugin-import-x');\n const plugin = (mod as any).default ?? mod;\n\n return [\n {\n name: 'qstanay/imports',\n plugins: {\n import: plugin,\n },\n rules: {\n 'import/first': 'error',\n 'import/no-duplicates': 'error',\n 'import/no-mutable-exports': 'error',\n 'import/no-named-default': 'error',\n 'import/order': [\n 'error',\n {\n 'groups': [\n 'builtin',\n 'external',\n 'internal',\n ['parent', 'sibling', 'index'],\n 'object',\n 'type',\n ],\n 'newlines-between': 'always',\n 'alphabetize': {\n order: 'asc',\n caseInsensitive: true,\n },\n },\n ],\n },\n },\n ];\n}\n","import type { TypedFlatConfigItem } from '../types';\n\n/**\n * Base JS quality rules from `@eslint/js` recommended.\n */\nexport async function javascript(): Promise<TypedFlatConfigItem[]> {\n const mod = await import('@eslint/js');\n const js = (mod as any).default ?? mod;\n\n return [\n {\n name: 'qstanay/javascript',\n rules: {\n ...(js.configs?.recommended?.rules ?? {}),\n },\n },\n ];\n}\n","import type { TypedFlatConfigItem } from '../types';\n\nexport async function nuxt(): Promise<TypedFlatConfigItem[]> {\n const mod = await import('@nuxt/eslint-plugin');\n const plugin = (mod as any).default ?? mod;\n\n return [\n {\n name: 'qstanay/nuxt',\n plugins: {\n nuxt: plugin,\n },\n rules: {\n // keep this minimal; Nuxt base config already provides most of it\n 'nuxt/prefer-import-meta': 'error',\n },\n },\n ];\n}\n","import { TYPESCRIPT_FILES } from '../utils';\n\nimport type { TypedFlatConfigItem } from '../types';\nimport type { Linter } from 'eslint';\n\nfunction collectRules(configs: TypedFlatConfigItem[]): Linter.RulesRecord {\n return Object.assign(\n {},\n ...configs\n .filter(config => config.rules)\n .map(config => config.rules),\n );\n}\n\nexport async function typescript(): Promise<TypedFlatConfigItem[]> {\n const parserMod = await import('@typescript-eslint/parser');\n const pluginMod = await import('@typescript-eslint/eslint-plugin');\n\n const parser = (parserMod as any).default ?? parserMod;\n const plugin = (pluginMod as any).default ?? pluginMod;\n\n const recommended = (plugin.configs?.['flat/recommended'] ?? []) as TypedFlatConfigItem[];\n\n return [\n {\n name: 'qstanay/typescript',\n files: [...TYPESCRIPT_FILES],\n languageOptions: {\n parser,\n parserOptions: {\n sourceType: 'module',\n ecmaVersion: 'latest',\n extraFileExtensions: ['.vue'],\n },\n },\n plugins: {\n '@typescript-eslint': plugin,\n },\n rules: collectRules(recommended),\n },\n ];\n}\n","import { VUE_FILES } from '../utils';\nimport { vueRules } from './vue-rules';\n\nimport type { TypedFlatConfigItem } from '../types';\n\n/**\n * Vue layer based on the official flat recommended preset.\n * Must spread the full array — it includes setup, processor, and rule packs.\n */\nexport async function vue(): Promise<TypedFlatConfigItem[]> {\n const vuePluginMod = await import('eslint-plugin-vue');\n const globalsMod = await import('globals');\n\n const vuePlugin = (vuePluginMod as any).default ?? vuePluginMod;\n const globals = (globalsMod as any).default ?? globalsMod;\n\n const recommended = (vuePlugin.configs?.['flat/recommended'] ?? []) as TypedFlatConfigItem[];\n\n return [\n ...recommended,\n {\n name: 'qstanay/vue/rules',\n files: [...VUE_FILES],\n languageOptions: {\n globals: {\n ...globals.browser,\n },\n parserOptions: {\n // Keep vue-eslint-parser as the root parser (from recommended),\n // and parse <script lang=\"ts\"> with the TS parser.\n parser: {\n ts: '@typescript-eslint/parser',\n js: 'espree',\n },\n ecmaVersion: 'latest',\n sourceType: 'module',\n extraFileExtensions: ['.vue'],\n },\n },\n rules: {\n ...vueRules(),\n },\n },\n ];\n}\n","import { FlatConfigComposer } from 'eslint-flat-config-utils';\n\nimport { ignores } from './configs/ignores';\nimport { imports } from './configs/imports';\nimport { javascript as javascriptConfig } from './configs/javascript';\nimport { nuxt as nuxtConfig } from './configs/nuxt';\nimport { sharedRules } from './configs/shared-rules';\nimport { stylistic as stylisticConfig } from './configs/stylistic';\nimport { typescript as typescriptConfig } from './configs/typescript';\nimport { vue as vueConfig } from './configs/vue';\nimport { has, resolveEnabled, resolveStylisticOptions, SOURCE_FILES } from './utils';\n\nimport type { Awaitable, OptionsConfig, TypedFlatConfigItem } from './types';\n\nexport { nuxt } from './nuxt';\nexport * from './types';\n\nexport function defineConfig(\n options: OptionsConfig = {},\n ...userConfigs: (Awaitable<TypedFlatConfigItem | TypedFlatConfigItem[]>)[]\n) {\n const enableTs = resolveEnabled(options.typescript, has('typescript'));\n const enableVue = resolveEnabled(options.vue, has('vue') || has('nuxt'));\n const enableNuxt = resolveEnabled(options.nuxt, has('nuxt'));\n const stylisticOptions = resolveStylisticOptions(options.stylistic);\n\n const configs: (Awaitable<TypedFlatConfigItem[]>)[] = [];\n\n configs.push(Promise.resolve(ignores(options.ignores)));\n configs.push(javascriptConfig());\n\n if (enableTs) {\n configs.push(typescriptConfig());\n }\n\n configs.push(imports());\n\n if (stylisticOptions) {\n configs.push(stylisticConfig(stylisticOptions));\n }\n\n if (enableVue) {\n configs.push(vueConfig());\n }\n\n if (enableNuxt) {\n configs.push(nuxtConfig());\n }\n\n configs.push(Promise.resolve([\n {\n name: 'qstanay/shared-rules',\n files: [...SOURCE_FILES],\n rules: sharedRules({\n typescript: enableTs,\n strict: options.strict,\n }),\n },\n ]));\n\n if (options.overrides) {\n // Trailing block so project overrides win over shared/vue/ts packs.\n configs.push(Promise.resolve([\n {\n name: 'qstanay/overrides',\n files: [...SOURCE_FILES],\n rules: options.overrides,\n },\n ]));\n }\n\n const composer = new FlatConfigComposer<TypedFlatConfigItem>();\n composer.append(...configs, ...userConfigs as any);\n return composer;\n}\n"],"mappings":"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"}
@@ -21,6 +21,11 @@ interface OptionsConfig {
21
21
  * Enable TypeScript rules when `typescript` is installed unless explicitly set.
22
22
  */
23
23
  typescript?: boolean;
24
+ /**
25
+ * Enable stricter opinionated TypeScript rules (e.g. `no-magic-numbers`).
26
+ * Off by default to keep app/UI code quiet.
27
+ */
28
+ strict?: boolean;
24
29
  stylistic?: boolean | StylisticOptions;
25
30
  /**
26
31
  * Extra ignores appended to defaults.
@@ -35,9 +40,24 @@ interface OptionsConfig {
35
40
  //#region src/nuxt.d.ts
36
41
  interface NuxtPresetOptions {
37
42
  stylistic?: boolean | StylisticOptions;
38
- overrides?: Record<string, unknown>;
43
+ /**
44
+ * Enable stricter opinionated TypeScript rules (e.g. `no-magic-numbers`).
45
+ */
46
+ strict?: boolean;
47
+ overrides?: Linter.RulesRecord;
48
+ /**
49
+ * Extra ignores appended to defaults / `.gitignore`.
50
+ */
51
+ ignores?: string[];
39
52
  }
53
+ /**
54
+ * Opinionated layer for Nuxt apps.
55
+ *
56
+ * Intended to be used with `@nuxt/eslint` + `withNuxt()`:
57
+ * Nuxt already provides TypeScript/Vue/import plugins, so this preset
58
+ * only adds stylistic formatting and shared opinionated rules.
59
+ */
40
60
  declare function nuxt(options?: NuxtPresetOptions): Promise<TypedFlatConfigItem[]>[];
41
61
  //#endregion
42
62
  export { StylisticOptions as a, OptionsConfig as i, nuxt as n, TypedFlatConfigItem as o, Awaitable as r, NuxtPresetOptions as t };
43
- //# sourceMappingURL=nuxt-CehpYBa3.d.mts.map
63
+ //# sourceMappingURL=nuxt-B4vvMBlj.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nuxt-B4vvMBlj.d.mts","names":[],"sources":["../src/types.ts","../src/nuxt.ts"],"mappings":";;KAEY,UAAU,KAAK,IAAI,QAAQ;KAE3B,sBAAsB,OAAO;UAExB;EACf;EACA;EACA;EACA;;UAGe;;;;EAIf;;;;EAIA;;;;EAIA;;;;;EAKA;EACA,sBAAsB;;;;EAItB;;;;EAIA,YAAY,OAAO;;;;UC9BJ;EACf,sBAAsB;;;;EAItB;EACA,YAAY,OAAO;;;;EAInB;;;;;;;;;iBAUc,KAAK,UAAS,oBAAsB,QAAA"}
@@ -0,0 +1,177 @@
1
+ import gitignore from "eslint-config-flat-gitignore";
2
+ import { isPackageExists } from "local-pkg";
3
+ //#region src/configs/ignores.ts
4
+ function ignores(extraIgnores = []) {
5
+ return [gitignore({ strict: false }), {
6
+ name: "qstanay/ignores",
7
+ ignores: [
8
+ "**/node_modules/**",
9
+ "**/dist/**",
10
+ "**/.output/**",
11
+ "**/.nuxt/**",
12
+ "**/.nitro/**",
13
+ "**/coverage/**",
14
+ ...extraIgnores
15
+ ]
16
+ }];
17
+ }
18
+ //#endregion
19
+ //#region src/configs/shared-rules.ts
20
+ function javascriptRules() {
21
+ return {
22
+ "no-console": ["error", { allow: ["warn", "error"] }],
23
+ "no-debugger": "error",
24
+ "eqeqeq": ["error", "always"],
25
+ "object-shorthand": ["error", "always"],
26
+ "prefer-template": "error",
27
+ "curly": ["error", "all"],
28
+ "arrow-body-style": ["error", "as-needed"]
29
+ };
30
+ }
31
+ function typescriptRules(options = {}) {
32
+ const rules = {
33
+ "no-unused-vars": "off",
34
+ "no-undef": "off",
35
+ "@typescript-eslint/no-unused-vars": ["error", {
36
+ argsIgnorePattern: "^_",
37
+ varsIgnorePattern: "^_",
38
+ caughtErrorsIgnorePattern: "^_",
39
+ destructuredArrayIgnorePattern: "^_"
40
+ }],
41
+ "@typescript-eslint/consistent-type-imports": ["error", {
42
+ prefer: "type-imports",
43
+ disallowTypeAnnotations: false
44
+ }],
45
+ "@typescript-eslint/no-explicit-any": "warn",
46
+ "@typescript-eslint/no-non-null-assertion": "error",
47
+ "@typescript-eslint/no-empty-function": ["error", { allow: ["arrowFunctions"] }]
48
+ };
49
+ if (options.strict) rules["@typescript-eslint/no-magic-numbers"] = ["warn", {
50
+ ignore: [
51
+ -1,
52
+ 0,
53
+ 1,
54
+ 2,
55
+ 1e3
56
+ ],
57
+ ignoreEnums: true,
58
+ ignoreArrayIndexes: true,
59
+ ignoreDefaultValues: true,
60
+ ignoreClassFieldInitialValues: true,
61
+ ignoreReadonlyClassProperties: true
62
+ }];
63
+ return rules;
64
+ }
65
+ /**
66
+ * Shared opinionated rules.
67
+ * TypeScript rules are included only when `typescript` is true,
68
+ * so JS-only projects do not reference a missing plugin.
69
+ */
70
+ function sharedRules(options = {}) {
71
+ return {
72
+ ...javascriptRules(),
73
+ ...options.typescript ? typescriptRules({ strict: options.strict }) : {}
74
+ };
75
+ }
76
+ //#endregion
77
+ //#region src/configs/stylistic.ts
78
+ async function loadStylistic() {
79
+ const mod = await import("@stylistic/eslint-plugin");
80
+ return mod.default ?? mod;
81
+ }
82
+ async function stylistic(options = {}) {
83
+ const { indent = 2, quotes = "single", semi = true, maxLen = 100 } = options;
84
+ const plugin = await loadStylistic();
85
+ const config = plugin.configs.customize({
86
+ indent,
87
+ quotes,
88
+ semi,
89
+ jsx: false,
90
+ pluginName: "style"
91
+ });
92
+ return [{
93
+ name: "qstanay/stylistic",
94
+ plugins: { style: plugin },
95
+ rules: {
96
+ ...config.rules ?? {},
97
+ "style/max-len": ["warn", {
98
+ code: maxLen,
99
+ ignoreUrls: true,
100
+ ignoreStrings: true,
101
+ ignoreTemplateLiterals: true,
102
+ ignoreComments: true,
103
+ ignoreTrailingComments: true,
104
+ ignoreRegExpLiterals: true
105
+ }]
106
+ }
107
+ }];
108
+ }
109
+ //#endregion
110
+ //#region src/utils.ts
111
+ function resolveEnabled(explicit, detected) {
112
+ return explicit ?? detected;
113
+ }
114
+ function has(pkg) {
115
+ return isPackageExists(pkg);
116
+ }
117
+ function resolveStylisticOptions(stylistic) {
118
+ if (stylistic === false) return false;
119
+ if (typeof stylistic === "object") return stylistic;
120
+ return {};
121
+ }
122
+ const SOURCE_FILES = ["**/*.{js,jsx,ts,tsx,cts,mts,vue}"];
123
+ const TYPESCRIPT_FILES = ["**/*.{ts,tsx,cts,mts}", "**/*.vue"];
124
+ const VUE_FILES = ["**/*.vue"];
125
+ //#endregion
126
+ //#region src/configs/vue-rules.ts
127
+ function vueRules() {
128
+ return {
129
+ "vue/html-self-closing": ["error", {
130
+ html: {
131
+ void: "always",
132
+ normal: "always",
133
+ component: "always"
134
+ },
135
+ svg: "always",
136
+ math: "always"
137
+ }],
138
+ "vue/attributes-order": "error",
139
+ "vue/padding-line-between-tags": "error"
140
+ };
141
+ }
142
+ //#endregion
143
+ //#region src/nuxt.ts
144
+ /**
145
+ * Opinionated layer for Nuxt apps.
146
+ *
147
+ * Intended to be used with `@nuxt/eslint` + `withNuxt()`:
148
+ * Nuxt already provides TypeScript/Vue/import plugins, so this preset
149
+ * only adds stylistic formatting and shared opinionated rules.
150
+ */
151
+ function nuxt(options = {}) {
152
+ const stylisticOptions = resolveStylisticOptions(options.stylistic);
153
+ const configs = [Promise.resolve(ignores(options.ignores))];
154
+ if (stylisticOptions) configs.push(stylistic(stylisticOptions));
155
+ configs.push(Promise.resolve([{
156
+ name: "qstanay/nuxt/shared-rules",
157
+ files: [...SOURCE_FILES],
158
+ rules: sharedRules({
159
+ typescript: true,
160
+ strict: options.strict
161
+ })
162
+ }, {
163
+ name: "qstanay/nuxt/vue-rules",
164
+ files: [...VUE_FILES],
165
+ rules: { ...vueRules() }
166
+ }]));
167
+ if (options.overrides) configs.push(Promise.resolve([{
168
+ name: "qstanay/nuxt/overrides",
169
+ files: [...SOURCE_FILES],
170
+ rules: options.overrides
171
+ }]));
172
+ return configs;
173
+ }
174
+ //#endregion
175
+ export { VUE_FILES as a, resolveStylisticOptions as c, ignores as d, TYPESCRIPT_FILES as i, stylistic as l, vueRules as n, has as o, SOURCE_FILES as r, resolveEnabled as s, nuxt as t, sharedRules as u };
176
+
177
+ //# sourceMappingURL=nuxt-B6cDasrO.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nuxt-B6cDasrO.mjs","names":["stylisticConfig"],"sources":["../src/configs/ignores.ts","../src/configs/shared-rules.ts","../src/configs/stylistic.ts","../src/utils.ts","../src/configs/vue-rules.ts","../src/nuxt.ts"],"sourcesContent":["import gitignore from 'eslint-config-flat-gitignore';\n\nimport type { TypedFlatConfigItem } from '../types';\n\nexport function ignores(extraIgnores: string[] = []): TypedFlatConfigItem[] {\n return [\n // Prefer project .gitignore when present; do not fail if missing.\n gitignore({ strict: false }),\n {\n name: 'qstanay/ignores',\n ignores: [\n '**/node_modules/**',\n '**/dist/**',\n '**/.output/**',\n '**/.nuxt/**',\n '**/.nitro/**',\n '**/coverage/**',\n ...extraIgnores,\n ],\n },\n ];\n}\n","import type { Linter } from 'eslint';\n\nexport function javascriptRules(): Linter.RulesRecord {\n return {\n 'no-console': ['error', { allow: ['warn', 'error'] }],\n 'no-debugger': 'error',\n 'eqeqeq': ['error', 'always'],\n 'object-shorthand': ['error', 'always'],\n 'prefer-template': 'error',\n 'curly': ['error', 'all'],\n 'arrow-body-style': ['error', 'as-needed'],\n };\n}\n\nexport function typescriptRules(options: { strict?: boolean } = {}): Linter.RulesRecord {\n const rules: Linter.RulesRecord = {\n // Disable base rules that conflict with TypeScript-aware variants.\n 'no-unused-vars': 'off',\n 'no-undef': 'off',\n\n '@typescript-eslint/no-unused-vars': [\n 'error',\n {\n argsIgnorePattern: '^_',\n varsIgnorePattern: '^_',\n caughtErrorsIgnorePattern: '^_',\n destructuredArrayIgnorePattern: '^_',\n },\n ],\n '@typescript-eslint/consistent-type-imports': [\n 'error',\n { prefer: 'type-imports', disallowTypeAnnotations: false },\n ],\n '@typescript-eslint/no-explicit-any': 'warn',\n '@typescript-eslint/no-non-null-assertion': 'error',\n '@typescript-eslint/no-empty-function': ['error', { allow: ['arrowFunctions'] }],\n };\n\n if (options.strict) {\n rules['@typescript-eslint/no-magic-numbers'] = [\n 'warn',\n {\n ignore: [-1, 0, 1, 2, 1000],\n ignoreEnums: true,\n ignoreArrayIndexes: true,\n ignoreDefaultValues: true,\n ignoreClassFieldInitialValues: true,\n ignoreReadonlyClassProperties: true,\n },\n ];\n }\n\n return rules;\n}\n\n/**\n * Shared opinionated rules.\n * TypeScript rules are included only when `typescript` is true,\n * so JS-only projects do not reference a missing plugin.\n */\nexport function sharedRules(options: {\n typescript?: boolean;\n strict?: boolean;\n} = {}): Linter.RulesRecord {\n return {\n ...javascriptRules(),\n ...(options.typescript\n ? typescriptRules({ strict: options.strict })\n : {}),\n };\n}\n","import type { TypedFlatConfigItem, StylisticOptions } from '../types';\n\nasync function loadStylistic() {\n const mod = await import('@stylistic/eslint-plugin');\n return mod.default ?? mod;\n}\n\nexport async function stylistic(\n options: StylisticOptions = {},\n): Promise<TypedFlatConfigItem[]> {\n const {\n indent = 2,\n quotes = 'single',\n semi = true,\n maxLen = 100,\n } = options;\n\n const plugin = await loadStylistic();\n\n // `customize()` gives us a coherent bundle of stylistic rules.\n // Plugin name is fixed to `style` for stable rule IDs.\n const config = plugin.configs.customize({\n indent,\n quotes,\n semi,\n jsx: false,\n pluginName: 'style',\n }) as TypedFlatConfigItem;\n\n return [\n {\n name: 'qstanay/stylistic',\n plugins: {\n style: plugin,\n },\n rules: {\n ...(config.rules ?? {}),\n // Keep max line length aligned across all projects.\n 'style/max-len': [\n 'warn',\n {\n code: maxLen,\n ignoreUrls: true,\n ignoreStrings: true,\n ignoreTemplateLiterals: true,\n ignoreComments: true,\n ignoreTrailingComments: true,\n ignoreRegExpLiterals: true,\n },\n ],\n },\n },\n ];\n}\n","import { isPackageExists } from 'local-pkg';\n\nimport type { StylisticOptions } from './types';\n\nexport function resolveEnabled(explicit: boolean | undefined, detected: boolean) {\n return explicit ?? detected;\n}\n\nexport function has(pkg: string) {\n return isPackageExists(pkg);\n}\n\nexport function resolveStylisticOptions(\n stylistic: boolean | StylisticOptions | undefined,\n): false | StylisticOptions {\n if (stylistic === false) {\n return false;\n }\n\n if (typeof stylistic === 'object') {\n return stylistic;\n }\n\n return {};\n}\n\nexport const SOURCE_FILES = ['**/*.{js,jsx,ts,tsx,cts,mts,vue}'] as const;\nexport const TYPESCRIPT_FILES = ['**/*.{ts,tsx,cts,mts}', '**/*.vue'] as const;\nexport const VUE_FILES = ['**/*.vue'] as const;\n","import type { Linter } from 'eslint';\n\nexport function vueRules(): Linter.RulesRecord {\n return {\n 'vue/html-self-closing': [\n 'error',\n {\n html: {\n void: 'always',\n normal: 'always',\n component: 'always',\n },\n svg: 'always',\n math: 'always',\n },\n ],\n 'vue/attributes-order': 'error',\n 'vue/padding-line-between-tags': 'error',\n };\n}\n","import { ignores } from './configs/ignores';\nimport { sharedRules } from './configs/shared-rules';\nimport { stylistic as stylisticConfig } from './configs/stylistic';\nimport { vueRules } from './configs/vue-rules';\nimport { resolveStylisticOptions, SOURCE_FILES, VUE_FILES } from './utils';\n\nimport type { StylisticOptions, TypedFlatConfigItem } from './types';\nimport type { Linter } from 'eslint';\n\nexport interface NuxtPresetOptions {\n stylistic?: boolean | StylisticOptions;\n /**\n * Enable stricter opinionated TypeScript rules (e.g. `no-magic-numbers`).\n */\n strict?: boolean;\n overrides?: Linter.RulesRecord;\n /**\n * Extra ignores appended to defaults / `.gitignore`.\n */\n ignores?: string[];\n}\n\n/**\n * Opinionated layer for Nuxt apps.\n *\n * Intended to be used with `@nuxt/eslint` + `withNuxt()`:\n * Nuxt already provides TypeScript/Vue/import plugins, so this preset\n * only adds stylistic formatting and shared opinionated rules.\n */\nexport function nuxt(options: NuxtPresetOptions = {}) {\n const stylisticOptions = resolveStylisticOptions(options.stylistic);\n const configs: Promise<TypedFlatConfigItem[]>[] = [\n Promise.resolve(ignores(options.ignores)),\n ];\n\n if (stylisticOptions) {\n configs.push(stylisticConfig(stylisticOptions));\n }\n\n configs.push(Promise.resolve([\n {\n name: 'qstanay/nuxt/shared-rules',\n files: [...SOURCE_FILES],\n // Host (@nuxt/eslint) registers @typescript-eslint; include TS rules.\n rules: sharedRules({\n typescript: true,\n strict: options.strict,\n }),\n },\n {\n name: 'qstanay/nuxt/vue-rules',\n files: [...VUE_FILES],\n rules: {\n ...vueRules(),\n },\n },\n ]));\n\n if (options.overrides) {\n // Dedicated trailing block so overrides always win over vue/shared rules.\n configs.push(Promise.resolve([\n {\n name: 'qstanay/nuxt/overrides',\n files: [...SOURCE_FILES],\n rules: options.overrides,\n },\n ]));\n }\n\n return configs;\n}\n"],"mappings":"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"}
package/dist/nuxt.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { n as nuxt, t as NuxtPresetOptions } from "./nuxt-CehpYBa3.mjs";
1
+ import { n as nuxt, t as NuxtPresetOptions } from "./nuxt-B4vvMBlj.mjs";
2
2
  export { NuxtPresetOptions, nuxt };
package/dist/nuxt.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { t as nuxt } from "./nuxt-Cz6LtoZ_.mjs";
1
+ import { t as nuxt } from "./nuxt-B6cDasrO.mjs";
2
2
  export { nuxt };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qstanay/eslint-config",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Opinionated ESLint flat config for Nuxt, Vue and TypeScript",
5
5
  "type": "module",
6
6
  "exports": {
@@ -15,13 +15,23 @@
15
15
  "lint": "eslint .",
16
16
  "lint:fix": "eslint . --fix",
17
17
  "test": "vitest",
18
- "typecheck": "tsc --noEmit"
18
+ "typecheck": "tsc --noEmit",
19
+ "prepublishOnly": "npm run build"
19
20
  },
20
21
  "repository": {
21
22
  "type": "git",
22
23
  "url": "git+https://github.com/qstanay/eslint-config.git"
23
24
  },
24
- "keywords": [],
25
+ "keywords": [
26
+ "eslint",
27
+ "eslint-config",
28
+ "eslintconfig",
29
+ "flat-config",
30
+ "nuxt",
31
+ "vue",
32
+ "typescript",
33
+ "stylistic"
34
+ ],
25
35
  "author": "",
26
36
  "license": "MIT",
27
37
  "bugs": {
@@ -29,7 +39,8 @@
29
39
  },
30
40
  "homepage": "https://github.com/qstanay/eslint-config#readme",
31
41
  "files": [
32
- "dist"
42
+ "dist",
43
+ "CHANGELOG.md"
33
44
  ],
34
45
  "peerDependencies": {
35
46
  "eslint": "^9.0.0 || ^10.0.0"
@@ -40,6 +51,7 @@
40
51
  }
41
52
  },
42
53
  "dependencies": {
54
+ "@eslint/js": "^10.0.1",
43
55
  "@nuxt/eslint-plugin": "^1.16.0",
44
56
  "@stylistic/eslint-plugin": "^5.10.0",
45
57
  "@typescript-eslint/eslint-plugin": "^8.0.0",
@@ -48,7 +60,6 @@
48
60
  "eslint-flat-config-utils": "^3.2.0",
49
61
  "eslint-plugin-import-x": "^4.0.0",
50
62
  "eslint-plugin-vue": "^10.0.0",
51
- "eslint-processor-vue-blocks": "^2.0.0",
52
63
  "globals": "^17.0.0",
53
64
  "local-pkg": "^1.2.0",
54
65
  "vue-eslint-parser": "^10.0.0"
@@ -56,7 +67,6 @@
56
67
  "devDependencies": {
57
68
  "@types/node": "^26.1.1",
58
69
  "eslint": "^10.7.0",
59
- "jiti": "^2.5.1",
60
70
  "tsdown": "^0.22.7",
61
71
  "typescript": "^6.0.3",
62
72
  "vitest": "^4.1.10"
@@ -1 +0,0 @@
1
- {"version":3,"file":"nuxt-CehpYBa3.d.mts","names":[],"sources":["../src/types.ts","../src/nuxt.ts"],"mappings":";;KAEY,UAAU,KAAK,IAAI,QAAQ;KAE3B,sBAAsB,OAAO;UAExB;EACf;EACA;EACA;EACA;;UAGe;;;;EAIf;;;;EAIA;;;;EAIA;EACA,sBAAsB;;;;EAItB;;;;EAIA,YAAY,OAAO;;;;UCzBJ;EACf,sBAAsB;EACtB,YAAY;;iBAGE,KAAK,UAAS,oBAAsB,QAAA"}
@@ -1,178 +0,0 @@
1
- //#region src/configs/shared-rules.ts
2
- function sharedRules() {
3
- return {
4
- "no-console": ["error", { allow: ["warn", "error"] }],
5
- "no-debugger": "error",
6
- "eqeqeq": ["error", "always"],
7
- "object-shorthand": ["error", "always"],
8
- "prefer-template": "error",
9
- "curly": ["error", "all"],
10
- "arrow-body-style": ["error", "as-needed"],
11
- "@typescript-eslint/no-unused-vars": ["error", {
12
- argsIgnorePattern: "^_",
13
- varsIgnorePattern: "^_",
14
- caughtErrorsIgnorePattern: "^_",
15
- destructuredArrayIgnorePattern: "^_"
16
- }],
17
- "@typescript-eslint/consistent-type-imports": ["error", {
18
- prefer: "type-imports",
19
- disallowTypeAnnotations: false
20
- }],
21
- "@typescript-eslint/no-explicit-any": "warn",
22
- "@typescript-eslint/no-non-null-assertion": "error",
23
- "@typescript-eslint/no-empty-function": ["error", { allow: ["arrowFunctions"] }],
24
- "@typescript-eslint/no-magic-numbers": ["warn", {
25
- ignore: [
26
- -1,
27
- 0,
28
- 1,
29
- 2,
30
- 1e3
31
- ],
32
- ignoreEnums: true,
33
- ignoreArrayIndexes: true,
34
- ignoreDefaultValues: true,
35
- ignoreClassFieldInitialValues: true,
36
- ignoreReadonlyClassProperties: true
37
- }]
38
- };
39
- }
40
- //#endregion
41
- //#region src/configs/imports.ts
42
- async function imports() {
43
- const mod = await import("eslint-plugin-import-x");
44
- return [{
45
- name: "qstanay/imports",
46
- plugins: { import: mod.default ?? mod },
47
- rules: {
48
- "import/first": "error",
49
- "import/no-duplicates": "error",
50
- "import/no-mutable-exports": "error",
51
- "import/no-named-default": "error"
52
- }
53
- }];
54
- }
55
- //#endregion
56
- //#region src/configs/nuxt.ts
57
- async function nuxt$1() {
58
- const mod = await import("@nuxt/eslint-plugin");
59
- return [{
60
- name: "qstanay/nuxt",
61
- plugins: { nuxt: mod.default ?? mod },
62
- rules: { "nuxt/prefer-import-meta": "error" }
63
- }];
64
- }
65
- //#endregion
66
- //#region src/configs/stylistic.ts
67
- async function loadStylistic() {
68
- const mod = await import("@stylistic/eslint-plugin");
69
- return mod.default ?? mod;
70
- }
71
- async function stylistic(options = {}) {
72
- const { indent = 2, quotes = "single", semi = true, maxLen = 100 } = options;
73
- const plugin = await loadStylistic();
74
- const config = plugin.configs.customize({
75
- indent,
76
- quotes,
77
- semi,
78
- jsx: false,
79
- pluginName: "style"
80
- });
81
- return [{
82
- name: "qstanay/stylistic",
83
- plugins: { style: plugin },
84
- rules: {
85
- ...config.rules ?? {},
86
- "style/max-len": ["warn", {
87
- code: maxLen,
88
- ignoreUrls: true,
89
- ignoreStrings: true,
90
- ignoreTemplateLiterals: true,
91
- ignoreComments: true,
92
- ignoreTrailingComments: true,
93
- ignoreRegExpLiterals: true
94
- }]
95
- }
96
- }];
97
- }
98
- //#endregion
99
- //#region src/configs/typescript.ts
100
- async function typescript() {
101
- const parserMod = await import("@typescript-eslint/parser");
102
- const pluginMod = await import("@typescript-eslint/eslint-plugin");
103
- const parser = parserMod.default ?? parserMod;
104
- const plugin = pluginMod.default ?? pluginMod;
105
- return [{
106
- name: "qstanay/typescript",
107
- files: ["**/*.{ts,tsx,cts,mts,vue}"],
108
- languageOptions: {
109
- parser,
110
- parserOptions: {
111
- sourceType: "module",
112
- ecmaVersion: "latest"
113
- }
114
- },
115
- plugins: { "@typescript-eslint": plugin },
116
- rules: { ...plugin.configs?.recommended?.rules ?? {} }
117
- }];
118
- }
119
- //#endregion
120
- //#region src/configs/vue.ts
121
- async function vue() {
122
- const vuePluginMod = await import("eslint-plugin-vue");
123
- const vueParserMod = await import("vue-eslint-parser");
124
- const vuePlugin = vuePluginMod.default ?? vuePluginMod;
125
- return [{
126
- name: "qstanay/vue",
127
- files: ["**/*.vue"],
128
- languageOptions: {
129
- parser: vueParserMod.default ?? vueParserMod,
130
- parserOptions: {
131
- parser: {
132
- ts: "@typescript-eslint/parser",
133
- js: "espree"
134
- },
135
- ecmaVersion: "latest",
136
- sourceType: "module",
137
- extraFileExtensions: [".vue"]
138
- }
139
- },
140
- plugins: { vue: vuePlugin },
141
- rules: {
142
- ...vuePlugin.configs?.["flat/recommended"]?.[0]?.rules ?? {},
143
- "vue/html-self-closing": ["error", {
144
- html: {
145
- void: "always",
146
- normal: "always",
147
- component: "always"
148
- },
149
- svg: "always",
150
- math: "always"
151
- }],
152
- "vue/attributes-order": "error",
153
- "vue/padding-line-between-tags": "error"
154
- }
155
- }];
156
- }
157
- //#endregion
158
- //#region src/nuxt.ts
159
- function nuxt(options = {}) {
160
- const stylisticOptions = options.stylistic === false ? false : typeof options.stylistic === "object" ? options.stylistic : {};
161
- const configs = [
162
- typescript(),
163
- imports(),
164
- vue(),
165
- nuxt$1(),
166
- Promise.resolve([{
167
- name: "qstanay/nuxt/shared-rules",
168
- files: ["**/*.{js,jsx,ts,tsx,cts,mts,vue}"],
169
- rules: { ...sharedRules() }
170
- }])
171
- ];
172
- if (stylisticOptions) configs.unshift(stylistic(stylisticOptions));
173
- return configs;
174
- }
175
- //#endregion
176
- export { nuxt$1 as a, stylistic as i, vue as n, imports as o, typescript as r, sharedRules as s, nuxt as t };
177
-
178
- //# sourceMappingURL=nuxt-Cz6LtoZ_.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"nuxt-Cz6LtoZ_.mjs","names":["nuxt","typescriptConfig","vueConfig","nuxtConfig","stylisticConfig"],"sources":["../src/configs/shared-rules.ts","../src/configs/imports.ts","../src/configs/nuxt.ts","../src/configs/stylistic.ts","../src/configs/typescript.ts","../src/configs/vue.ts","../src/nuxt.ts"],"sourcesContent":["import type { Linter } from 'eslint';\n\nexport function sharedRules(): Linter.RulesRecord {\n return {\n // JavaScript logic\n 'no-console': ['error', { allow: ['warn', 'error'] }],\n 'no-debugger': 'error',\n 'eqeqeq': ['error', 'always'],\n 'object-shorthand': ['error', 'always'],\n 'prefer-template': 'error',\n 'curly': ['error', 'all'],\n 'arrow-body-style': ['error', 'as-needed'],\n\n // TypeScript logic\n '@typescript-eslint/no-unused-vars': [\n 'error',\n {\n argsIgnorePattern: '^_',\n varsIgnorePattern: '^_',\n caughtErrorsIgnorePattern: '^_',\n destructuredArrayIgnorePattern: '^_',\n },\n ],\n '@typescript-eslint/consistent-type-imports': [\n 'error',\n { prefer: 'type-imports', disallowTypeAnnotations: false },\n ],\n '@typescript-eslint/no-explicit-any': 'warn',\n '@typescript-eslint/no-non-null-assertion': 'error',\n '@typescript-eslint/no-empty-function': ['error', { allow: ['arrowFunctions'] }],\n '@typescript-eslint/no-magic-numbers': [\n 'warn',\n {\n ignore: [-1, 0, 1, 2, 1000],\n ignoreEnums: true,\n ignoreArrayIndexes: true,\n ignoreDefaultValues: true,\n ignoreClassFieldInitialValues: true,\n ignoreReadonlyClassProperties: true,\n },\n ],\n };\n}\n","import type { TypedFlatConfigItem } from '../types';\n\nexport async function imports(): Promise<TypedFlatConfigItem[]> {\n const mod = await import('eslint-plugin-import-x');\n const plugin = (mod as any).default ?? mod;\n\n return [\n {\n name: 'qstanay/imports',\n plugins: {\n import: plugin,\n },\n rules: {\n 'import/first': 'error',\n 'import/no-duplicates': 'error',\n 'import/no-mutable-exports': 'error',\n 'import/no-named-default': 'error',\n },\n },\n ];\n}\n","import type { TypedFlatConfigItem } from '../types';\n\nexport async function nuxt(): Promise<TypedFlatConfigItem[]> {\n const mod = await import('@nuxt/eslint-plugin');\n const plugin = (mod as any).default ?? mod;\n\n return [\n {\n name: 'qstanay/nuxt',\n plugins: {\n nuxt: plugin,\n },\n rules: {\n // keep this minimal; Nuxt base config already provides most of it\n 'nuxt/prefer-import-meta': 'error',\n },\n },\n ];\n}\n","import type { TypedFlatConfigItem, StylisticOptions } from '../types';\n\nasync function loadStylistic() {\n const mod = await import('@stylistic/eslint-plugin');\n return mod.default ?? mod;\n}\n\nexport async function stylistic(\n options: StylisticOptions = {},\n): Promise<TypedFlatConfigItem[]> {\n const {\n indent = 2,\n quotes = 'single',\n semi = true,\n maxLen = 100,\n } = options;\n\n const plugin = await loadStylistic();\n\n // `customize()` gives us a coherent bundle of stylistic rules.\n // Plugin name is fixed to `style` for stable rule IDs.\n const config = plugin.configs.customize({\n indent,\n quotes,\n semi,\n jsx: false,\n pluginName: 'style',\n }) as TypedFlatConfigItem;\n\n return [\n {\n name: 'qstanay/stylistic',\n plugins: {\n style: plugin,\n },\n rules: {\n ...(config.rules ?? {}),\n // Keep max line length aligned across all projects.\n 'style/max-len': [\n 'warn',\n {\n code: maxLen,\n ignoreUrls: true,\n ignoreStrings: true,\n ignoreTemplateLiterals: true,\n ignoreComments: true,\n ignoreTrailingComments: true,\n ignoreRegExpLiterals: true,\n },\n ],\n },\n },\n ];\n}\n","import type { TypedFlatConfigItem } from '../types';\n\nexport async function typescript(): Promise<TypedFlatConfigItem[]> {\n const parserMod = await import('@typescript-eslint/parser');\n const pluginMod = await import('@typescript-eslint/eslint-plugin');\n\n const parser = (parserMod as any).default ?? parserMod;\n const plugin = (pluginMod as any).default ?? pluginMod;\n\n return [\n {\n name: 'qstanay/typescript',\n files: ['**/*.{ts,tsx,cts,mts,vue}'],\n languageOptions: {\n parser,\n parserOptions: {\n sourceType: 'module',\n ecmaVersion: 'latest',\n },\n },\n plugins: {\n '@typescript-eslint': plugin,\n },\n rules: {\n ...(plugin.configs?.recommended?.rules ?? {}),\n },\n },\n ];\n}\n","import type { TypedFlatConfigItem } from '../types';\n\nexport async function vue(): Promise<TypedFlatConfigItem[]> {\n const vuePluginMod = await import('eslint-plugin-vue');\n const vueParserMod = await import('vue-eslint-parser');\n\n const vuePlugin = (vuePluginMod as any).default ?? vuePluginMod;\n const vueParser = (vueParserMod as any).default ?? vueParserMod;\n\n return [\n {\n name: 'qstanay/vue',\n files: ['**/*.vue'],\n languageOptions: {\n parser: vueParser,\n parserOptions: {\n parser: {\n ts: '@typescript-eslint/parser',\n js: 'espree',\n },\n ecmaVersion: 'latest',\n sourceType: 'module',\n extraFileExtensions: ['.vue'],\n },\n },\n plugins: {\n vue: vuePlugin,\n },\n rules: {\n ...(vuePlugin.configs?.['flat/recommended']?.[0]?.rules ?? {}),\n 'vue/html-self-closing': [\n 'error',\n {\n html: {\n void: 'always',\n normal: 'always',\n component: 'always',\n },\n svg: 'always',\n math: 'always',\n },\n ],\n 'vue/attributes-order': 'error',\n 'vue/padding-line-between-tags': 'error',\n },\n },\n ];\n}\n","import type { StylisticOptions, TypedFlatConfigItem } from './types';\n\nimport { sharedRules } from './configs/shared-rules';\nimport { imports } from './configs/imports';\nimport { nuxt as nuxtConfig } from './configs/nuxt';\nimport { stylistic as stylisticConfig } from './configs/stylistic';\nimport { typescript as typescriptConfig } from './configs/typescript';\nimport { vue as vueConfig } from './configs/vue';\n\nexport interface NuxtPresetOptions {\n stylistic?: boolean | StylisticOptions;\n overrides?: Record<string, unknown>;\n}\n\nexport function nuxt(options: NuxtPresetOptions = {}) {\n const stylisticOptions = options.stylistic === false\n ? false\n : typeof options.stylistic === 'object'\n ? options.stylistic\n : {};\n\n const configs: Promise<TypedFlatConfigItem[]>[] = [\n typescriptConfig(),\n imports(),\n vueConfig(),\n nuxtConfig(),\n Promise.resolve([\n {\n name: 'qstanay/nuxt/shared-rules',\n files: ['**/*.{js,jsx,ts,tsx,cts,mts,vue}'],\n rules: {\n ...sharedRules(),\n },\n },\n ]),\n ];\n\n if (stylisticOptions) {\n configs.unshift(stylisticConfig(stylisticOptions));\n }\n\n return configs;\n}\n"],"mappings":"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"}