@useinsider/eslint-config 1.13.0 → 1.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/README.md +366 -58
  2. package/dist/builders/configFiles.d.ts +12 -0
  3. package/dist/builders/jquery.d.ts +5 -0
  4. package/dist/builders/scopeBlocks.d.ts +49 -0
  5. package/dist/builders/spellChecker.d.ts +7 -0
  6. package/dist/builders/strict.d.ts +2 -0
  7. package/dist/builders/typescript.d.ts +6 -0
  8. package/dist/builders/vue.d.ts +8 -0
  9. package/dist/cli.cjs +4538 -0
  10. package/dist/cli.cjs.map +1 -0
  11. package/dist/configs/config/dependencies.d.ts +1 -0
  12. package/dist/configs/javascript/dependencies.d.ts +1 -0
  13. package/dist/configs/javascript-dom/dependencies.d.ts +1 -0
  14. package/dist/configs/javascript-node/dependencies.d.ts +1 -0
  15. package/dist/configs/jest/dependencies.d.ts +3 -0
  16. package/dist/configs/jsdoc-based-ts/dependencies.d.ts +6 -0
  17. package/dist/configs/strict/dependencies.d.ts +3 -0
  18. package/dist/configs/typescript/dependencies.d.ts +6 -0
  19. package/dist/configs/typescript-dom/dependencies.d.ts +6 -0
  20. package/dist/configs/typescript-node/dependencies.d.ts +6 -0
  21. package/dist/configs/vitest/dependencies.d.ts +3 -0
  22. package/dist/configs/vitest/index.d.ts +3 -0
  23. package/dist/configs/vue2/dependencies.d.ts +5 -0
  24. package/dist/configs/vue2-options-api/dependencies.d.ts +5 -0
  25. package/dist/configs/vue2-options-api/index.d.ts +1208 -0
  26. package/dist/configs/vue2-typescript/dependencies.d.ts +9 -0
  27. package/dist/configs/vue2-typescript-options-api/dependencies.d.ts +9 -0
  28. package/dist/configs/vue2-typescript-options-api/index.d.ts +3 -0
  29. package/dist/configs/vue3/dependencies.d.ts +5 -0
  30. package/dist/configs/vue3-options-api/dependencies.d.ts +5 -0
  31. package/dist/configs/vue3-options-api/index.d.ts +1208 -0
  32. package/dist/configs/vue3-typescript/dependencies.d.ts +9 -0
  33. package/dist/configs/vue3-typescript-options-api/dependencies.d.ts +9 -0
  34. package/dist/configs/vue3-typescript-options-api/index.d.ts +3 -0
  35. package/dist/{javascript-ZbGsFE17.cjs → javascript-CrNAuq8X.cjs} +2 -2
  36. package/dist/{javascript-ZbGsFE17.cjs.map → javascript-CrNAuq8X.cjs.map} +1 -1
  37. package/dist/{javascript-BXgxOHrE.js → javascript-DBh1tdoj.js} +2 -2
  38. package/dist/{javascript-BXgxOHrE.js.map → javascript-DBh1tdoj.js.map} +1 -1
  39. package/dist/{javascript-dom-D7RX0w0r.cjs → javascript-dom-qddIl6lD.cjs} +2 -2
  40. package/dist/{javascript-dom-D7RX0w0r.cjs.map → javascript-dom-qddIl6lD.cjs.map} +1 -1
  41. package/dist/{javascript-dom-DQiJS6LF.js → javascript-dom-vHj4V_jJ.js} +2 -2
  42. package/dist/{javascript-dom-DQiJS6LF.js.map → javascript-dom-vHj4V_jJ.js.map} +1 -1
  43. package/dist/{javascript-node-fII8MlI4.cjs → javascript-node-CymkpeIN.cjs} +2 -2
  44. package/dist/{javascript-node-fII8MlI4.cjs.map → javascript-node-CymkpeIN.cjs.map} +1 -1
  45. package/dist/{javascript-node-DDpIBysN.js → javascript-node-rbQ7OZX2.js} +2 -2
  46. package/dist/{javascript-node-DDpIBysN.js.map → javascript-node-rbQ7OZX2.js.map} +1 -1
  47. package/dist/main.cjs +530 -52
  48. package/dist/main.cjs.map +1 -1
  49. package/dist/main.d.ts +56 -21
  50. package/dist/main.js +531 -55
  51. package/dist/main.js.map +1 -1
  52. package/dist/rules/vue-options-api.d.ts +2 -0
  53. package/dist/{stylistic-Cca81A-Y.js → stylistic-C527N_5D.js} +22 -20
  54. package/dist/stylistic-C527N_5D.js.map +1 -0
  55. package/dist/{stylistic-BltudTa0.cjs → stylistic-_qagyIah.cjs} +22 -20
  56. package/dist/stylistic-_qagyIah.cjs.map +1 -0
  57. package/dist/{typescript-Z0gBgZeY.js → typescript-BkxC1Ebj.js} +3 -3
  58. package/dist/{typescript-Z0gBgZeY.js.map → typescript-BkxC1Ebj.js.map} +1 -1
  59. package/dist/{typescript-RDy5oH7o.cjs → typescript-Cm5y5BRu.cjs} +3 -3
  60. package/dist/{typescript-RDy5oH7o.cjs.map → typescript-Cm5y5BRu.cjs.map} +1 -1
  61. package/dist/{typescript-dom-DUh1spmb.cjs → typescript-dom-B5cwc97i.cjs} +2 -2
  62. package/dist/{typescript-dom-DUh1spmb.cjs.map → typescript-dom-B5cwc97i.cjs.map} +1 -1
  63. package/dist/{typescript-dom-BFinGO4G.js → typescript-dom-BMG-VaTV.js} +2 -2
  64. package/dist/{typescript-dom-BFinGO4G.js.map → typescript-dom-BMG-VaTV.js.map} +1 -1
  65. package/dist/{typescript-node-ClKSHtBn.cjs → typescript-node-BPHyiIve.cjs} +2 -2
  66. package/dist/{typescript-node-ClKSHtBn.cjs.map → typescript-node-BPHyiIve.cjs.map} +1 -1
  67. package/dist/{typescript-node-B3akGwfD.js → typescript-node-D_KHq9pf.js} +2 -2
  68. package/dist/{typescript-node-B3akGwfD.js.map → typescript-node-D_KHq9pf.js.map} +1 -1
  69. package/dist/utils/ensureConfigStructure.d.ts +17 -0
  70. package/dist/vitest-BgPQ6GrC.js +15 -0
  71. package/dist/vitest-BgPQ6GrC.js.map +1 -0
  72. package/dist/vitest-Cxe6To8m.cjs +17 -0
  73. package/dist/vitest-Cxe6To8m.cjs.map +1 -0
  74. package/dist/{vue-ABpPpVRF.cjs → vue-BSB1UZUR.cjs} +1 -1
  75. package/dist/{vue-ABpPpVRF.cjs.map → vue-BSB1UZUR.cjs.map} +1 -1
  76. package/dist/{vue-DN4l4tpE.js → vue-W9Dr0NU_.js} +1 -1
  77. package/dist/{vue-DN4l4tpE.js.map → vue-W9Dr0NU_.js.map} +1 -1
  78. package/dist/vue-options-api-DOwpLXkl.cjs +21 -0
  79. package/dist/vue-options-api-DOwpLXkl.cjs.map +1 -0
  80. package/dist/vue-options-api-Dx5bF7ak.js +16 -0
  81. package/dist/vue-options-api-Dx5bF7ak.js.map +1 -0
  82. package/dist/{vue2-DSL0XmaS.cjs → vue2-BO5tkjc4.cjs} +2 -2
  83. package/dist/{vue2-DSL0XmaS.cjs.map → vue2-BO5tkjc4.cjs.map} +1 -1
  84. package/dist/{vue2-BiP0fuu1.js → vue2-DkvfPqh_.js} +2 -2
  85. package/dist/{vue2-BiP0fuu1.js.map → vue2-DkvfPqh_.js.map} +1 -1
  86. package/dist/{vue2-Bh7W369C.cjs → vue2-XNhU8qvc.cjs} +3 -3
  87. package/dist/{vue2-Bh7W369C.cjs.map → vue2-XNhU8qvc.cjs.map} +1 -1
  88. package/dist/{vue2-DDKBhsLm.js → vue2-npomS1zY.js} +3 -3
  89. package/dist/{vue2-DDKBhsLm.js.map → vue2-npomS1zY.js.map} +1 -1
  90. package/dist/vue2-options-api-BPw5U0yK.js +25 -0
  91. package/dist/vue2-options-api-BPw5U0yK.js.map +1 -0
  92. package/dist/vue2-options-api-zm_Ppsnb.cjs +31 -0
  93. package/dist/vue2-options-api-zm_Ppsnb.cjs.map +1 -0
  94. package/dist/vue2-typescript-B2ubjEbm.cjs +18 -0
  95. package/dist/vue2-typescript-B2ubjEbm.cjs.map +1 -0
  96. package/dist/{vue2-typescript-CUqjxRHT.js → vue2-typescript-DV30OSCU.js} +4 -13
  97. package/dist/vue2-typescript-DV30OSCU.js.map +1 -0
  98. package/dist/vue2-typescript-DkeW8a4q.js +13 -0
  99. package/dist/vue2-typescript-DkeW8a4q.js.map +1 -0
  100. package/dist/vue2-typescript-options-api-Dxl4Cj_u.js +42 -0
  101. package/dist/vue2-typescript-options-api-Dxl4Cj_u.js.map +1 -0
  102. package/dist/vue2-typescript-options-api-Tj8_pTDc.cjs +50 -0
  103. package/dist/vue2-typescript-options-api-Tj8_pTDc.cjs.map +1 -0
  104. package/dist/{vue2-typescript-GmtjjCxx.cjs → vue2-typescript-qUvTF_0O.cjs} +5 -14
  105. package/dist/vue2-typescript-qUvTF_0O.cjs.map +1 -0
  106. package/dist/{vue3-CKwnKeS6.js → vue3-BnQYXB3K.js} +3 -3
  107. package/dist/{vue3-CKwnKeS6.js.map → vue3-BnQYXB3K.js.map} +1 -1
  108. package/dist/{vue3-BtNhSn_w.cjs → vue3-Dexa-ftV.cjs} +3 -3
  109. package/dist/{vue3-BtNhSn_w.cjs.map → vue3-Dexa-ftV.cjs.map} +1 -1
  110. package/dist/vue3-options-api-Fl27U2nN.cjs +31 -0
  111. package/dist/vue3-options-api-Fl27U2nN.cjs.map +1 -0
  112. package/dist/vue3-options-api-cejoqzVH.js +25 -0
  113. package/dist/vue3-options-api-cejoqzVH.js.map +1 -0
  114. package/dist/{vue3-typescript-CbM4dYzN.js → vue3-typescript-C65tDgFp.js} +3 -3
  115. package/dist/{vue3-typescript-CbM4dYzN.js.map → vue3-typescript-C65tDgFp.js.map} +1 -1
  116. package/dist/{vue3-typescript-P2UoKs0V.cjs → vue3-typescript-CzR7L5ep.cjs} +3 -3
  117. package/dist/{vue3-typescript-P2UoKs0V.cjs.map → vue3-typescript-CzR7L5ep.cjs.map} +1 -1
  118. package/dist/vue3-typescript-options-api-D56mHjp4.cjs +49 -0
  119. package/dist/vue3-typescript-options-api-D56mHjp4.cjs.map +1 -0
  120. package/dist/vue3-typescript-options-api-DL7JFqMJ.js +41 -0
  121. package/dist/vue3-typescript-options-api-DL7JFqMJ.js.map +1 -0
  122. package/package.json +29 -6
  123. package/dist/stylistic-BltudTa0.cjs.map +0 -1
  124. package/dist/stylistic-Cca81A-Y.js.map +0 -1
  125. package/dist/vue2-typescript-CUqjxRHT.js.map +0 -1
  126. package/dist/vue2-typescript-GmtjjCxx.cjs.map +0 -1
package/README.md CHANGED
@@ -1,97 +1,405 @@
1
- # ESLint Configurations
1
+ # @useinsider/eslint-config
2
+
3
+ Shared ESLint 9 flat-config for Insider projects. `useInsider()` takes a single
4
+ scope-keyed config object and returns a `defineConfig([...])` array — one
5
+ entry per file scope you describe. There is no opaque preset list, no
6
+ freeform `config` escape hatch, and no expectation that you spread the result
7
+ into your own array.
8
+
9
+ The default export is the resolved Promise returned by `useInsider(...)`;
10
+ ESLint 9 awaits it automatically. **Do not `await` it. Do not spread it. Do
11
+ not wrap it in an array.** If you find yourself wanting to append a block,
12
+ that is a sign your scope coverage is incomplete — describe the extra files
13
+ inside `useInsider({...})` instead.
2
14
 
3
15
  ## Table of Contents
4
- - [ESLint Configurations](#eslint-configurations)
5
- - [Table of Contents](#table-of-contents)
6
- - [Prerequisites](#prerequisites)
7
- - [Available Presets](#available-presets)
8
- - [Vanilla 🍦](#vanilla-)
9
- - [Library-specific \& Standalone Configs](#library-specific--standalone-configs)
10
- - [Framework-specific](#framework-specific)
11
- - [ Upcoming Configurations](#-upcoming-configurations)
12
- - [Examples](#examples)
13
- - [Troubleshooting](#troubleshooting)
14
- - [`Missing dependencies detected:`](#missing-dependencies-detected)
15
- - [Contributing](#contributing)
16
+
17
+ - [Prerequisites](#prerequisites)
18
+ - [Quick start](#quick-start)
19
+ - [Manual setup](#manual-setup)
20
+ - [Node + TypeScript](#node--typescript)
21
+ - [Browser + Vue 3 + TypeScript with split tsconfigs](#browser--vue-3--typescript-with-split-tsconfigs)
22
+ - [Vue 2 + JavaScript with jQuery globals](#vue-2--javascript-with-jquery-globals)
23
+ - [Strict and spell-checker knobs](#strict-and-spell-checker-knobs)
24
+ - [API reference](#api-reference)
25
+ - [Migrating from v1.x](#migrating-from-v1x)
26
+ - [First lint after install](#first-lint-after-install)
27
+ - [Troubleshooting](#troubleshooting)
28
+ - [Contributing](#contributing)
16
29
 
17
30
  ## Prerequisites
18
31
 
19
- - NodeJS 20+
32
+ - Node.js 20+
20
33
  - ESLint 9+
34
+ - pnpm, npm, or yarn
35
+
36
+ ## Quick start
37
+
38
+ ```bash
39
+ npx @useinsider/eslint-config
40
+ ```
41
+
42
+ The CLI walks an interactive prompt (project type, language, framework, test
43
+ runner, jQuery globals, tsconfig layout), installs every required ESLint
44
+ plugin pinned to the versions this package was built against, and writes a
45
+ starter `eslint.config.mjs` at the project root.
46
+
47
+ To migrate an existing v1 `eslint.config.{js,mjs,cjs}` or a legacy
48
+ `.eslintrc.{js,cjs}`:
49
+
50
+ ```bash
51
+ npx @useinsider/eslint-config migrate [path]
52
+ ```
53
+
54
+ The migrate flow auto-detects the source format. For flat configs it
55
+ parses the v1 file, prints a summary plus any dropped custom rules, asks
56
+ for confirmation, then rewrites the file in place. For legacy `.eslintrc`
57
+ files it writes a fresh `eslint.config.mjs` next to the original (custom
58
+ rules and non-`@useinsider/eslint-config/*` extends are dropped with a
59
+ loud warning so you can review what changed). Legacy `.eslintrc.{json,yml,yaml}`
60
+ are not supported in this release — convert them to `.eslintrc.{js,cjs}` first.
61
+
62
+ Example output for a Node + TypeScript project:
63
+
64
+ ```js
65
+ import { useInsider } from '@useinsider/eslint-config';
66
+
67
+ export default useInsider({
68
+ typescriptNode: [
69
+ {
70
+ files: ['**/*.{ts,tsx}'],
71
+ tsconfigPaths: ['tsconfig.json'],
72
+ },
73
+ ],
74
+ });
75
+ ```
76
+
77
+ What the CLI installs for that answer set (versions reflect the publish-time
78
+ pins):
79
+
80
+ - `@useinsider/eslint-config`
81
+ - `eslint`
82
+ - `globals`
83
+ - `typescript`
84
+ - `typescript-eslint`
21
85
 
22
- ## Available Presets
86
+ Vue, Jest, or Vitest answers add the matching plugin set (e.g. `eslint-plugin-vue`,
87
+ `vue-eslint-parser`, `eslint-plugin-vue-scoped-css`, `eslint-plugin-jest`,
88
+ or `@vitest/eslint-plugin`).
23
89
 
24
- We provide a variety of configurations to suit different environments and
25
- frameworks. Here's a list of available presets:
90
+ ## Manual setup
26
91
 
27
- ### Vanilla 🍦
92
+ Install the package first:
28
93
 
29
- There are additional presets for DOM (browser) and Node.js environments, beside
30
- the vanilla configuration. The vanilla is suitable for general JavaScript and
31
- TypeScript projects that does not have any specific environment and can be
32
- configured for different environments, such as ServiceWorkers, WebWorkers, etc.
94
+ ```bash
95
+ pnpm add -E -D @useinsider/eslint-config
96
+ ```
97
+
98
+ Then create `eslint.config.mjs` and call `useInsider(...)` with the scopes
99
+ your project needs. Each scope holds an array of `{ files, ... }` entries;
100
+ each entry becomes its own flat-config block.
101
+
102
+ ### Node + TypeScript
103
+
104
+ ```js
105
+ import { useInsider } from '@useinsider/eslint-config';
106
+
107
+ export default useInsider({
108
+ typescriptNode: [
109
+ {
110
+ files: ['**/*.{ts,tsx}'],
111
+ tsconfigPaths: ['tsconfig.json'],
112
+ },
113
+ ],
114
+ vitest: [
115
+ { files: ['**/*.{test,spec}.{ts,tsx}'] },
116
+ ],
117
+ });
118
+ ```
119
+
120
+ ### Browser + Vue 3 + TypeScript with split tsconfigs
121
+
122
+ A project using `tsconfig.app.json` for source and `tsconfig.test.json` for
123
+ tests, with `RouterLink` and `RouterView` as globally-registered components.
33
124
 
34
- | Environment | Vanilla | Browser (DOM) | Node |
35
- | :---------------- | :---------------------------------------------- | :------------------------------------------------------ | :-------------------------------------------------------- |
36
- | **EcmaScript/JS** | [`javascript`](./src/configs/javascript#readme) | [`javascript-dom`](./src/configs/javascript-dom#readme) | [`javascript-node`](./src/configs/javascript-node#readme) |
37
- | **TypeScript** | [`typescript`](./src/configs/typescript#readme) | [`typescript-dom`](./src/configs/typescript-dom#readme) | [`typescript-node`](./src/configs/typescript-node#readme) |
125
+ ```js
126
+ import { useInsider } from '@useinsider/eslint-config';
38
127
 
39
- ### Library-specific & Standalone Configs
128
+ export default useInsider({
129
+ vue3Typescript: [
130
+ {
131
+ files: ['src/**/*.{ts,tsx,vue}'],
132
+ tsconfigPaths: ['tsconfig.app.json'],
133
+ globalComponents: ['RouterLink', 'RouterView'],
134
+ },
135
+ ],
136
+ vitest: [
137
+ {
138
+ files: ['**/*.{test,spec}.{ts,tsx}'],
139
+ },
140
+ ],
141
+ typescriptNode: [
142
+ {
143
+ files: ['*.config.{ts,mts,cts}'],
144
+ tsconfigPaths: ['tsconfig.node.json'],
145
+ },
146
+ ],
147
+ });
148
+ ```
40
149
 
41
- | Environment | JavaScript & TypeScript |
42
- | :--------------- | :-------------------------------------- |
43
- | **Config files** | [`config`](./src/configs/config#readme) |
44
- | **Jest** | [`jest`](./src/configs/jest#readme) |
45
- | **Strict** | [`strict`](./src/configs/strict#readme) |
150
+ Multiple `tsconfigPaths` entries are supported per block — pass an array of
151
+ paths if a single scope needs more than one project reference.
46
152
 
47
- ### Framework-specific
153
+ ### Vue 2 + JavaScript with jQuery globals
48
154
 
49
- | Environment | JavaScript | TypeScript |
50
- | :-------------------------------- | :-------------------------------------------------------- | :-------------------------------------------------------- |
51
- | **Vue 3 (Setup/Composition API)** | [`vue3`](./src/configs/vue3#readme) | [`vue3-typescript`](./src/configs/vue3-typescript#readme) |
52
- | **Vue 2 (Setup/Composition API)** | [`vue2-typescript`](./src/configs/vue2-typescript#readme) | [`vue2-typescript`](./src/configs/vue2-typescript#readme) |
53
- | **Vue 2 (Options API)** | [`vue2`](./src/configs/vue2#readme) | - |
155
+ ```js
156
+ import { useInsider } from '@useinsider/eslint-config';
157
+
158
+ export default useInsider({
159
+ vue2: [
160
+ { files: ['src/**/*.{js,vue}'] },
161
+ ],
162
+ javascriptNode: [
163
+ { files: ['*.{js,cjs,mjs}'] },
164
+ ],
165
+ jquery: [
166
+ { files: ['src/**/*.{js,vue}'] },
167
+ ],
168
+ });
169
+ ```
54
170
 
55
- ### Upcoming Configurations
171
+ `jquery` is a top-level scope. Pass an array of `{ files }` entries describing
172
+ the globs that should see the jQuery globals (`$`, `jQuery`). The block is
173
+ emitted after the scope blocks and before `strict`/`spellChecker`, so the
174
+ matching language scope still applies its rule set and jQuery globals are
175
+ layered on top of it.
56
176
 
57
- Planned configurations for the next
177
+ ### Strict and spell-checker knobs
58
178
 
59
- - Legacy ES5 💀​
179
+ `strict` and `spellChecker` are flat cross-cutting options. They sit at the
180
+ top level of the config, not inside a scope entry.
181
+
182
+ ```js
183
+ import { useInsider } from '@useinsider/eslint-config';
184
+
185
+ export default useInsider({
186
+ typescriptNode: [
187
+ {
188
+ files: ['**/*.{ts,tsx}'],
189
+ tsconfigPaths: ['tsconfig.json'],
190
+ },
191
+ ],
192
+ strict: ['src/**/*.ts'],
193
+ spellChecker: {
194
+ ignoredPaths: ['vendor/**', 'dist/**'],
195
+ customWordListFile: './cspell.custom.json',
196
+ },
197
+ silenceRules: ['no-console'],
198
+ });
199
+ ```
60
200
 
61
- ## Examples
201
+ - `strict: true` applies strict rules to every file.
202
+ - `strict: string[]` applies strict rules only to the matching paths.
203
+ - `spellChecker.customWordListFile` re-points `@cspell/spellchecker` to a
204
+ project-local word list.
205
+ - `spellChecker.ignoredPaths` turns the spell-checker off for the matching
206
+ globs (the off block is emitted after the custom-list block, so ignore
207
+ wins on overlap).
208
+ - `silenceRules` rewrites the severity of the listed rule IDs to `'warn'`
209
+ across every emitted block while preserving each rule's options.
62
210
 
63
- Checkout the [examples directory](../../examples) to see various apps with the extended ESLint
64
- configuration.
211
+ ## API reference
212
+
213
+ `useInsider(config)` accepts the following top-level properties. Each scope
214
+ holds an array of entries; each entry produces its own flat-config block.
215
+
216
+ Every scope entry shape also accepts two common fields:
217
+
218
+ - `ignores?: string[]` — applies as the block's `ignores` key, scoping the
219
+ rule set away from the listed globs.
220
+ - `globals?: Record<string, GlobalConf>` — merged on top of the globals the
221
+ preset already provides; pass `'readonly'`, `'writable'`, or `'off'` per
222
+ ESLint's `Linter.Globals`. Use this to declare project-specific globals
223
+ like `APP_URL`, `axios`, `atatus`.
224
+
225
+ | Property | Entry shape | Notes |
226
+ | ---------------- | -------------------------------------------------------------------------------------------------------- | ----- |
227
+ | `ignores` | `string[]` (top-level) | Emits a leading `{ ignores }` block applied to every other block. |
228
+ | `javascript` | `{ files: string[]; ignores?: string[]; globals?: Linter.Globals }` | Environment-agnostic JS (workers, isomorphic). |
229
+ | `javascriptDom` | `{ files: string[]; ignores?: string[]; globals?: Linter.Globals }` | Browser JS. |
230
+ | `javascriptNode` | `{ files: string[]; ignores?: string[]; globals?: Linter.Globals }` | Node JS. |
231
+ | `typescript` | `{ files: string[]; tsconfigPaths: string[]; ignores?: string[]; globals?: Linter.Globals }` | Environment-agnostic TS. |
232
+ | `typescriptDom` | `{ files: string[]; tsconfigPaths: string[]; ignores?: string[]; globals?: Linter.Globals }` | Browser TS. |
233
+ | `typescriptNode` | `{ files: string[]; tsconfigPaths: string[]; ignores?: string[]; globals?: Linter.Globals }` | Node TS. |
234
+ | `vue2` | `{ files: string[]; globalComponents?: string[]; ignores?: string[]; globals?: Linter.Globals }` | Vue 2 single-file components in JS. |
235
+ | `vue3` | `{ files: string[]; globalComponents?: string[]; ignores?: string[]; globals?: Linter.Globals }` | Vue 3 single-file components in JS. |
236
+ | `vue2Typescript` | `{ files: string[]; globalComponents?: string[]; tsconfigPaths: string[]; ignores?: string[]; globals?: Linter.Globals }` | Vue 2 + TS. |
237
+ | `vue3Typescript` | `{ files: string[]; globalComponents?: string[]; tsconfigPaths: string[]; ignores?: string[]; globals?: Linter.Globals }` | Vue 3 + TS. |
238
+ | `jest` | `{ files: string[]; ignores?: string[]; globals?: Linter.Globals }` | Jest test files. |
239
+ | `vitest` | `{ files: string[]; ignores?: string[]; globals?: Linter.Globals }` | Vitest test files. |
240
+ | `jsdocBasedTs` | `{ files: string[]; tsconfigPaths: string[]; ignores?: string[]; globals?: Linter.Globals }` | JS files type-checked via JSDoc. |
241
+ | `jquery` | `{ files: string[]; ignores?: string[]; globals?: Linter.Globals }` | Layers jQuery globals (`$`, `jQuery`) on top of the matching globs. Per-entry `globals` merge with the jQuery ones rather than replacing them. |
242
+ | `strict` | `boolean \| string[]` | Applies the strict preset globally (`true`) or scoped to globs. |
243
+ | `spellChecker` | `{ ignoredPaths?: string[]; customWordListFile?: string }` | Cross-cutting cspell overrides. |
244
+ | `silenceRules` | `string[]` | Rule IDs to demote to `'warn'` across every block. |
245
+ | `configFiles` | `false \| string[]` | Emits a dedicated block for root-level configuration files (`*.config.*`, `eslint.config.*`) that disables `import-x/no-extraneous-dependencies` and `import-x/prefer-default-export`. **Defaults are applied automatically** — omit the key (or pass `[]`) to use the built-in defaults only, pass a `string[]` to layer your own globs on top, or pass `false` to opt out entirely. |
246
+
247
+ A scope entry with per-entry globals — declare project-specific bindings
248
+ without spreading the `useInsider` return into your own array:
249
+
250
+ ```js
251
+ import { useInsider } from '@useinsider/eslint-config';
252
+
253
+ export default useInsider({
254
+ ignores: ['dist', 'coverage'],
255
+ javascriptDom: [
256
+ {
257
+ files: ['src/**/*.js'],
258
+ ignores: ['src/vendor/**'],
259
+ globals: {
260
+ APP_URL: 'readonly',
261
+ axios: 'readonly',
262
+ atatus: 'readonly',
263
+ },
264
+ },
265
+ ],
266
+ });
267
+ ```
268
+
269
+ Block-emission order — scope blocks first (in the order their keys were
270
+ inserted into the config object), then `jquery` blocks, then any `strict`
271
+ blocks, then `spellChecker` blocks. Later blocks win on overlap, matching
272
+ ESLint's flat-config precedence model.
273
+
274
+ `useInsider` returns `Promise<Linter.Config[]>`. Export it directly — ESLint
275
+ 9 resolves the Promise at load time. `useInsider`'s return type carries
276
+ through, so no JSDoc annotation is needed; the `UseInsiderResult` type alias
277
+ is exported for TypeScript callers that wrap `useInsider` in a helper of
278
+ their own.
279
+
280
+ `silenceRules()` (named export) is also available as a global registration
281
+ hook. Call it at module top level to register rule IDs to demote *before*
282
+ `useInsider` is invoked; the per-call `silenceRules: [...]` option layers
283
+ on top.
284
+
285
+ ```js
286
+ import { useInsider, silenceRules } from '@useinsider/eslint-config';
287
+
288
+ silenceRules(['no-magic-numbers']);
289
+
290
+ export default useInsider({ /* ... */ });
291
+ ```
292
+
293
+ ## Migrating from v1.x
294
+
295
+ v2 is a hard break. The summary:
296
+
297
+ - **`preset: string[]`** → top-level scope properties. The order in the
298
+ v1 `preset` array no longer matters — the new shape has one property per
299
+ scope and overrides are explicit.
300
+
301
+ ```diff
302
+ - await useInsider({
303
+ - preset: ['typescript-node'],
304
+ - config: { files: ['src/**/*.ts'], languageOptions: { parserOptions: { project: ['./tsconfig.json'] } } },
305
+ - })
306
+ + useInsider({
307
+ + typescriptNode: [
308
+ + { files: ['src/**/*.ts'], tsconfigPaths: ['tsconfig.json'] },
309
+ + ],
310
+ + })
311
+ ```
312
+
313
+ - **`preset: ['vue3-typescript']` + `config`** → `vue3Typescript` entry
314
+ with a dedicated `globalComponents` field. No more hand-rolled
315
+ `vue/no-undef-components` overrides.
316
+
317
+ ```diff
318
+ - await useInsider({
319
+ - preset: ['vue3-typescript'],
320
+ - config: {
321
+ - files: ['src/**/*.{ts,vue}'],
322
+ - languageOptions: { parserOptions: { project: ['./tsconfig.app.json'] } },
323
+ - rules: { 'vue/no-undef-components': ['error', { ignorePatterns: ['^RouterLink$', '^RouterView$'] }] },
324
+ - },
325
+ - })
326
+ + useInsider({
327
+ + vue3Typescript: [
328
+ + {
329
+ + files: ['src/**/*.{ts,vue}'],
330
+ + tsconfigPaths: ['tsconfig.app.json'],
331
+ + globalComponents: ['RouterLink', 'RouterView'],
332
+ + },
333
+ + ],
334
+ + })
335
+ ```
336
+
337
+ - **`preset: ['strict']`** → top-level `strict: true | string[]`.
338
+
339
+ ```diff
340
+ - await useInsider({ preset: ['typescript-node', 'strict'], config: { files: ['src/**/*.ts'] } })
341
+ + useInsider({
342
+ + typescriptNode: [{ files: ['src/**/*.ts'], tsconfigPaths: ['tsconfig.json'] }],
343
+ + strict: true,
344
+ + })
345
+ ```
346
+
347
+ Behavior change: in v1 the `strict` preset was always global when listed.
348
+ In v2, `strict: true` keeps that global behavior; `strict: string[]`
349
+ scopes the strict rule set to the matching globs only. If you have
350
+ paths-targeted strict checks, set `strict: [...]` instead of
351
+ `strict: true`.
352
+
353
+ - **Shape change**: `useInsider(...)` is now exported directly as the
354
+ default export, without `await`, without spread, and without an array
355
+ wrap. ESLint 9 resolves the Promise on load. The old pattern
356
+ `export default [...await useInsider({...})]` still parses, but the
357
+ preferred shape is `export default useInsider({...})`. There is no
358
+ supported override path — describe every glob you want linted inside
359
+ the call, including jQuery files via the dedicated `jquery` scope.
360
+
361
+ - **Removed**: the `preset` array, the `config: Linter.Config` escape
362
+ hatch, and the `config` preset itself. Configuration-file linting is
363
+ now an ordinary `typescriptNode` (or `javascriptNode`) entry pointed at
364
+ the right tsconfig.
365
+
366
+ - **Kept**: `silenceRules` accepts the same `string[]` shape both as a
367
+ top-level option and via the named `silenceRules()` export.
368
+ `silenceDependencyWarning()` works unchanged. Side-effect lines such as
369
+ `silenceDependencyWarning(true)` continue to sit above the
370
+ `export default useInsider({...})` call.
371
+
372
+ ## First lint after install
373
+
374
+ The first time you run lint after installing v2, `ensureDependencies` may
375
+ detect that your project's `eslint` or `globals` version is older than the
376
+ pin and auto-install them, exiting with code `1`. Run lint again and it
377
+ will complete normally.
65
378
 
66
379
  ## Troubleshooting
67
380
 
68
381
  ### `Missing dependencies detected:`
69
- If you see this error, it means that the configuration you are trying to use
70
- has some dependencies that are not installed in your project. You can install
71
- them by running the command that it provides.
72
382
 
73
- If you want to silence the warning, you can add the following code to your
74
- ESLint config file.
383
+ If you see this error, your project is missing a peer plugin this config
384
+ needs. The error message lists the install command. To silence the warning
385
+ permanently:
75
386
 
76
387
  ```js
77
388
  import { useInsider, silenceDependencyWarning } from '@useinsider/eslint-config';
78
389
 
79
390
  silenceDependencyWarning(['@cspell/eslint-plugin', '@stylistic/eslint-plugin']);
80
- ```
81
391
 
82
- Or you can pass `true` to the `silenceDependencyWarning` function to silence all
83
- warnings.
392
+ export default useInsider({ /* ... */ });
393
+ ```
84
394
 
85
- However, this is not recommended as it may cause unexpected issues while
86
- maintaining the dependencies.
395
+ Passing `true` silences every warning; that is not recommended because the
396
+ warning is the only signal that your installed plugin versions drifted
397
+ from what the config expects.
87
398
 
88
399
  ```js
89
- import { useInsider, silenceDependencyWarning } from '@useinsider/eslint-config';
90
-
91
400
  silenceDependencyWarning(true);
92
401
  ```
93
402
 
94
403
  ## Contributing
95
404
 
96
- Please refer to the [CONTRIBUTING.md](CONTRIBUTING.md) file for guidelines on
97
- how to contribute to this project.
405
+ See [CONTRIBUTING.md](../../CONTRIBUTING.md) at the repo root.
@@ -0,0 +1,12 @@
1
+ import type { Linter } from 'eslint';
2
+ /**
3
+ * Default globs treated as "configuration files" — root-level `*.config.*`
4
+ * variants plus the canonical `eslint.config.*` flat-config filenames.
5
+ *
6
+ * These are intentionally conservative: only the top-level matches that the
7
+ * v1 `config` preset was overwhelmingly applied to. Project-specific paths
8
+ * (subdirectories, custom names) must be opted into by passing them via the
9
+ * `configFiles: string[]` knob.
10
+ */
11
+ export declare const DEFAULT_CONFIG_FILE_GLOBS: readonly string[];
12
+ export declare function buildConfigFilesBlocks(value: false | string[] | undefined): Linter.Config[];
@@ -0,0 +1,5 @@
1
+ import type { Linter } from 'eslint';
2
+ export interface JqueryEntry {
3
+ files: string[];
4
+ }
5
+ export declare function buildJqueryBlocks(entries: readonly JqueryEntry[] | undefined): Linter.Config[];
@@ -0,0 +1,49 @@
1
+ import type { Linter } from 'eslint';
2
+ export interface CommonEntryFields {
3
+ ignores?: string[];
4
+ globals?: Linter.Globals;
5
+ }
6
+ export interface JsEntry extends CommonEntryFields {
7
+ files: string[];
8
+ }
9
+ export interface TsEntry extends CommonEntryFields {
10
+ files: string[];
11
+ tsconfigPaths: string[];
12
+ }
13
+ export interface VueEntry extends CommonEntryFields {
14
+ files: string[];
15
+ globalComponents?: string[];
16
+ }
17
+ export interface VueTsEntry extends CommonEntryFields {
18
+ files: string[];
19
+ globalComponents?: string[];
20
+ tsconfigPaths: string[];
21
+ }
22
+ export interface TestEntry extends CommonEntryFields {
23
+ files: string[];
24
+ }
25
+ export type ScopeEntry = JsEntry | TsEntry | VueEntry | VueTsEntry | TestEntry;
26
+ declare const scopeMap: {
27
+ config(): Promise<typeof import("../configs/config")>;
28
+ javascript(): Promise<typeof import("../configs/javascript")>;
29
+ javascriptDom(): Promise<typeof import("../configs/javascript-dom")>;
30
+ javascriptNode(): Promise<typeof import("../configs/javascript-node")>;
31
+ typescript(): Promise<typeof import("../configs/typescript")>;
32
+ typescriptDom(): Promise<typeof import("../configs/typescript-dom")>;
33
+ typescriptNode(): Promise<typeof import("../configs/typescript-node")>;
34
+ vue2(): Promise<typeof import("../configs/vue2")>;
35
+ vue3(): Promise<typeof import("../configs/vue3")>;
36
+ vue2Typescript(): Promise<typeof import("../configs/vue2-typescript")>;
37
+ vue3Typescript(): Promise<typeof import("../configs/vue3-typescript")>;
38
+ vue2OptionsApi(): Promise<typeof import("../configs/vue2-options-api")>;
39
+ vue3OptionsApi(): Promise<typeof import("../configs/vue3-options-api")>;
40
+ vue2TypescriptOptionsApi(): Promise<typeof import("../configs/vue2-typescript-options-api")>;
41
+ vue3TypescriptOptionsApi(): Promise<typeof import("../configs/vue3-typescript-options-api")>;
42
+ jest(): Promise<typeof import("../configs/jest")>;
43
+ vitest(): Promise<typeof import("../configs/vitest")>;
44
+ jsdocBasedTs(): Promise<typeof import("../configs/jsdoc-based-ts")>;
45
+ };
46
+ export type ScopeName = keyof typeof scopeMap;
47
+ export declare function isScopeName(key: string): key is ScopeName;
48
+ export declare function buildScopeBlocks(scope: ScopeName, entries: readonly ScopeEntry[]): Promise<Linter.Config[]>;
49
+ export {};
@@ -0,0 +1,7 @@
1
+ import type { Linter } from 'eslint';
2
+ interface SpellCheckerInput {
3
+ ignoredPaths?: string[];
4
+ customWordListFile?: string;
5
+ }
6
+ export declare function buildSpellCheckerBlocks(input: SpellCheckerInput | undefined): Linter.Config[];
7
+ export {};
@@ -0,0 +1,2 @@
1
+ import type { Linter } from 'eslint';
2
+ export declare function buildStrictBlocks(value: boolean | string[] | undefined): Promise<Linter.Config[]>;
@@ -0,0 +1,6 @@
1
+ import type { Linter } from 'eslint';
2
+ interface TypescriptOverrideInput {
3
+ tsconfigPaths: string[];
4
+ }
5
+ export declare function applyTypescriptOverrides<BlockType extends Linter.Config>(block: BlockType, input: TypescriptOverrideInput): BlockType;
6
+ export {};
@@ -0,0 +1,8 @@
1
+ import type { Linter } from 'eslint';
2
+ interface VueOverrideInput {
3
+ globalComponents?: string[];
4
+ }
5
+ export declare function escapeRegex(input: string): string;
6
+ export declare function anchoredEscapeRegex(input: string): string;
7
+ export declare function applyVueOverrides<BlockType extends Linter.Config>(block: BlockType, input: VueOverrideInput): BlockType;
8
+ export {};