@nitra/cursor 1.8.144 → 1.8.147

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.
@@ -12,6 +12,9 @@
12
12
  * повторно використовувати між запитами.
13
13
  * - небезпечні “динамічні списки” в SQL, коли в TemplateLiteral/TaggedTemplateExpression
14
14
  * підставляють рядки, зібрані через `.join(',')` (типово для `IN (...)` або `VALUES (...)`).
15
+ * - підстановки `IN (${expr})`, де `expr` не пройшов числовий парсер (parseInt/Number/BigInt
16
+ * /parseFloat або унарний `+`) і не є літеральним масивом чисел — навіть у tagged template
17
+ * це додатковий шар захисту від SQL injection (див. js-mssql.mdc).
15
18
  *
16
19
  * Семантика береться з **oxc-parser** по AST, щоб не покладатися на regex.
17
20
  * Якщо файл не парситься або містить синтаксичні помилки — повертаємо порожній
@@ -21,6 +24,8 @@ import { parseSync } from 'oxc-parser'
21
24
 
22
25
  const SOURCE_FILE_RE = /\.([cm]?[jt]sx?)$/
23
26
  const SQL_LIST_CONTEXT_RE = /\b(in|values)\b\s*\(/iu
27
+ const IN_PLACEHOLDER_END_RE = /\bin\s*\(\s*$/iu
28
+ const NUMERIC_PARSE_FN_NAMES = new Set(['parseInt', 'parseFloat', 'Number', 'BigInt'])
24
29
 
25
30
  /**
26
31
  * Мова для Oxc за шляхом файлу (розширення).
@@ -302,7 +307,6 @@ export function findSharedMssqlRequestInText(content, virtualPath = 'scan.ts') {
302
307
  *
303
308
  * Цей патерн небезпечний навіть якщо зовні використовується tagged template, бо в запит
304
309
  * потрапляє “готовий шматок SQL”, а не параметризовані значення.
305
- *
306
310
  * @param {string} content вихідний код
307
311
  * @param {string} [virtualPath] шлях для вибору `lang`
308
312
  * @returns {{ line: number, snippet: string }[]} список порушень
@@ -346,6 +350,189 @@ export function findUnsafeMssqlDynamicSqlListInText(content, virtualPath = 'scan
346
350
  return out
347
351
  }
348
352
 
353
+ /**
354
+ * Чи елементи літерального масиву — лише числові (numeric/bigint) літерали.
355
+ * Такі масиви безпечні в `IN (...)` навіть без явного парсера.
356
+ * @param {unknown} node AST node
357
+ * @returns {boolean} true, якщо це непорожній масив суто числових літералів
358
+ */
359
+ function isLiteralNumericArrayExpression(node) {
360
+ if (!node || typeof node !== 'object' || node.type !== 'ArrayExpression') return false
361
+ const elements = node.elements
362
+ if (!Array.isArray(elements) || elements.length === 0) return false
363
+ return elements.every(el => {
364
+ if (!el || typeof el !== 'object') return false
365
+ if (el.type === 'NumericLiteral' || el.type === 'BigIntLiteral') return true
366
+ if (el.type === 'Literal' && (typeof el.value === 'number' || typeof el.value === 'bigint')) {
367
+ return true
368
+ }
369
+ return false
370
+ })
371
+ }
372
+
373
+ /**
374
+ * Чи це безпосередній виклик числового парсера (parseInt/parseFloat/Number/BigInt)
375
+ * або обʼєктний доступ до них (наприклад `Number.parseInt(...)`).
376
+ * @param {Record<string, unknown>} node AST CallExpression
377
+ * @returns {boolean} true, якщо callee — числовий парсер
378
+ */
379
+ function isNumericParseCallExpression(node) {
380
+ if (node.type !== 'CallExpression') return false
381
+ const callee = node.callee
382
+ if (!callee) return false
383
+ if (callee.type === 'Identifier' && NUMERIC_PARSE_FN_NAMES.has(callee.name)) return true
384
+ if (callee.type === 'MemberExpression' && !callee.computed) {
385
+ const prop = callee.property
386
+ return !!prop && prop.type === 'Identifier' && NUMERIC_PARSE_FN_NAMES.has(prop.name)
387
+ }
388
+ return false
389
+ }
390
+
391
+ /**
392
+ * Чи містить піддерево виклик числового парсера (parseInt/parseFloat/Number/BigInt)
393
+ * або унарний `+` (приведення до Number). Це сигнал, що значення гарантовано числове
394
+ * і не може містити SQL-метасимволи.
395
+ * @param {unknown} node AST node
396
+ * @returns {boolean} true, якщо знайдено числовий парсер у піддереві
397
+ */
398
+ function subtreeHasNumericParseCall(node) {
399
+ if (!node || typeof node !== 'object') return false
400
+ if (Array.isArray(node)) return node.some(item => subtreeHasNumericParseCall(item))
401
+
402
+ if (isNumericParseCallExpression(node)) return true
403
+ if (node.type === 'UnaryExpression' && node.operator === '+') return true
404
+
405
+ for (const key of Object.keys(node)) {
406
+ if (key === 'parent') continue
407
+ const v = node[key]
408
+ if (v && typeof v === 'object' && subtreeHasNumericParseCall(v)) return true
409
+ }
410
+ return false
411
+ }
412
+
413
+ /**
414
+ * Збирає всі VariableDeclarator-вузли в AST (для трасування Identifier-ів до їх init).
415
+ * @param {unknown} programNode AST root (Program)
416
+ * @returns {Array<Record<string, unknown>>} список VariableDeclarator-ів
417
+ */
418
+ function collectVariableDeclarators(programNode) {
419
+ /** @type {Array<Record<string, unknown>>} */
420
+ const out = []
421
+ walkAstWithAncestors(programNode, [], node => {
422
+ if (node.type === 'VariableDeclarator') out.push(node)
423
+ })
424
+ return out
425
+ }
426
+
427
+ /**
428
+ * Чи виглядає вираз, який підставляється в `IN (${...})`, як «безпечно розпарсений»:
429
+ * - літеральний масив чисел;
430
+ * - саме піддерево містить виклик числового парсера (parseInt/Number/BigInt/parseFloat/+x);
431
+ * - Identifier, чий init у файлі рекурсивно задовольняє ці умови.
432
+ *
433
+ * Якщо для Identifier немає видимого init (наприклад параметр функції чи import),
434
+ * вираз вважається не парсованим — потрібен явний парсер на місці підстановки.
435
+ * @param {unknown} expr вираз з template.expressions
436
+ * @param {Array<Record<string, unknown>>} declarators VariableDeclarator-и файлу
437
+ * @param {Set<string>} [seen] іменa Identifier-ів, що вже трасуються (анти-цикл)
438
+ * @returns {boolean} true, якщо вираз можна вважати безпечно числовим
439
+ */
440
+ function isInListExpressionParsed(expr, declarators, seen = new Set()) {
441
+ if (!expr || typeof expr !== 'object') return false
442
+ if (isLiteralNumericArrayExpression(expr)) return true
443
+ if (subtreeHasNumericParseCall(expr)) return true
444
+
445
+ if (expr.type === 'Identifier' && typeof expr.name === 'string') {
446
+ if (seen.has(expr.name)) return false
447
+ const nextSeen = new Set(seen)
448
+ nextSeen.add(expr.name)
449
+ const inits = declarators
450
+ .filter(d => {
451
+ const id = d.id
452
+ return (
453
+ !!id &&
454
+ typeof id === 'object' &&
455
+ id.type === 'Identifier' &&
456
+ id.name === expr.name &&
457
+ !!d.init
458
+ )
459
+ })
460
+ .map(d => d.init)
461
+ if (inits.length === 0) return false
462
+ return inits.every(init => isInListExpressionParsed(init, declarators, nextSeen))
463
+ }
464
+
465
+ return false
466
+ }
467
+
468
+ /**
469
+ * Сирий текст quasi-елемента TemplateLiteral на позиції перед expressions[i].
470
+ * @param {unknown} q quasi-елемент TemplateLiteral
471
+ * @returns {string} `q.value.raw` або порожній рядок, якщо структура не підходить
472
+ */
473
+ function quasiRawText(q) {
474
+ return q && typeof q === 'object' && q.value && typeof q.value === 'object' && typeof q.value.raw === 'string'
475
+ ? q.value.raw
476
+ : ''
477
+ }
478
+
479
+ /**
480
+ * Збирає порушення для одного TemplateLiteral вузла: знаходить expressions, що
481
+ * стоять одразу після `IN (` без числового парсера значень.
482
+ * @param {Record<string, unknown>} node TemplateLiteral
483
+ * @param {string} content вихідний код
484
+ * @param {Array<Record<string, unknown>>} declarators VariableDeclarator-и для трасування
485
+ * @param {{ line: number, snippet: string }[]} out буфер результатів
486
+ */
487
+ function collectInListUnparsedFromTemplate(node, content, declarators, out) {
488
+ if (node.type !== 'TemplateLiteral') return
489
+ const quasis = node.quasis
490
+ const expressions = node.expressions
491
+ if (!Array.isArray(quasis) || !Array.isArray(expressions) || expressions.length === 0) return
492
+
493
+ for (const [i, expr] of expressions.entries()) {
494
+ if (!IN_PLACEHOLDER_END_RE.test(quasiRawText(quasis[i]))) continue
495
+ if (!expr || typeof expr !== 'object') continue
496
+ if (isJoinCall(expr)) continue
497
+ if (isInListExpressionParsed(expr, declarators)) continue
498
+
499
+ const startOffset = typeof expr.start === 'number' ? expr.start : node.start
500
+ out.push({
501
+ line: offsetToLine(content, startOffset),
502
+ snippet: normalizeSnippet(content.slice(node.start, node.end))
503
+ })
504
+ }
505
+ }
506
+
507
+ /**
508
+ * Знаходить підстановки IN (вираз) у TemplateLiteral, де вираз не пройшов числовий парсер.
509
+ *
510
+ * Навіть у безпечному tagged template pool.request().query краще явно парсити значення (parseInt,
511
+ * Number, BigInt, parseFloat) та фільтрувати NaN. Див. також findUnsafeMssqlDynamicSqlListInText для
512
+ * випадків arr.join у списках.
513
+ * @param {string} content вихідний код
514
+ * @param {string} [virtualPath] шлях для вибору мови парсера (lang)
515
+ * @returns {{ line: number, snippet: string }[]} список порушень
516
+ */
517
+ export function findUnsafeMssqlInListUnparsedInText(content, virtualPath = 'scan.ts') {
518
+ const lang = langFromPath(virtualPath || 'scan.ts')
519
+ let result
520
+ try {
521
+ result = parseSync(virtualPath, content, { lang, sourceType: 'module' })
522
+ } catch {
523
+ return []
524
+ }
525
+ if (result.errors?.length) return []
526
+
527
+ const declarators = collectVariableDeclarators(result.program)
528
+
529
+ /** @type {{ line: number, snippet: string }[]} */
530
+ const out = []
531
+ walkAstWithAncestors(result.program, [], node => collectInListUnparsedFromTemplate(node, content, declarators, out))
532
+
533
+ return out
534
+ }
535
+
349
536
  /**
350
537
  * Чи сканувати цей файл за розширенням (JS/TS-сім'я).
351
538
  * @param {string} relativePathPosix відносний шлях (posix)
@@ -0,0 +1,27 @@
1
+ {
2
+ "$schema": "./node_modules/oxlint/configuration_schema.json",
3
+ "plugins": ["unicorn", "oxc", "import", "jsdoc", "promise", "node"],
4
+ "jsPlugins": ["@e18e/eslint-plugin"],
5
+ "categories": {},
6
+ "rules": {},
7
+ "settings": {
8
+ "next": {
9
+ "rootDir": []
10
+ },
11
+ "jsdoc": {
12
+ "ignorePrivate": false,
13
+ "ignoreInternal": false,
14
+ "ignoreReplacesDocs": true,
15
+ "overrideReplacesDocs": true,
16
+ "augmentsExtendsReplacesDocs": false,
17
+ "implementsReplacesDocs": false,
18
+ "exemptDestructuredRootsFromChecks": false,
19
+ "tagNamePreference": {}
20
+ }
21
+ },
22
+ "env": {
23
+ "builtin": true
24
+ },
25
+ "globals": {},
26
+ "ignorePatterns": []
27
+ }
@@ -0,0 +1,387 @@
1
+ {
2
+ "$schema": "./node_modules/oxlint/configuration_schema.json",
3
+ "plugins": ["unicorn", "oxc", "import", "jsdoc", "promise", "node"],
4
+ "jsPlugins": ["@e18e/eslint-plugin"],
5
+ "categories": {},
6
+ "rules": {
7
+ "e18e/prefer-includes": "error",
8
+ "array-callback-return": "deny",
9
+ "no-new-wrappers": "deny",
10
+ "import/no-named-as-default": "deny",
11
+ "oxc/uninvoked-array-callback": "deny",
12
+ "typescript/no-non-null-assertion": "deny",
13
+ "unicorn/prefer-date-now": "deny",
14
+ "no-obj-calls": "deny",
15
+ "default-case-last": "deny",
16
+ "import/no-webpack-loader-syntax": "deny",
17
+ "promise/no-promise-in-callback": "deny",
18
+ "typescript/no-unnecessary-type-constraint": "deny",
19
+ "unicorn/prefer-dom-node-remove": "deny",
20
+ "for-direction": "deny",
21
+ "no-prototype-builtins": "deny",
22
+ "typescript/no-useless-empty-export": "deny",
23
+ "unicorn/prefer-includes": "deny",
24
+ "guard-for-in": "deny",
25
+ "no-restricted-globals": "deny",
26
+ "promise/prefer-await-to-then": "off",
27
+ "typescript/prefer-as-const": "deny",
28
+ "unicorn/prefer-math-trunc": "deny",
29
+ "no-self-assign": "deny",
30
+ "max-params": "off",
31
+ "react/button-has-type": "deny",
32
+ "typescript/prefer-function-type": "deny",
33
+ "unicorn/prefer-native-coercion-functions": "deny",
34
+ "no-extra-label": "deny",
35
+ "no-shadow-restricted-names": "deny",
36
+ "react/iframe-missing-sandbox": "deny",
37
+ "typescript/prefer-ts-expect-error": "deny",
38
+ "unicorn/prefer-number-properties": "off",
39
+ "no-labels": "deny",
40
+ "no-ternary": "off",
41
+ "react/jsx-key": "deny",
42
+ "unicorn/consistent-empty-array-spread": "deny",
43
+ "unicorn/prefer-query-selector": "deny",
44
+ "no-object-constructor": "deny",
45
+ "react/jsx-no-script-url": "deny",
46
+ "unicorn/empty-brace-spaces": "deny",
47
+ "unicorn/prefer-set-has": "deny",
48
+ "no-array-constructor": "deny",
49
+ "react/jsx-no-useless-fragment": "deny",
50
+ "unicorn/explicit-length-check": "off",
51
+ "unicorn/prefer-string-replace-all": "deny",
52
+ "no-bitwise": "deny",
53
+ "no-unsafe-optional-chaining": "deny",
54
+ "react/no-children-prop": "deny",
55
+ "unicorn/no-abusive-eslint-disable": "deny",
56
+ "unicorn/prefer-string-trim-start-end": "deny",
57
+ "no-class-assign": "deny",
58
+ "no-unused-private-class-members": "deny",
59
+ "react/no-direct-mutation-state": "deny",
60
+ "unicorn/no-array-reduce": "deny",
61
+ "unicorn/require-array-join-separator": "deny",
62
+ "no-console": "off",
63
+ "no-useless-concat": "deny",
64
+ "react/no-render-return-value": "deny",
65
+ "unicorn/no-console-spaces": "deny",
66
+ "unicorn/text-encoding-identifier-case": "deny",
67
+ "no-constant-condition": "deny",
68
+ "no-useless-rename": "deny",
69
+ "react/no-unescaped-entities": "deny",
70
+ "unicorn/no-hex-escape": "deny",
71
+ "no-control-regex": "deny",
72
+ "no-with": "deny",
73
+ "react/react-in-jsx-scope": "deny",
74
+ "unicorn/no-length-as-slice-end": "deny",
75
+ "no-div-regex": "deny",
76
+ "prefer-numeric-literals": "deny",
77
+ "react/self-closing-comp": "deny",
78
+ "unicorn/no-negation-in-equality-check": "deny",
79
+ "no-dupe-keys": "deny",
80
+ "prefer-rest-params": "deny",
81
+ "unicorn/no-new-buffer": "deny",
82
+ "no-empty-character-class": "deny",
83
+ "require-await": "deny",
84
+ "node/no-exports-assign": "deny",
85
+ "unicorn/no-process-exit": "deny",
86
+ "no-empty-static-block": "deny",
87
+ "sort-keys": "off",
88
+ "oxc/bad-array-method-on-arguments": "deny",
89
+ "unicorn/no-thenable": "deny",
90
+ "typescript/ban-ts-comment": "deny",
91
+ "no-eval": "deny",
92
+ "unicode-bom": "deny",
93
+ "jsdoc/check-access": "deny",
94
+ "oxc/bad-comparison-sequence": "deny",
95
+ "unicorn/no-unnecessary-await": "deny",
96
+ "typescript/consistent-generic-constructors": "deny",
97
+ "no-extra-boolean-cast": "deny",
98
+ "vars-on-top": "deny",
99
+ "jsdoc/empty-tags": "deny",
100
+ "oxc/bad-replace-all-arg": "deny",
101
+ "unicorn/no-useless-fallback-in-spread": "deny",
102
+ "no-global-assign": "deny",
103
+ "jsdoc/require-param": "deny",
104
+ "oxc/erasing-op": "deny",
105
+ "unicorn/no-useless-spread": "deny",
106
+ "typescript/no-confusing-non-null-assertion": "deny",
107
+ "no-invalid-regexp": "deny",
108
+ "import/no-namespace": "off",
109
+ "jsdoc/require-param-type": "deny",
110
+ "oxc/no-accumulating-spread": "deny",
111
+ "typescript/no-empty-interface": "deny",
112
+ "unicorn/no-zero-fractions": "deny",
113
+ "import/namespace": "deny",
114
+ "jsdoc/require-property-name": "deny",
115
+ "no-label-var": "deny",
116
+ "typescript/no-extra-non-null-assertion": "deny",
117
+ "oxc/no-barrel-file": "deny",
118
+ "unicorn/prefer-spread": "deny",
119
+ "no-negated-condition": "deny",
120
+ "import/no-cycle": "deny",
121
+ "jsdoc/require-returns-description": "deny",
122
+ "typescript/no-misused-new": "deny",
123
+ "oxc/no-optional-chaining": "off",
124
+ "unicorn/prefer-array-flat-map": "deny",
125
+ "no-new-native-nonconstructor": "deny",
126
+ "import/no-dynamic-require": "deny",
127
+ "oxc/only-used-in-recursion": "deny",
128
+ "typescript/no-non-null-asserted-optional-chain": "deny",
129
+ "unicorn/prefer-code-point": "deny",
130
+ "default-case": "off",
131
+ "no-nonoctal-decimal-escape": "deny",
132
+ "import/no-self-import": "deny",
133
+ "promise/catch-or-return": "deny",
134
+ "typescript/no-this-alias": "deny",
135
+ "unicorn/prefer-dom-node-dataset": "deny",
136
+ "eqeqeq": "deny",
137
+ "no-proto": "deny",
138
+ "promise/no-new-statics": "deny",
139
+ "typescript/no-unsafe-function-type": "deny",
140
+ "unicorn/prefer-event-target": "deny",
141
+ "no-regex-spaces": "deny",
142
+ "promise/prefer-await-to-callbacks": "off",
143
+ "typescript/no-wrapper-object-types": "deny",
144
+ "unicorn/prefer-math-min-max": "deny",
145
+ "max-lines": "off",
146
+ "no-script-url": "deny",
147
+ "promise/valid-params": "deny",
148
+ "typescript/prefer-for-of": "deny",
149
+ "unicorn/prefer-modern-math-apis": "deny",
150
+ "no-useless-call": "deny",
151
+ "no-setter-return": "deny",
152
+ "typescript/prefer-namespace-keyword": "deny",
153
+ "unicorn/prefer-node-protocol": "deny",
154
+ "no-nested-ternary": "off",
155
+ "no-template-curly-in-string": "deny",
156
+ "react/jsx-curly-brace-presence": "deny",
157
+ "unicorn/catch-error-name": "deny",
158
+ "unicorn/prefer-prototype-methods": "deny",
159
+ "no-throw-literal": "deny",
160
+ "react/jsx-no-duplicate-props": "deny",
161
+ "unicorn/consistent-function-scoping": "deny",
162
+ "unicorn/prefer-regexp-test": "deny",
163
+ "no-alert": "deny",
164
+ "no-unexpected-multiline": "deny",
165
+ "react/jsx-no-undef": "deny",
166
+ "unicorn/escape-case": "deny",
167
+ "unicorn/prefer-string-raw": "deny",
168
+ "no-await-in-loop": "off",
169
+ "no-unsafe-negation": "deny",
170
+ "react/no-array-index-key": "deny",
171
+ "unicorn/new-for-builtins": "deny",
172
+ "unicorn/prefer-string-starts-ends-with": "deny",
173
+ "no-case-declarations": "deny",
174
+ "no-unused-labels": "deny",
175
+ "react/no-danger": "deny",
176
+ "unicorn/no-array-for-each": "deny",
177
+ "unicorn/prefer-type-error": "deny",
178
+ "no-cond-assign": "deny",
179
+ "no-useless-catch": "deny",
180
+ "react/no-is-mounted": "deny",
181
+ "unicorn/no-await-in-promise-methods": "deny",
182
+ "unicorn/switch-case-braces": "deny",
183
+ "no-constant-binary-expression": "deny",
184
+ "no-useless-escape": "deny",
185
+ "react/no-string-refs": "deny",
186
+ "unicorn/no-empty-file": "deny",
187
+ "no-void": "deny",
188
+ "unicorn/no-invalid-remove-event-listener": "deny",
189
+ "react/prefer-es6-class": "deny",
190
+ "no-delete-var": "deny",
191
+ "prefer-exponentiation-operator": "deny",
192
+ "react/rules-of-hooks": "deny",
193
+ "unicorn/no-magic-array-flat-depth": "deny",
194
+ "no-dupe-else-if": "deny",
195
+ "prefer-object-spread": "deny",
196
+ "react/void-dom-elements-no-children": "deny",
197
+ "unicorn/no-new-array": "deny",
198
+ "no-else-return": "deny",
199
+ "radix": "off",
200
+ "unicorn/no-object-as-default-parameter": "deny",
201
+ "no-empty-pattern": "deny",
202
+ "sort-imports": "off",
203
+ "oxc/approx-constant": "deny",
204
+ "typescript/array-type": "deny",
205
+ "unicorn/no-static-only-class": "deny",
206
+ "no-eq-null": "deny",
207
+ "symbol-description": "deny",
208
+ "oxc/bad-char-at-comparison": "deny",
209
+ "typescript/ban-types": "deny",
210
+ "unicorn/no-typeof-undefined": "deny",
211
+ "no-extend-native": "deny",
212
+ "valid-typeof": "deny",
213
+ "jsdoc/check-tag-names": "deny",
214
+ "oxc/bad-object-literal-comparison": "deny",
215
+ "typescript/consistent-type-definitions": "deny",
216
+ "unicorn/no-unreadable-iife": "deny",
217
+ "no-func-assign": "deny",
218
+ "import/default": "deny",
219
+ "jsdoc/no-defaults": "deny",
220
+ "oxc/double-comparisons": "deny",
221
+ "typescript/no-inferrable-types": "deny",
222
+ "unicorn/no-useless-promise-resolve-reject": "deny",
223
+ "no-inner-declarations": "deny",
224
+ "import/no-named-default": "deny",
225
+ "oxc/missing-throw": "deny",
226
+ "jsdoc/require-param-name": "deny",
227
+ "typescript/no-dynamic-delete": "deny",
228
+ "unicorn/no-useless-undefined": "deny",
229
+ "no-iterator": "deny",
230
+ "jsdoc/require-property-description": "deny",
231
+ "oxc/no-async-endpoint-handlers": "deny",
232
+ "typescript/no-explicit-any": "deny",
233
+ "unicorn/numeric-separators-style": "off",
234
+ "no-magic-numbers": "off",
235
+ "import/no-commonjs": "off",
236
+ "jsdoc/require-returns": "deny",
237
+ "typescript/no-import-type-side-effects": "deny",
238
+ "unicorn/prefer-array-flat": "deny",
239
+ "no-new-func": "deny",
240
+ "import/no-duplicates": "deny",
241
+ "jsdoc/require-yields": "deny",
242
+ "oxc/number-arg-out-of-range": "deny",
243
+ "typescript/no-non-null-asserted-nullish-coalescing": "deny",
244
+ "unicorn/prefer-blob-reading-methods": "deny",
245
+ "no-new": "deny",
246
+ "import/no-named-as-default-member": "off",
247
+ "promise/avoid-new": "deny",
248
+ "typescript/no-require-imports": "deny",
249
+ "unicorn/prefer-dom-node-append": "deny",
250
+ "default-param-last": "deny",
251
+ "no-plusplus": "off",
252
+ "import/unambiguous": "off",
253
+ "promise/no-callback-in-promise": "deny",
254
+ "typescript/no-unsafe-declaration-merging": "deny",
255
+ "unicorn/prefer-dom-node-text-content": "deny",
256
+ "func-names": "off",
257
+ "no-redeclare": "deny",
258
+ "promise/param-names": "deny",
259
+ "typescript/no-var-requires": "deny",
260
+ "unicorn/prefer-logical-operator-over-ternary": "deny",
261
+ "max-classes-per-file": "deny",
262
+ "no-return-assign": "deny",
263
+ "promise/spec-only": "deny",
264
+ "typescript/prefer-enum-initializers": "deny",
265
+ "unicorn/prefer-modern-dom-apis": "deny",
266
+ "new-cap": "off",
267
+ "no-self-compare": "deny",
268
+ "react/checked-requires-onchange-or-readonly": "deny",
269
+ "typescript/prefer-literal-enum-member": "deny",
270
+ "unicorn/prefer-negative-index": "deny",
271
+ "no-multi-assign": "deny",
272
+ "no-sparse-arrays": "deny",
273
+ "typescript/triple-slash-reference": "deny",
274
+ "react/jsx-boolean-value": "deny",
275
+ "unicorn/prefer-optional-catch-binding": "deny",
276
+ "no-lone-blocks": "deny",
277
+ "no-this-before-super": "deny",
278
+ "react/jsx-no-comment-textnodes": "deny",
279
+ "unicorn/consistent-existence-index-check": "deny",
280
+ "unicorn/prefer-reflect-apply": "deny",
281
+ "no-duplicate-imports": "deny",
282
+ "no-undefined": "off",
283
+ "react/jsx-no-target-blank": "deny",
284
+ "unicorn/prefer-set-size": "deny",
285
+ "unicorn/error-message": "deny",
286
+ "no-async-promise-executor": "deny",
287
+ "no-unsafe-finally": "deny",
288
+ "react/jsx-props-no-spread-multi": "deny",
289
+ "unicorn/filename-case": "off",
290
+ "unicorn/prefer-string-slice": "deny",
291
+ "no-caller": "deny",
292
+ "no-unused-expressions": "deny",
293
+ "react/no-danger-with-children": "deny",
294
+ "unicorn/no-anonymous-default-export": "off",
295
+ "unicorn/prefer-structured-clone": "deny",
296
+ "no-compare-neg-zero": "deny",
297
+ "no-unused-vars": "deny",
298
+ "react/no-find-dom-node": "deny",
299
+ "unicorn/no-await-expression-member": "deny",
300
+ "unicorn/require-number-to-fixed-digits-argument": "deny",
301
+ "no-const-assign": "deny",
302
+ "no-useless-constructor": "deny",
303
+ "react/no-set-state": "deny",
304
+ "unicorn/no-document-cookie": "deny",
305
+ "unicorn/throw-new-error": "deny",
306
+ "no-constructor-return": "deny",
307
+ "no-var": "deny",
308
+ "react/no-unknown-property": "deny",
309
+ "unicorn/no-instanceof-array": "deny",
310
+ "no-debugger": "deny",
311
+ "prefer-promise-reject-errors": "deny",
312
+ "unicorn/no-lonely-if": "deny",
313
+ "no-dupe-class-members": "deny",
314
+ "prefer-object-has-own": "deny",
315
+ "react/style-prop-object": "deny",
316
+ "unicorn/no-nested-ternary": "off",
317
+ "no-duplicate-case": "deny",
318
+ "prefer-spread": "deny",
319
+ "unicorn/no-null": "off",
320
+ "no-empty-function": "deny",
321
+ "require-yield": "deny",
322
+ "node/no-new-require": "deny",
323
+ "typescript/adjacent-overload-signatures": "deny",
324
+ "unicorn/no-single-promise-in-promise-methods": "deny",
325
+ "no-empty": "deny",
326
+ "sort-vars": "deny",
327
+ "oxc/bad-bitwise-operator": "deny",
328
+ "typescript/ban-tslint-comment": "deny",
329
+ "unicorn/no-this-assignment": "deny",
330
+ "no-ex-assign": "deny",
331
+ "use-isnan": "deny",
332
+ "jsdoc/check-property-names": "deny",
333
+ "oxc/bad-min-max-func": "deny",
334
+ "typescript/consistent-indexed-object-style": "deny",
335
+ "unicorn/no-unreadable-array-destructuring": "deny",
336
+ "no-fallthrough": "deny",
337
+ "yoda": "deny",
338
+ "jsdoc/implements-on-classes": "deny",
339
+ "oxc/const-comparisons": "deny",
340
+ "unicorn/no-useless-length-check": "deny",
341
+ "typescript/explicit-function-return-type": "deny",
342
+ "no-import-assign": "deny",
343
+ "import/first": "deny",
344
+ "jsdoc/require-param-description": "deny",
345
+ "typescript/no-duplicate-enum-values": "deny",
346
+ "oxc/misrefactored-assign-op": "deny",
347
+ "unicorn/no-useless-switch-case": "deny",
348
+ "no-irregular-whitespace": "deny",
349
+ "import/max-dependencies": "off",
350
+ "jsdoc/require-property": "deny",
351
+ "oxc/no-async-await": "off",
352
+ "typescript/no-empty-object-type": "deny",
353
+ "unicorn/number-literal-case": "deny",
354
+ "no-loss-of-precision": "deny",
355
+ "import/no-amd": "deny",
356
+ "jsdoc/require-property-type": "deny",
357
+ "oxc/no-const-enum": "deny",
358
+ "typescript/no-extraneous-class": "deny",
359
+ "unicorn/prefer-add-event-listener": "deny",
360
+ "no-multi-str": "deny",
361
+ "import/no-default-export": "off",
362
+ "jsdoc/require-returns-type": "deny",
363
+ "oxc/no-rest-spread-properties": "off",
364
+ "typescript/no-namespace": "deny",
365
+ "unicorn/prefer-array-some": "deny"
366
+ },
367
+ "settings": {
368
+ "next": {
369
+ "rootDir": []
370
+ },
371
+ "jsdoc": {
372
+ "ignorePrivate": false,
373
+ "ignoreInternal": false,
374
+ "ignoreReplacesDocs": true,
375
+ "overrideReplacesDocs": true,
376
+ "augmentsExtendsReplacesDocs": false,
377
+ "implementsReplacesDocs": false,
378
+ "exemptDestructuredRootsFromChecks": false,
379
+ "tagNamePreference": {}
380
+ }
381
+ },
382
+ "env": {
383
+ "builtin": true
384
+ },
385
+ "globals": {},
386
+ "ignorePatterns": []
387
+ }