@nitra/eslint-config 3.6.2 → 3.6.4
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/graphql-eslint-anchor.js +42 -1
- package/index.js +52 -12
- package/package.json +1 -1
package/graphql-eslint-anchor.js
CHANGED
|
@@ -20,6 +20,42 @@ const RELEVANT_KEYWORDS = ['gql', 'graphql', 'GraphQL']
|
|
|
20
20
|
/** Регулярний вираз на рівні модуля для e18e/prefer-static-regex. */
|
|
21
21
|
const VUE_OR_SVELTE_FILE_RE = /\.(vue|svelte)$/
|
|
22
22
|
|
|
23
|
+
/** Сегмент шляху до залежностей: виключаємо з пулу sibling-операцій для unique-operation-name / unique-fragment-name. */
|
|
24
|
+
const NODE_MODULES_SEGMENT_RE = /[/\\]node_modules[/\\]/
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Чи шлях джерела документа не всередині `node_modules`.
|
|
28
|
+
* @param {{ filePath?: string }} entry запис операції/фрагмента з graphql-eslint
|
|
29
|
+
* @returns {boolean} `true`, якщо `filePath` заданий і не містить сегмента `node_modules`
|
|
30
|
+
*/
|
|
31
|
+
function documentEntryOutsideNodeModules(entry) {
|
|
32
|
+
return typeof entry?.filePath === 'string' && !NODE_MODULES_SEGMENT_RE.test(entry.filePath)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Обгортка siblingOperations: graphql-config може підтягувати `documents` із `node_modules`, тоді
|
|
37
|
+
* правила з `requiresSiblings` бачать дублікати імен між застосунком і залежністю. Фільтр лишає
|
|
38
|
+
* лише записи зі шляхів поза `node_modules` (кеш плагіна не змінюється).
|
|
39
|
+
* @param {object} siblings оригінальний `siblingOperations` з graphql-eslint parser services
|
|
40
|
+
* @returns {object} той самий API з відфільтрованими `getOperation` / `getFragment` / списками
|
|
41
|
+
*/
|
|
42
|
+
function siblingOperationsWithoutNodeModules(siblings) {
|
|
43
|
+
if (!siblings?.available) {
|
|
44
|
+
return siblings
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
...siblings,
|
|
48
|
+
getFragment: name => siblings.getFragment(name).filter(entry => documentEntryOutsideNodeModules(entry)),
|
|
49
|
+
getFragments: () => siblings.getFragments().filter(entry => documentEntryOutsideNodeModules(entry)),
|
|
50
|
+
getFragmentByType: typeName =>
|
|
51
|
+
siblings.getFragmentByType(typeName).filter(entry => documentEntryOutsideNodeModules(entry)),
|
|
52
|
+
getOperation: name => siblings.getOperation(name).filter(entry => documentEntryOutsideNodeModules(entry)),
|
|
53
|
+
getOperations: () => siblings.getOperations().filter(entry => documentEntryOutsideNodeModules(entry)),
|
|
54
|
+
getOperationByType: type =>
|
|
55
|
+
siblings.getOperationByType(type).filter(entry => documentEntryOutsideNodeModules(entry))
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
23
59
|
/**
|
|
24
60
|
* Шлях для graphql-config: для віртуальних блоків Vue — фізичний .vue, інакше той самий filePath.
|
|
25
61
|
* @param {string} filePath шлях файлу, який обробляє processor
|
|
@@ -127,10 +163,15 @@ const baseParser = graphqlEslintPlugin.parser
|
|
|
127
163
|
*/
|
|
128
164
|
export function graphqlParseForESLintWithAnchor(code, options = {}) {
|
|
129
165
|
const filePath = options.filePath || ''
|
|
130
|
-
|
|
166
|
+
const parsed = baseParser.parseForESLint(code, {
|
|
131
167
|
...options,
|
|
132
168
|
filePath: graphQLConfigPathAnchor(filePath)
|
|
133
169
|
})
|
|
170
|
+
const sibs = parsed.services?.siblingOperations
|
|
171
|
+
if (sibs) {
|
|
172
|
+
parsed.services.siblingOperations = siblingOperationsWithoutNodeModules(sibs)
|
|
173
|
+
}
|
|
174
|
+
return parsed
|
|
134
175
|
}
|
|
135
176
|
|
|
136
177
|
/** Парсер для flat config (обгортка над graphql-eslint). */
|
package/index.js
CHANGED
|
@@ -2,8 +2,8 @@ import e18ePlugin from '@e18e/eslint-plugin'
|
|
|
2
2
|
import { fixupPluginRules } from '@eslint/compat'
|
|
3
3
|
import js from '@eslint/js'
|
|
4
4
|
import graphqlEslintPlugin from '@graphql-eslint/eslint-plugin'
|
|
5
|
-
import { graphqlCodefileProcessor, graphqlParserWithConfigAnchor } from './graphql-eslint-anchor.js'
|
|
6
5
|
import microsoftSdl from '@microsoft/eslint-plugin-sdl'
|
|
6
|
+
import { mergeProcessors } from 'eslint-merge-processors'
|
|
7
7
|
import { flatConfigs as importXFlatConfigs } from 'eslint-plugin-import-x'
|
|
8
8
|
import jsdocPlugin from 'eslint-plugin-jsdoc'
|
|
9
9
|
import { configs as jsoncConfigs } from 'eslint-plugin-jsonc'
|
|
@@ -14,15 +14,37 @@ import securityPlugin from 'eslint-plugin-security'
|
|
|
14
14
|
import sonarjsPlugin from 'eslint-plugin-sonarjs'
|
|
15
15
|
import unicornPlugin from 'eslint-plugin-unicorn'
|
|
16
16
|
import vuePlugin from 'eslint-plugin-vue'
|
|
17
|
-
import vueEslintParser from 'vue-eslint-parser'
|
|
18
17
|
import { configs as ymlConfigs } from 'eslint-plugin-yml'
|
|
19
|
-
import { mergeProcessors } from 'eslint-merge-processors'
|
|
20
18
|
import processorVueBlocks from 'eslint-processor-vue-blocks'
|
|
21
19
|
import globals from 'globals'
|
|
20
|
+
import vueEslintParser from 'vue-eslint-parser'
|
|
21
|
+
import { graphqlCodefileProcessor, graphqlParserWithConfigAnchor } from './graphql-eslint-anchor.js'
|
|
22
|
+
|
|
23
|
+
/** Витягнуті graphql-eslint документи: gql під `node_modules` не обробляються (sibling-фільтр у `graphql-eslint-anchor` уже прибирає залежності з унікальності імен; patterns `ignores` скорочують шум і час). */
|
|
24
|
+
const GRAPHQL_EXTRACTED_IGNORES = ['**/node_modules/**']
|
|
22
25
|
|
|
23
26
|
/** Glob-патерни файлів для eslint-plugin-unicorn (JS-подібні джерела; без сирих YAML/Markdown). */
|
|
24
27
|
const UNICORN_FILES = ['**/*.{js,mjs,cjs,vue}']
|
|
25
28
|
|
|
29
|
+
/** Узгоджені опції `no-unused-vars` для `.js` і Vue SFC (`eslint-plugin-oxlint` не вимикає це правило для `.vue`, тож oxlint CLI його там не покриває). */
|
|
30
|
+
const NO_UNUSED_VARS_RULE = ['error', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }]
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Частина ядра `eslint:recommended`, яку не вимикає `eslint-plugin-oxlint` flat/recommended (oxlint не заявляє заміну
|
|
34
|
+
* цих правил у ESLint) і яка не ввімкнена в oxlint за кореневим `.oxlintrc.json` — для `<script>` у `.vue` їх
|
|
35
|
+
* лишаємо на ESLint після oxlint. Решту з recommended для SFC покриває oxlint CLI з вашого `.oxlintrc.json`.
|
|
36
|
+
*/
|
|
37
|
+
const VUE_SCRIPT_ESLINT_RECOMMENDED_GAP_RULES = {
|
|
38
|
+
'getter-return': 'error',
|
|
39
|
+
'no-dupe-args': 'error',
|
|
40
|
+
'no-octal': 'error',
|
|
41
|
+
'no-undef': 'error',
|
|
42
|
+
'no-unreachable': 'error',
|
|
43
|
+
'no-useless-assignment': 'error',
|
|
44
|
+
'preserve-caught-error': 'error',
|
|
45
|
+
'no-unused-vars': NO_UNUSED_VARS_RULE
|
|
46
|
+
}
|
|
47
|
+
|
|
26
48
|
/** Пресет recommended `@e18e/eslint-plugin` (flat). */
|
|
27
49
|
// @ts-expect-error типізація плагіна не гарантує `configs.recommended`; у runtime поле є.
|
|
28
50
|
const e18eRecommendedFlat = /** @type {import('eslint').Linter.FlatConfig} */ (e18ePlugin.configs.recommended)
|
|
@@ -36,6 +58,7 @@ const GRAPHQL_EXTRACTED_DOCUMENT_FILES = ['**/*.graphql']
|
|
|
36
58
|
*/
|
|
37
59
|
const graphqlExtractedDocumentLint = {
|
|
38
60
|
files: GRAPHQL_EXTRACTED_DOCUMENT_FILES,
|
|
61
|
+
ignores: GRAPHQL_EXTRACTED_IGNORES,
|
|
39
62
|
languageOptions: {
|
|
40
63
|
parser: graphqlParserWithConfigAnchor
|
|
41
64
|
},
|
|
@@ -55,6 +78,7 @@ const graphqlExtractedDocumentLint = {
|
|
|
55
78
|
*/
|
|
56
79
|
const graphqlExtractedDocumentLintVueUniqueOperationOverride = {
|
|
57
80
|
files: ['**/*.vue/**/*.graphql'],
|
|
81
|
+
ignores: GRAPHQL_EXTRACTED_IGNORES,
|
|
58
82
|
rules: {
|
|
59
83
|
'@graphql-eslint/unique-operation-name': 'off'
|
|
60
84
|
}
|
|
@@ -122,7 +146,7 @@ const all = [
|
|
|
122
146
|
},
|
|
123
147
|
rules: {
|
|
124
148
|
...js.configs.recommended.rules,
|
|
125
|
-
'no-unused-vars':
|
|
149
|
+
'no-unused-vars': NO_UNUSED_VARS_RULE
|
|
126
150
|
}
|
|
127
151
|
},
|
|
128
152
|
// Unicorn правила (лише JS-подібні файли — узгоджено з блоком рекомендованих правил ESLint)
|
|
@@ -238,14 +262,9 @@ const vueAllVite = [
|
|
|
238
262
|
useQuery: 'readonly',
|
|
239
263
|
watch: 'readonly',
|
|
240
264
|
computed: 'readonly',
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
defineExpose: 'readonly',
|
|
245
|
-
withDefaults: 'readonly',
|
|
246
|
-
defineSlots: 'readonly',
|
|
247
|
-
defineModel: 'readonly',
|
|
248
|
-
defineOptions: 'readonly'
|
|
265
|
+
|
|
266
|
+
// Макроси `<script setup>` (джерело списку — `globals` / `vue` у vue-eslint-parser).
|
|
267
|
+
...globals.vue
|
|
249
268
|
}
|
|
250
269
|
}
|
|
251
270
|
}
|
|
@@ -332,6 +351,26 @@ function pushGraphqlVueMergedProcessorLast(result, dirs) {
|
|
|
332
351
|
})
|
|
333
352
|
}
|
|
334
353
|
|
|
354
|
+
/**
|
|
355
|
+
* Після oxlint додає для `.vue` правила з `eslint:recommended`, які не делегує `eslint-plugin-oxlint` і які
|
|
356
|
+
* не ввімкнені в oxlint за `.oxlintrc.json` (див. `VUE_SCRIPT_ESLINT_RECOMMENDED_GAP_RULES`).
|
|
357
|
+
* @param {import('eslint').Linter.FlatConfig[]} result масив конфігів
|
|
358
|
+
* @param {string[]} dirs кореневі директорії Vue-пакетів (ті самі аргументи dirs, що й у pushVueConfigs)
|
|
359
|
+
*/
|
|
360
|
+
function pushVueScriptEslintRecommendedGapsAfterOxlint(result, dirs) {
|
|
361
|
+
if (!dirs?.length) {
|
|
362
|
+
return
|
|
363
|
+
}
|
|
364
|
+
result.push({
|
|
365
|
+
name: 'nitra/vue-script-eslint-recommended-oxlint-gaps',
|
|
366
|
+
files: dirs.map(name => `${name}/**/*.vue`),
|
|
367
|
+
// Правила з `eslint:recommended` + `no-unused-vars` з опціями; тип `RuleConfig` у ESLint 10 вимагає кортеж, тож подвійне приведення.
|
|
368
|
+
rules: /** @type {import('eslint').Linter.RulesRecord} */ (
|
|
369
|
+
/** @type {unknown} */ (VUE_SCRIPT_ESLINT_RECOMMENDED_GAP_RULES)
|
|
370
|
+
)
|
|
371
|
+
})
|
|
372
|
+
}
|
|
373
|
+
|
|
335
374
|
/**
|
|
336
375
|
* Додає до result конфіги для Vue-проєктів (vite, .vue, .js).
|
|
337
376
|
* @param {import('eslint').Linter.FlatConfig[]} result масив конфігів
|
|
@@ -410,6 +449,7 @@ export function getConfig(params = { node: [], vue: [], vue2: [] }) {
|
|
|
410
449
|
|
|
411
450
|
if (graphqlVueDirsLast.length) {
|
|
412
451
|
pushGraphqlVueMergedProcessorLast(result, graphqlVueDirsLast)
|
|
452
|
+
pushVueScriptEslintRecommendedGapsAfterOxlint(result, graphqlVueDirsLast)
|
|
413
453
|
}
|
|
414
454
|
|
|
415
455
|
return result
|