@qstanay/eslint-config 1.0.1 → 1.0.3

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,64 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented in this file.
4
+
5
+ ## [1.0.3] - 2026-07-20
6
+
7
+ ### Fixed
8
+
9
+ - Do not attach the TypeScript parser to `.vue` when Vue is disabled (avoids fatal parse errors)
10
+ - Ignore `.vue` files when Vue is disabled so `eslint .` does not crash on stray SFCs
11
+ - Apply shared rules and overrides to `.mjs` / `.cjs` (not only `.js`)
12
+ - Declare Node + ES2022 globals in the JavaScript layer so `no-undef` no longer false-positives on `console` / `process`
13
+ - Resolve TypeScript types for `@qstanay/eslint-config/nuxt` via package `exports`
14
+ - Declare `typescript` as an optional peer dependency (matches existing `peerDependenciesMeta`)
15
+ - Use an explicit options array for `vue/padding-line-between-tags`
16
+
17
+ ### Changed
18
+
19
+ - Fill `author` and `engines.node` (`>=18`) in `package.json`
20
+
21
+ ## [1.0.2] - 2026-07-18
22
+
23
+ ### Added
24
+
25
+ - `@eslint/js` recommended as the JavaScript baseline in `defineConfig()`
26
+ - Autofixable `import/order` (grouped + alphabetized)
27
+ - `strict` option for `defineConfig()` / `nuxt()` to opt into stricter TypeScript rules (e.g. `no-magic-numbers`)
28
+ - `ignores` option on the Nuxt preset (`nuxt({ ignores: [...] })`)
29
+ - npm `keywords` for discoverability
30
+
31
+ ### Changed
32
+
33
+ - `no-magic-numbers` is no longer enabled by default (use `strict: true`)
34
+ - When TypeScript is enabled, turn off conflicting base rules (`no-unused-vars`, `no-undef`)
35
+
36
+ ## [1.0.1] - 2026-07-18
37
+
38
+ ### Fixed
39
+
40
+ - Correctly apply the full `eslint-plugin-vue` `flat/recommended` preset (previously only `[0].rules` was used, which contained no rules)
41
+ - Include TypeScript shared rules only when TypeScript is enabled (JS-only projects no longer crash on a missing `@typescript-eslint` plugin)
42
+ - Apply `overrides` in a trailing config block so they win over shared/Vue rules in both `defineConfig()` and `nuxt()`
43
+
44
+ ### Added
45
+
46
+ - Honor project `.gitignore` in ignores and add `coverage` to default ignores
47
+ - Browser `globals` for Vue; load TypeScript rules from `flat/recommended`
48
+ - `prepublishOnly` build hook
49
+ - Expanded README for humans and agents
50
+ - Tests for JS-only setups, Vue recommended rules, and overrides behavior
51
+
52
+ ### Removed
53
+
54
+ - Unused dependency `eslint-processor-vue-blocks`
55
+
56
+ ## [1.0.0] - 2026-07-13
57
+
58
+ ### Added
59
+
60
+ - Initial release of `@qstanay/eslint-config`
61
+ - `defineConfig()` for Vue and TypeScript projects
62
+ - `@qstanay/eslint-config/nuxt` layer for use with `@nuxt/eslint` + `withNuxt()`
63
+ - Stylistic formatting via `@stylistic` (`eslint --fix`)
64
+ - Shared opinionated JS/TS rules, import hygiene, and Vue opinionated extras
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Denis Lapshin
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -14,6 +14,18 @@ Formatting is handled by ESLint via **@stylistic** (`eslint --fix`). Do **not**
14
14
 
15
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`.
16
16
 
17
+ ## When to use this
18
+
19
+ Use this preset when you want a **small, Nuxt/Vue/TypeScript-focused** flat config with lint + format in one toolchain (`eslint --fix` via `@stylistic`), without Prettier.
20
+
21
+ How it differs from common alternatives:
22
+
23
+ - **vs `@antfu/eslint-config`** — narrower scope. No JSON/YAML/Markdown/CSS formatters, no React/Next/Svelte/Astro stack. Keeps standard rule prefixes (`@typescript-eslint/*`, `import/*`) and defaults to semicolons + single quotes + 2-space indent. Includes a dedicated Nuxt layer for `@nuxt/eslint` + `withNuxt()`.
24
+ - **vs Prettier (+ eslint-config-prettier)** — formatting lives in ESLint/Stylistic. Do not run both unless you set `stylistic: false`.
25
+ - **vs using `@nuxt/eslint` alone** — Nuxt already gives project-aware Vue/TS setup; this package adds opinionated shared rules and stylistic formatting on top.
26
+
27
+ If you need a wide multi-framework “batteries included” preset, prefer something like `@antfu/eslint-config`. If you mainly ship Nuxt/Vue/TS apps and want a predictable thin layer, use this.
28
+
17
29
  ## Requirements
18
30
 
19
31
  - Node.js 18+
@@ -125,6 +137,7 @@ Main entry for Vue / TypeScript projects.
125
137
  | `vue` | `boolean` | auto (`vue` or `nuxt` installed) | Enable Vue rules |
126
138
  | `typescript` | `boolean` | auto (`typescript` installed) | Enable TypeScript rules |
127
139
  | `nuxt` | `boolean` | auto (`nuxt` installed) | Enable Nuxt plugin rule(s). Prefer `/nuxt` for Nuxt apps |
140
+ | `strict` | `boolean` | `false` | Stricter TS rules (e.g. `no-magic-numbers`) |
128
141
  | `stylistic` | `false \| object` | enabled | Formatting rules (see below) |
129
142
  | `overrides` | `Linter.RulesRecord` | `{}` | Custom rules merged last over shared rules |
130
143
  | `ignores` | `string[]` | `[]` | Extra ignore globs |
@@ -150,7 +163,9 @@ Layer for Nuxt apps used with `withNuxt(...nuxt())`.
150
163
  | Option | Type | Default | Description |
151
164
  |---|---|---|---|
152
165
  | `stylistic` | `false \| object` | enabled | Formatting rules (see below) |
166
+ | `strict` | `boolean` | `false` | Stricter TS rules (e.g. `no-magic-numbers`) |
153
167
  | `overrides` | `Linter.RulesRecord` | `{}` | Custom rules merged last over shared rules |
168
+ | `ignores` | `string[]` | `[]` | Extra ignore globs (plus defaults / `.gitignore`) |
154
169
 
155
170
  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.
156
171
 
@@ -205,9 +220,12 @@ Built-in ignores cover `node_modules`, `dist`, `.output`, `.nuxt`, `.nitro`, `co
205
220
  defineConfig({
206
221
  ignores: ['**/fixtures/**'],
207
222
  })
208
- ```
209
223
 
210
- `ignores` is only on `defineConfig`, not on the Nuxt preset (use Nuxt / ESLint ignore mechanisms there if needed).
224
+ // Nuxt:
225
+ nuxt({
226
+ ignores: ['**/fixtures/**'],
227
+ })
228
+ ```
211
229
 
212
230
  ## Prettier
213
231
 
@@ -263,11 +281,13 @@ Disable Prettier for the same file types (or uninstall / disable the Prettier ex
263
281
 
264
282
  ## What this preset enforces (high level)
265
283
 
266
- - Shared JS rules always; TypeScript opinionated rules only when TypeScript is enabled (so JS-only projects stay valid)
267
- - Official `eslint-plugin-vue` `flat/recommended` when Vue is enabled, plus a small opinionated Vue layer (self-closing tags, attribute order, padding between tags)
284
+ - `@eslint/js` recommended as the JS baseline in `defineConfig()`
285
+ - Shared opinionated JS rules always; TypeScript opinionated rules only when TypeScript is enabled
286
+ - Official `eslint-plugin-vue` `flat/recommended` when Vue is enabled, plus a small opinionated Vue layer
268
287
  - Stylistic formatting via `@stylistic` (rule namespace: `style/*`)
269
- - Import hygiene via `eslint-plugin-import-x` in `defineConfig` (Nuxt relies on `@nuxt/eslint` for its own import/TS/Vue stack)
288
+ - Import hygiene + autofixable `import/order` via `eslint-plugin-import-x` in `defineConfig` (Nuxt relies on `@nuxt/eslint` for its own import/TS/Vue stack)
270
289
  - `overrides` are applied in a trailing config block so they win over shared/Vue rules
290
+ - Optional `strict: true` for noisier TypeScript checks like `no-magic-numbers`
271
291
 
272
292
  ## Agent / setup checklist
273
293
 
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-D-E7z44c.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":";;;iBAuBgB,aACd,UAAS,kBACN,cAAc,UAAU,sBAAsB,4BAAyB,mBAAA"}
package/dist/index.mjs CHANGED
@@ -1,22 +1,5 @@
1
- import { a as SOURCE_FILES, c as has, i as sharedRules, l as resolveEnabled, n as vueRules, o as TYPESCRIPT_FILES, r as stylistic, s as VUE_FILES, t as nuxt, u as resolveStylisticOptions } from "./nuxt-HGf9trGQ.mjs";
1
+ import { a as resolveEnabled, c as typescriptFiles, d as ignores, i as has, l as stylistic, n as vueRules, o as resolveStylisticOptions, r as VUE_FILES, s as sourceFiles, t as nuxt, u as sharedRules } from "./nuxt-jcrXAC4G.mjs";
2
2
  import { FlatConfigComposer } from "eslint-flat-config-utils";
3
- import gitignore from "eslint-config-flat-gitignore";
4
- //#region src/configs/ignores.ts
5
- function ignores(extraIgnores = []) {
6
- return [gitignore({ strict: false }), {
7
- name: "qstanay/ignores",
8
- ignores: [
9
- "**/node_modules/**",
10
- "**/dist/**",
11
- "**/.output/**",
12
- "**/.nuxt/**",
13
- "**/.nitro/**",
14
- "**/coverage/**",
15
- ...extraIgnores
16
- ]
17
- }];
18
- }
19
- //#endregion
20
3
  //#region src/configs/imports.ts
21
4
  async function imports() {
22
5
  const mod = await import("eslint-plugin-import-x");
@@ -27,11 +10,51 @@ async function imports() {
27
10
  "import/first": "error",
28
11
  "import/no-duplicates": "error",
29
12
  "import/no-mutable-exports": "error",
30
- "import/no-named-default": "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
+ }]
31
33
  }
32
34
  }];
33
35
  }
34
36
  //#endregion
37
+ //#region src/configs/javascript.ts
38
+ /**
39
+ * Base JS quality rules from `@eslint/js` recommended.
40
+ * Declares Node + ES2022 globals so `no-undef` does not false-positive on
41
+ * `console`, `process`, and other built-ins.
42
+ */
43
+ async function javascript() {
44
+ const jsMod = await import("@eslint/js");
45
+ const globalsMod = await import("globals");
46
+ const js = jsMod.default ?? jsMod;
47
+ const globals = globalsMod.default ?? globalsMod;
48
+ return [{
49
+ name: "qstanay/javascript",
50
+ languageOptions: { globals: {
51
+ ...globals.es2022,
52
+ ...globals.nodeBuiltin
53
+ } },
54
+ rules: { ...js.configs?.recommended?.rules ?? {} }
55
+ }];
56
+ }
57
+ //#endregion
35
58
  //#region src/configs/nuxt.ts
36
59
  async function nuxt$1() {
37
60
  const mod = await import("@nuxt/eslint-plugin");
@@ -46,21 +69,22 @@ async function nuxt$1() {
46
69
  function collectRules(configs) {
47
70
  return Object.assign({}, ...configs.filter((config) => config.rules).map((config) => config.rules));
48
71
  }
49
- async function typescript() {
72
+ async function typescript(options = {}) {
50
73
  const parserMod = await import("@typescript-eslint/parser");
51
74
  const pluginMod = await import("@typescript-eslint/eslint-plugin");
52
75
  const parser = parserMod.default ?? parserMod;
53
76
  const plugin = pluginMod.default ?? pluginMod;
54
77
  const recommended = plugin.configs?.["flat/recommended"] ?? [];
78
+ const vueEnabled = options.vue === true;
55
79
  return [{
56
80
  name: "qstanay/typescript",
57
- files: [...TYPESCRIPT_FILES],
81
+ files: typescriptFiles(vueEnabled),
58
82
  languageOptions: {
59
83
  parser,
60
84
  parserOptions: {
61
85
  sourceType: "module",
62
86
  ecmaVersion: "latest",
63
- extraFileExtensions: [".vue"]
87
+ ...vueEnabled ? { extraFileExtensions: [".vue"] } : {}
64
88
  }
65
89
  },
66
90
  plugins: { "@typescript-eslint": plugin },
@@ -103,21 +127,26 @@ function defineConfig(options = {}, ...userConfigs) {
103
127
  const enableVue = resolveEnabled(options.vue, has("vue") || has("nuxt"));
104
128
  const enableNuxt = resolveEnabled(options.nuxt, has("nuxt"));
105
129
  const stylisticOptions = resolveStylisticOptions(options.stylistic);
130
+ const files = sourceFiles(enableVue);
106
131
  const configs = [];
107
- configs.push(Promise.resolve(ignores(options.ignores)));
108
- if (enableTs) configs.push(typescript());
132
+ configs.push(Promise.resolve(ignores([...options.ignores ?? [], ...!enableVue ? VUE_FILES : []])));
133
+ configs.push(javascript());
134
+ if (enableTs) configs.push(typescript({ vue: enableVue }));
109
135
  configs.push(imports());
110
136
  if (stylisticOptions) configs.push(stylistic(stylisticOptions));
111
137
  if (enableVue) configs.push(vue());
112
138
  if (enableNuxt) configs.push(nuxt$1());
113
139
  configs.push(Promise.resolve([{
114
140
  name: "qstanay/shared-rules",
115
- files: [...SOURCE_FILES],
116
- rules: sharedRules({ typescript: enableTs })
141
+ files,
142
+ rules: sharedRules({
143
+ typescript: enableTs,
144
+ strict: options.strict
145
+ })
117
146
  }]));
118
147
  if (options.overrides) configs.push(Promise.resolve([{
119
148
  name: "qstanay/overrides",
120
- files: [...SOURCE_FILES],
149
+ files,
121
150
  rules: options.overrides
122
151
  }]));
123
152
  const composer = new FlatConfigComposer();
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["nuxt","typescriptConfig","stylisticConfig","vueConfig","nuxtConfig"],"sources":["../src/configs/ignores.ts","../src/configs/imports.ts","../src/configs/nuxt.ts","../src/configs/typescript.ts","../src/configs/vue.ts","../src/index.ts"],"sourcesContent":["import type { TypedFlatConfigItem } from '../types';\n\nimport gitignore from 'eslint-config-flat-gitignore';\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 { 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 { Linter } from 'eslint';\n\nimport type { TypedFlatConfigItem } from '../types';\n\nimport { TYPESCRIPT_FILES } from '../utils';\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 type { TypedFlatConfigItem } from '../types';\n\nimport { VUE_FILES } from '../utils';\nimport { vueRules } from './vue-rules';\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 type { Awaitable, OptionsConfig, TypedFlatConfigItem } from './types';\n\nimport { FlatConfigComposer } from 'eslint-flat-config-utils';\nimport { has, resolveEnabled, resolveStylisticOptions, SOURCE_FILES } 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 const stylisticOptions = resolveStylisticOptions(options.stylistic);\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 files: [...SOURCE_FILES],\n rules: sharedRules({ typescript: enableTs }),\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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"}
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 * Declares Node + ES2022 globals so `no-undef` does not false-positive on\n * `console`, `process`, and other built-ins.\n */\nexport async function javascript(): Promise<TypedFlatConfigItem[]> {\n const jsMod = await import('@eslint/js');\n const globalsMod = await import('globals');\n\n const js = (jsMod as any).default ?? jsMod;\n const globals = (globalsMod as any).default ?? globalsMod;\n\n return [\n {\n name: 'qstanay/javascript',\n languageOptions: {\n globals: {\n ...globals.es2022,\n ...globals.nodeBuiltin,\n },\n },\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 { typescriptFiles } 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(options: {\n vue?: boolean;\n} = {}): 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 const vueEnabled = options.vue === true;\n\n return [\n {\n name: 'qstanay/typescript',\n files: typescriptFiles(vueEnabled),\n languageOptions: {\n parser,\n parserOptions: {\n sourceType: 'module',\n ecmaVersion: 'latest',\n ...(vueEnabled\n ? { extraFileExtensions: ['.vue'] }\n : {}),\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 {\n has,\n resolveEnabled,\n resolveStylisticOptions,\n sourceFiles,\n VUE_FILES,\n} 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 const files = sourceFiles(enableVue);\n\n const configs: (Awaitable<TypedFlatConfigItem[]>)[] = [];\n\n // When Vue is off, skip SFCs entirely so espree/TS do not fatal-parse them.\n configs.push(Promise.resolve(ignores([\n ...(options.ignores ?? []),\n ...(!enableVue ? VUE_FILES : []),\n ])));\n configs.push(javascriptConfig());\n\n if (enableTs) {\n configs.push(typescriptConfig({ vue: enableVue }));\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,\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,\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,7 +40,15 @@ interface OptionsConfig {
35
40
  //#region src/nuxt.d.ts
36
41
  interface NuxtPresetOptions {
37
42
  stylistic?: boolean | StylisticOptions;
43
+ /**
44
+ * Enable stricter opinionated TypeScript rules (e.g. `no-magic-numbers`).
45
+ */
46
+ strict?: boolean;
38
47
  overrides?: Linter.RulesRecord;
48
+ /**
49
+ * Extra ignores appended to defaults / `.gitignore`.
50
+ */
51
+ ignores?: string[];
39
52
  }
40
53
  /**
41
54
  * Opinionated layer for Nuxt apps.
@@ -47,4 +60,4 @@ interface NuxtPresetOptions {
47
60
  declare function nuxt(options?: NuxtPresetOptions): Promise<TypedFlatConfigItem[]>[];
48
61
  //#endregion
49
62
  export { StylisticOptions as a, OptionsConfig as i, nuxt as n, TypedFlatConfigItem as o, Awaitable as r, NuxtPresetOptions as t };
50
- //# sourceMappingURL=nuxt-D-E7z44c.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"}
@@ -1,19 +1,20 @@
1
+ import gitignore from "eslint-config-flat-gitignore";
1
2
  import { isPackageExists } from "local-pkg";
2
- //#region src/utils.ts
3
- function resolveEnabled(explicit, detected) {
4
- return explicit ?? detected;
5
- }
6
- function has(pkg) {
7
- return isPackageExists(pkg);
8
- }
9
- function resolveStylisticOptions(stylistic) {
10
- if (stylistic === false) return false;
11
- if (typeof stylistic === "object") return stylistic;
12
- return {};
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
+ }];
13
17
  }
14
- const SOURCE_FILES = ["**/*.{js,jsx,ts,tsx,cts,mts,vue}"];
15
- const TYPESCRIPT_FILES = ["**/*.{ts,tsx,cts,mts}", "**/*.vue"];
16
- const VUE_FILES = ["**/*.vue"];
17
18
  //#endregion
18
19
  //#region src/configs/shared-rules.ts
19
20
  function javascriptRules() {
@@ -27,8 +28,10 @@ function javascriptRules() {
27
28
  "arrow-body-style": ["error", "as-needed"]
28
29
  };
29
30
  }
30
- function typescriptRules() {
31
- return {
31
+ function typescriptRules(options = {}) {
32
+ const rules = {
33
+ "no-unused-vars": "off",
34
+ "no-undef": "off",
32
35
  "@typescript-eslint/no-unused-vars": ["error", {
33
36
  argsIgnorePattern: "^_",
34
37
  varsIgnorePattern: "^_",
@@ -41,22 +44,23 @@ function typescriptRules() {
41
44
  }],
42
45
  "@typescript-eslint/no-explicit-any": "warn",
43
46
  "@typescript-eslint/no-non-null-assertion": "error",
44
- "@typescript-eslint/no-empty-function": ["error", { allow: ["arrowFunctions"] }],
45
- "@typescript-eslint/no-magic-numbers": ["warn", {
46
- ignore: [
47
- -1,
48
- 0,
49
- 1,
50
- 2,
51
- 1e3
52
- ],
53
- ignoreEnums: true,
54
- ignoreArrayIndexes: true,
55
- ignoreDefaultValues: true,
56
- ignoreClassFieldInitialValues: true,
57
- ignoreReadonlyClassProperties: true
58
- }]
47
+ "@typescript-eslint/no-empty-function": ["error", { allow: ["arrowFunctions"] }]
59
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;
60
64
  }
61
65
  /**
62
66
  * Shared opinionated rules.
@@ -66,7 +70,7 @@ function typescriptRules() {
66
70
  function sharedRules(options = {}) {
67
71
  return {
68
72
  ...javascriptRules(),
69
- ...options.typescript ? typescriptRules() : {}
73
+ ...options.typescript ? typescriptRules({ strict: options.strict }) : {}
70
74
  };
71
75
  }
72
76
  //#endregion
@@ -103,6 +107,35 @@ async function stylistic(options = {}) {
103
107
  }];
104
108
  }
105
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 SCRIPT_FILES = ["**/*.{js,mjs,cjs,jsx,ts,tsx,cts,mts}"];
123
+ const VUE_FILES = ["**/*.vue"];
124
+ /** TypeScript sources (`.vue` is added only when Vue is enabled). */
125
+ const TYPESCRIPT_FILES = ["**/*.{ts,tsx,cts,mts}"];
126
+ /**
127
+ * Files that receive shared / override rule packs.
128
+ * `.vue` is included only when Vue support is enabled.
129
+ */
130
+ function sourceFiles(vueEnabled) {
131
+ return vueEnabled ? [...SCRIPT_FILES, ...VUE_FILES] : [...SCRIPT_FILES];
132
+ }
133
+ function typescriptFiles(vueEnabled) {
134
+ return vueEnabled ? [...TYPESCRIPT_FILES, ...VUE_FILES] : [...TYPESCRIPT_FILES];
135
+ }
136
+ /** Files that receive shared / override rule packs when Vue is enabled. */
137
+ const SOURCE_FILES = ["**/*.{js,mjs,cjs,jsx,ts,tsx,cts,mts,vue}"];
138
+ //#endregion
106
139
  //#region src/configs/vue-rules.ts
107
140
  function vueRules() {
108
141
  return {
@@ -116,7 +149,11 @@ function vueRules() {
116
149
  math: "always"
117
150
  }],
118
151
  "vue/attributes-order": "error",
119
- "vue/padding-line-between-tags": "error"
152
+ "vue/padding-line-between-tags": ["error", [{
153
+ blankLine: "always",
154
+ prev: "*",
155
+ next: "*"
156
+ }]]
120
157
  };
121
158
  }
122
159
  //#endregion
@@ -130,12 +167,15 @@ function vueRules() {
130
167
  */
131
168
  function nuxt(options = {}) {
132
169
  const stylisticOptions = resolveStylisticOptions(options.stylistic);
133
- const configs = [];
170
+ const configs = [Promise.resolve(ignores(options.ignores))];
134
171
  if (stylisticOptions) configs.push(stylistic(stylisticOptions));
135
172
  configs.push(Promise.resolve([{
136
173
  name: "qstanay/nuxt/shared-rules",
137
174
  files: [...SOURCE_FILES],
138
- rules: sharedRules({ typescript: true })
175
+ rules: sharedRules({
176
+ typescript: true,
177
+ strict: options.strict
178
+ })
139
179
  }, {
140
180
  name: "qstanay/nuxt/vue-rules",
141
181
  files: [...VUE_FILES],
@@ -149,6 +189,6 @@ function nuxt(options = {}) {
149
189
  return configs;
150
190
  }
151
191
  //#endregion
152
- export { SOURCE_FILES as a, has as c, sharedRules as i, resolveEnabled as l, vueRules as n, TYPESCRIPT_FILES as o, stylistic as r, VUE_FILES as s, nuxt as t, resolveStylisticOptions as u };
192
+ export { resolveEnabled as a, typescriptFiles as c, ignores as d, has as i, stylistic as l, vueRules as n, resolveStylisticOptions as o, VUE_FILES as r, sourceFiles as s, nuxt as t, sharedRules as u };
153
193
 
154
- //# sourceMappingURL=nuxt-HGf9trGQ.mjs.map
194
+ //# sourceMappingURL=nuxt-jcrXAC4G.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nuxt-jcrXAC4G.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\nconst SCRIPT_FILES = [\n '**/*.{js,mjs,cjs,jsx,ts,tsx,cts,mts}',\n] as const;\n\nexport const VUE_FILES = ['**/*.vue'] as const;\n\n/** TypeScript sources (`.vue` is added only when Vue is enabled). */\nexport const TYPESCRIPT_FILES = [\n '**/*.{ts,tsx,cts,mts}',\n] as const;\n\n/**\n * Files that receive shared / override rule packs.\n * `.vue` is included only when Vue support is enabled.\n */\nexport function sourceFiles(vueEnabled: boolean): string[] {\n return vueEnabled\n ? [...SCRIPT_FILES, ...VUE_FILES]\n : [...SCRIPT_FILES];\n}\n\nexport function typescriptFiles(vueEnabled: boolean): string[] {\n return vueEnabled\n ? [...TYPESCRIPT_FILES, ...VUE_FILES]\n : [...TYPESCRIPT_FILES];\n}\n\n/** Files that receive shared / override rule packs when Vue is enabled. */\nexport const SOURCE_FILES = [\n '**/*.{js,mjs,cjs,jsx,ts,tsx,cts,mts,vue}',\n] 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': [\n 'error',\n [\n {\n blankLine: 'always',\n prev: '*',\n next: '*',\n },\n ],\n ],\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-D-E7z44c.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-HGf9trGQ.mjs";
1
+ import { t as nuxt } from "./nuxt-jcrXAC4G.mjs";
2
2
  export { nuxt };
package/package.json CHANGED
@@ -1,11 +1,17 @@
1
1
  {
2
2
  "name": "@qstanay/eslint-config",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "Opinionated ESLint flat config for Nuxt, Vue and TypeScript",
5
5
  "type": "module",
6
6
  "exports": {
7
- ".": "./dist/index.mjs",
8
- "./nuxt": "./dist/nuxt.mjs",
7
+ ".": {
8
+ "types": "./dist/index.d.mts",
9
+ "default": "./dist/index.mjs"
10
+ },
11
+ "./nuxt": {
12
+ "types": "./dist/nuxt.d.mts",
13
+ "default": "./dist/nuxt.mjs"
14
+ },
9
15
  "./package.json": "./package.json"
10
16
  },
11
17
  "types": "./dist/index.d.mts",
@@ -22,18 +28,32 @@
22
28
  "type": "git",
23
29
  "url": "git+https://github.com/qstanay/eslint-config.git"
24
30
  },
25
- "keywords": [],
26
- "author": "",
31
+ "keywords": [
32
+ "eslint",
33
+ "eslint-config",
34
+ "eslintconfig",
35
+ "flat-config",
36
+ "nuxt",
37
+ "vue",
38
+ "typescript",
39
+ "stylistic"
40
+ ],
41
+ "author": "Denis Lapshin",
27
42
  "license": "MIT",
28
43
  "bugs": {
29
44
  "url": "https://github.com/qstanay/eslint-config/issues"
30
45
  },
31
46
  "homepage": "https://github.com/qstanay/eslint-config#readme",
47
+ "engines": {
48
+ "node": ">=18"
49
+ },
32
50
  "files": [
33
- "dist"
51
+ "dist",
52
+ "CHANGELOG.md"
34
53
  ],
35
54
  "peerDependencies": {
36
- "eslint": "^9.0.0 || ^10.0.0"
55
+ "eslint": "^9.0.0 || ^10.0.0",
56
+ "typescript": ">=4.9.0"
37
57
  },
38
58
  "peerDependenciesMeta": {
39
59
  "typescript": {
@@ -41,6 +61,7 @@
41
61
  }
42
62
  },
43
63
  "dependencies": {
64
+ "@eslint/js": "^10.0.1",
44
65
  "@nuxt/eslint-plugin": "^1.16.0",
45
66
  "@stylistic/eslint-plugin": "^5.10.0",
46
67
  "@typescript-eslint/eslint-plugin": "^8.0.0",
@@ -56,7 +77,6 @@
56
77
  "devDependencies": {
57
78
  "@types/node": "^26.1.1",
58
79
  "eslint": "^10.7.0",
59
- "jiti": "^2.5.1",
60
80
  "tsdown": "^0.22.7",
61
81
  "typescript": "^6.0.3",
62
82
  "vitest": "^4.1.10"
@@ -1 +0,0 @@
1
- {"version":3,"file":"nuxt-D-E7z44c.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,OAAO;;;;;;;;;iBAUL,KAAK,UAAS,oBAAsB,QAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"nuxt-HGf9trGQ.mjs","names":["stylisticConfig"],"sources":["../src/utils.ts","../src/configs/shared-rules.ts","../src/configs/stylistic.ts","../src/configs/vue-rules.ts","../src/nuxt.ts"],"sourcesContent":["import type { StylisticOptions } from './types';\n\nimport { 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\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 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(): Linter.RulesRecord {\n return {\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\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: { typescript?: boolean } = {}): Linter.RulesRecord {\n return {\n ...javascriptRules(),\n ...(options.typescript ? typescriptRules() : {}),\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 { 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 type { Linter } from 'eslint';\n\nimport type { StylisticOptions, TypedFlatConfigItem } from './types';\n\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\nexport interface NuxtPresetOptions {\n stylistic?: boolean | StylisticOptions;\n overrides?: Linter.RulesRecord;\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\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({ typescript: true }),\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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"}