@blumintinc/eslint-plugin-blumint 1.12.6 → 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 (258) hide show
  1. package/README.md +171 -99
  2. package/lib/index.js +300 -17
  3. package/lib/rules/array-methods-this-context.js +20 -2
  4. package/lib/rules/avoid-utils-directory.js +11 -2
  5. package/lib/rules/class-methods-read-top-to-bottom.js +24 -5
  6. package/lib/rules/consistent-callback-naming.js +1 -1
  7. package/lib/rules/dynamic-https-errors.d.ts +3 -1
  8. package/lib/rules/dynamic-https-errors.js +48 -11
  9. package/lib/rules/enforce-assert-safe-object-key.d.ts +8 -0
  10. package/lib/rules/{enforce-assertSafe-object-key.js → enforce-assert-safe-object-key.js} +52 -96
  11. package/lib/rules/enforce-assert-throws.d.ts +3 -1
  12. package/lib/rules/enforce-assert-throws.js +493 -51
  13. package/lib/rules/enforce-boolean-naming-prefixes.d.ts +3 -1
  14. package/lib/rules/enforce-boolean-naming-prefixes.js +820 -39
  15. package/lib/rules/enforce-callable-types.js +4 -4
  16. package/lib/rules/enforce-callback-memo.js +143 -18
  17. package/lib/rules/enforce-centralized-mock-firestore.js +5 -2
  18. package/lib/rules/enforce-console-error.d.ts +3 -0
  19. package/lib/rules/enforce-console-error.js +278 -0
  20. package/lib/rules/enforce-css-media-queries.js +24 -46
  21. package/lib/rules/enforce-dynamic-file-naming.d.ts +2 -0
  22. package/lib/rules/enforce-dynamic-file-naming.js +53 -28
  23. package/lib/rules/enforce-dynamic-firebase-imports.js +100 -19
  24. package/lib/rules/enforce-dynamic-imports.js +1 -1
  25. package/lib/rules/enforce-early-destructuring.d.ts +2 -0
  26. package/lib/rules/enforce-early-destructuring.js +980 -0
  27. package/lib/rules/enforce-empty-object-check.d.ts +11 -0
  28. package/lib/rules/enforce-empty-object-check.js +502 -0
  29. package/lib/rules/enforce-exported-function-types.js +4 -4
  30. package/lib/rules/enforce-fieldpath-syntax-in-docsetter.d.ts +2 -0
  31. package/lib/rules/enforce-fieldpath-syntax-in-docsetter.js +262 -0
  32. package/lib/rules/enforce-firestore-doc-ref-generic.js +350 -3
  33. package/lib/rules/enforce-firestore-facade.js +349 -157
  34. package/lib/rules/enforce-firestore-rules-get-access.d.ts +3 -0
  35. package/lib/rules/enforce-firestore-rules-get-access.js +109 -0
  36. package/lib/rules/enforce-firestore-set-merge.js +3 -4
  37. package/lib/rules/enforce-global-constants.d.ts +4 -1
  38. package/lib/rules/enforce-global-constants.js +240 -12
  39. package/lib/rules/enforce-identifiable-firestore-type.js +108 -58
  40. package/lib/rules/enforce-memoize-async.d.ts +2 -1
  41. package/lib/rules/enforce-memoize-async.js +92 -27
  42. package/lib/rules/enforce-memoize-getters.d.ts +3 -0
  43. package/lib/rules/enforce-memoize-getters.js +147 -0
  44. package/lib/rules/enforce-microdiff.js +3 -2
  45. package/lib/rules/enforce-object-literal-as-const.js +4 -4
  46. package/lib/rules/enforce-positive-naming.js +9 -7
  47. package/lib/rules/enforce-props-argument-name.d.ts +2 -7
  48. package/lib/rules/enforce-props-argument-name.js +165 -151
  49. package/lib/rules/enforce-props-naming-consistency.d.ts +2 -0
  50. package/lib/rules/enforce-props-naming-consistency.js +145 -0
  51. package/lib/rules/enforce-querykey-ts.d.ts +9 -0
  52. package/lib/rules/enforce-querykey-ts.js +274 -0
  53. package/lib/rules/enforce-safe-stringify.js +1 -1
  54. package/lib/rules/enforce-serializable-params.js +3 -3
  55. package/lib/rules/enforce-singular-type-names.js +10 -6
  56. package/lib/rules/enforce-stable-hash-spread-props.d.ts +13 -0
  57. package/lib/rules/enforce-stable-hash-spread-props.js +342 -0
  58. package/lib/rules/enforce-storage-context.d.ts +9 -0
  59. package/lib/rules/enforce-storage-context.js +646 -0
  60. package/lib/rules/enforce-timestamp-now.js +23 -7
  61. package/lib/rules/enforce-transform-memoization.d.ts +4 -0
  62. package/lib/rules/enforce-transform-memoization.js +416 -0
  63. package/lib/rules/enforce-typescript-markdown-code-blocks.d.ts +1 -0
  64. package/lib/rules/enforce-typescript-markdown-code-blocks.js +100 -0
  65. package/lib/rules/enforce-unique-cursor-headers.d.ts +16 -0
  66. package/lib/rules/enforce-unique-cursor-headers.js +365 -0
  67. package/lib/rules/enforce-verb-noun-naming.js +90 -14
  68. package/lib/rules/ensure-pointer-events-none.js +28 -2
  69. package/lib/rules/export-if-in-doubt.js +27 -4
  70. package/lib/rules/extract-global-constants.js +92 -53
  71. package/lib/rules/fast-deep-equal-over-microdiff.d.ts +2 -1
  72. package/lib/rules/fast-deep-equal-over-microdiff.js +351 -83
  73. package/lib/rules/firestore-transaction-reads-before-writes.d.ts +1 -0
  74. package/lib/rules/firestore-transaction-reads-before-writes.js +277 -0
  75. package/lib/rules/flatten-push-calls.d.ts +2 -0
  76. package/lib/rules/flatten-push-calls.js +428 -0
  77. package/lib/rules/generic-starts-with-t.js +8 -2
  78. package/lib/rules/global-const-style.js +50 -19
  79. package/lib/rules/jsdoc-above-field.d.ts +11 -0
  80. package/lib/rules/jsdoc-above-field.js +208 -0
  81. package/lib/rules/key-only-outermost-element.js +21 -3
  82. package/lib/rules/logical-top-to-bottom-grouping.d.ts +5 -0
  83. package/lib/rules/logical-top-to-bottom-grouping.js +1258 -0
  84. package/lib/rules/memo-compare-deeply-complex-props.d.ts +3 -0
  85. package/lib/rules/memo-compare-deeply-complex-props.js +788 -0
  86. package/lib/rules/memo-nested-react-components.d.ts +8 -0
  87. package/lib/rules/memo-nested-react-components.js +410 -0
  88. package/lib/rules/memoize-root-level-hocs.d.ts +7 -0
  89. package/lib/rules/memoize-root-level-hocs.js +242 -0
  90. package/lib/rules/no-always-true-false-conditions.d.ts +2 -1
  91. package/lib/rules/no-always-true-false-conditions.js +68 -8
  92. package/lib/rules/no-array-length-in-deps.d.ts +12 -0
  93. package/lib/rules/no-array-length-in-deps.js +314 -0
  94. package/lib/rules/no-async-array-filter.js +5 -2
  95. package/lib/rules/no-async-foreach.js +210 -12
  96. package/lib/rules/no-circular-references.js +18 -17
  97. package/lib/rules/no-class-instance-destructuring.js +55 -12
  98. package/lib/rules/no-complex-cloud-params.js +22 -5
  99. package/lib/rules/no-compositing-layer-props.js +6 -4
  100. package/lib/rules/no-conditional-literals-in-jsx.js +37 -12
  101. package/lib/rules/no-console-error.d.ts +9 -0
  102. package/lib/rules/no-console-error.js +525 -0
  103. package/lib/rules/no-curly-brackets-around-commented-properties.d.ts +2 -0
  104. package/lib/rules/no-curly-brackets-around-commented-properties.js +258 -0
  105. package/lib/rules/no-empty-dependency-use-callbacks.d.ts +11 -0
  106. package/lib/rules/no-empty-dependency-use-callbacks.js +576 -0
  107. package/lib/rules/no-entire-object-hook-deps.d.ts +3 -1
  108. package/lib/rules/no-entire-object-hook-deps.js +320 -68
  109. package/lib/rules/no-excessive-parent-chain.d.ts +5 -0
  110. package/lib/rules/no-excessive-parent-chain.js +273 -0
  111. package/lib/rules/no-explicit-return-type.d.ts +2 -1
  112. package/lib/rules/no-explicit-return-type.js +215 -26
  113. package/lib/rules/no-filter-without-return.js +5 -1
  114. package/lib/rules/no-firestore-jest-mock.d.ts +2 -1
  115. package/lib/rules/no-firestore-jest-mock.js +126 -8
  116. package/lib/rules/no-firestore-object-arrays.js +398 -28
  117. package/lib/rules/no-handler-suffix.d.ts +12 -0
  118. package/lib/rules/no-handler-suffix.js +305 -0
  119. package/lib/rules/no-hungarian.js +14 -14
  120. package/lib/rules/no-inline-component-prop.d.ts +10 -0
  121. package/lib/rules/no-inline-component-prop.js +456 -0
  122. package/lib/rules/no-jsx-in-hooks.js +6 -1
  123. package/lib/rules/no-jsx-whitespace-literal.js +8 -2
  124. package/lib/rules/no-margin-properties.d.ts +7 -1
  125. package/lib/rules/no-margin-properties.js +22 -9
  126. package/lib/rules/no-memoize-on-static.js +9 -1
  127. package/lib/rules/no-misleading-boolean-prefixes.d.ts +7 -0
  128. package/lib/rules/no-misleading-boolean-prefixes.js +331 -0
  129. package/lib/rules/no-misused-switch-case.js +22 -1
  130. package/lib/rules/no-mixed-firestore-transactions.d.ts +3 -1
  131. package/lib/rules/no-mixed-firestore-transactions.js +296 -34
  132. package/lib/rules/no-mock-firebase-admin.js +5 -2
  133. package/lib/rules/no-object-values-on-strings.js +10 -2
  134. package/lib/rules/no-overridable-method-calls-in-constructor.d.ts +1 -0
  135. package/lib/rules/no-overridable-method-calls-in-constructor.js +272 -0
  136. package/lib/rules/no-passthrough-getters.d.ts +4 -0
  137. package/lib/rules/no-passthrough-getters.js +206 -0
  138. package/lib/rules/no-redundant-annotation-assertion.d.ts +2 -0
  139. package/lib/rules/no-redundant-annotation-assertion.js +402 -0
  140. package/lib/rules/no-redundant-param-types.js +16 -6
  141. package/lib/rules/no-redundant-this-params.d.ts +3 -0
  142. package/lib/rules/no-redundant-this-params.js +459 -0
  143. package/lib/rules/no-redundant-usecallback-wrapper.d.ts +8 -0
  144. package/lib/rules/no-redundant-usecallback-wrapper.js +328 -0
  145. package/lib/rules/no-res-error-status-in-onrequest.d.ts +4 -0
  146. package/lib/rules/no-res-error-status-in-onrequest.js +521 -0
  147. package/lib/rules/no-restricted-properties-fix.d.ts +12 -0
  148. package/lib/rules/no-restricted-properties-fix.js +173 -0
  149. package/lib/rules/no-separate-loading-state.d.ts +8 -0
  150. package/lib/rules/no-separate-loading-state.js +133 -0
  151. package/lib/rules/no-stale-state-across-await.d.ts +1 -0
  152. package/lib/rules/no-stale-state-across-await.js +185 -0
  153. package/lib/rules/no-static-constants-in-dynamic-files.d.ts +3 -0
  154. package/lib/rules/no-static-constants-in-dynamic-files.js +149 -0
  155. package/lib/rules/no-try-catch-already-exists-in-transaction.d.ts +1 -0
  156. package/lib/rules/no-try-catch-already-exists-in-transaction.js +342 -0
  157. package/lib/rules/no-type-assertion-returns.js +49 -49
  158. package/lib/rules/no-undefined-null-passthrough.js +217 -40
  159. package/lib/rules/no-unmemoized-memo-without-props.d.ts +8 -0
  160. package/lib/rules/no-unmemoized-memo-without-props.js +426 -0
  161. package/lib/rules/no-unnecessary-destructuring-rename.d.ts +2 -0
  162. package/lib/rules/no-unnecessary-destructuring-rename.js +347 -0
  163. package/lib/rules/no-unnecessary-destructuring.js +14 -4
  164. package/lib/rules/no-unnecessary-verb-suffix.js +2 -3
  165. package/lib/rules/no-unpinned-dependencies.js +36 -5
  166. package/lib/rules/no-unsafe-firestore-spread.js +8 -5
  167. package/lib/rules/no-unused-props.d.ts +5 -2
  168. package/lib/rules/no-unused-props.js +451 -112
  169. package/lib/rules/no-unused-usestate.js +6 -2
  170. package/lib/rules/no-useless-fragment.js +28 -2
  171. package/lib/rules/no-useless-usememo-primitives.d.ts +9 -0
  172. package/lib/rules/no-useless-usememo-primitives.js +393 -0
  173. package/lib/rules/no-usememo-for-pass-by-value.d.ts +13 -0
  174. package/lib/rules/no-usememo-for-pass-by-value.js +757 -0
  175. package/lib/rules/no-uuidv4-base62-as-key.js +18 -13
  176. package/lib/rules/omit-index-html.d.ts +2 -1
  177. package/lib/rules/omit-index-html.js +62 -7
  178. package/lib/rules/optimize-object-boolean-conditions.d.ts +1 -0
  179. package/lib/rules/optimize-object-boolean-conditions.js +236 -0
  180. package/lib/rules/parallelize-async-operations.d.ts +8 -0
  181. package/lib/rules/parallelize-async-operations.js +394 -0
  182. package/lib/rules/prefer-batch-operations.d.ts +1 -3
  183. package/lib/rules/prefer-batch-operations.js +228 -35
  184. package/lib/rules/prefer-block-comments-for-declarations.js +22 -7
  185. package/lib/rules/prefer-clone-deep.js +3 -3
  186. package/lib/rules/prefer-destructuring-no-class.d.ts +2 -1
  187. package/lib/rules/prefer-destructuring-no-class.js +244 -59
  188. package/lib/rules/prefer-docsetter-setall.d.ts +2 -0
  189. package/lib/rules/prefer-docsetter-setall.js +243 -0
  190. package/lib/rules/prefer-document-flattening.d.ts +4 -0
  191. package/lib/rules/prefer-document-flattening.js +239 -0
  192. package/lib/rules/prefer-field-paths-in-transforms.d.ts +7 -0
  193. package/lib/rules/prefer-field-paths-in-transforms.js +251 -0
  194. package/lib/rules/prefer-fragment-component.js +4 -4
  195. package/lib/rules/prefer-fragment-shorthand.js +2 -1
  196. package/lib/rules/prefer-getter-over-parameterless-method.d.ts +13 -0
  197. package/lib/rules/prefer-getter-over-parameterless-method.js +648 -0
  198. package/lib/rules/prefer-global-router-state-key.d.ts +7 -3
  199. package/lib/rules/prefer-global-router-state-key.js +305 -31
  200. package/lib/rules/prefer-memoized-props.d.ts +3 -0
  201. package/lib/rules/prefer-memoized-props.js +445 -0
  202. package/lib/rules/prefer-next-dynamic.d.ts +9 -0
  203. package/lib/rules/prefer-next-dynamic.js +357 -0
  204. package/lib/rules/prefer-nullish-coalescing-boolean-props.d.ts +1 -0
  205. package/lib/rules/prefer-nullish-coalescing-boolean-props.js +435 -0
  206. package/lib/rules/prefer-nullish-coalescing-override.d.ts +7 -0
  207. package/lib/rules/prefer-nullish-coalescing-override.js +188 -0
  208. package/lib/rules/prefer-params-over-parent-id.d.ts +5 -0
  209. package/lib/rules/prefer-params-over-parent-id.js +277 -0
  210. package/lib/rules/prefer-settings-object.js +23 -15
  211. package/lib/rules/prefer-type-alias-over-typeof-constant.d.ts +3 -0
  212. package/lib/rules/prefer-type-alias-over-typeof-constant.js +259 -0
  213. package/lib/rules/prefer-type-over-interface.js +7 -2
  214. package/lib/rules/prefer-url-tostring-over-tojson.d.ts +2 -0
  215. package/lib/rules/prefer-url-tostring-over-tojson.js +169 -0
  216. package/lib/rules/prefer-use-deep-compare-memo.d.ts +4 -0
  217. package/lib/rules/prefer-use-deep-compare-memo.js +431 -0
  218. package/lib/rules/prefer-usecallback-over-usememo-for-functions.js +25 -2
  219. package/lib/rules/prefer-usememo-over-useeffect-usestate.js +24 -5
  220. package/lib/rules/prefer-utility-function-over-private-static.js +34 -2
  221. package/lib/rules/prevent-children-clobber.d.ts +2 -0
  222. package/lib/rules/prevent-children-clobber.js +536 -0
  223. package/lib/rules/react-memoize-literals.d.ts +4 -0
  224. package/lib/rules/react-memoize-literals.js +495 -0
  225. package/lib/rules/react-usememo-should-be-component.d.ts +2 -1
  226. package/lib/rules/react-usememo-should-be-component.js +144 -78
  227. package/lib/rules/require-dynamic-firebase-imports.js +2 -1
  228. package/lib/rules/require-hooks-default-params.js +17 -16
  229. package/lib/rules/require-https-error-cause.d.ts +4 -0
  230. package/lib/rules/require-https-error-cause.js +136 -0
  231. package/lib/rules/require-https-error.js +43 -21
  232. package/lib/rules/require-image-optimized.js +2 -2
  233. package/lib/rules/require-memo.js +12 -2
  234. package/lib/rules/require-memoize-jsx-returners.d.ts +3 -0
  235. package/lib/rules/require-memoize-jsx-returners.js +485 -0
  236. package/lib/rules/require-usememo-object-literals.js +9 -4
  237. package/lib/rules/semantic-function-prefixes.js +38 -18
  238. package/lib/rules/sync-onwrite-name-func.js +5 -1
  239. package/lib/rules/test-file-location-enforcement.d.ts +1 -0
  240. package/lib/rules/test-file-location-enforcement.js +57 -0
  241. package/lib/rules/use-custom-link.js +6 -1
  242. package/lib/rules/use-custom-router.js +6 -1
  243. package/lib/rules/use-latest-callback.d.ts +3 -0
  244. package/lib/rules/use-latest-callback.js +271 -0
  245. package/lib/rules/vertically-group-related-functions.d.ts +16 -0
  246. package/lib/rules/vertically-group-related-functions.js +480 -0
  247. package/lib/utils/ASTHelpers.d.ts +13 -1
  248. package/lib/utils/ASTHelpers.js +34 -0
  249. package/lib/utils/createRule.js +1 -1
  250. package/lib/utils/getMethodName.d.ts +27 -0
  251. package/lib/utils/getMethodName.js +35 -0
  252. package/lib/utils/graph/ClassGraphSorterReadability.js +1 -1
  253. package/lib/utils/ruleTester.d.ts +1 -0
  254. package/lib/utils/ruleTester.js +4 -1
  255. package/lib/utils/tsTypeClassifier.d.ts +30 -0
  256. package/lib/utils/tsTypeClassifier.js +149 -0
  257. package/package.json +23 -14
  258. package/lib/rules/enforce-assertSafe-object-key.d.ts +0 -2
@@ -0,0 +1,394 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parallelizeAsyncOperations = void 0;
4
+ const utils_1 = require("@typescript-eslint/utils");
5
+ const createRule_1 = require("../utils/createRule");
6
+ const defaultOptions = [
7
+ {
8
+ sideEffectPatterns: [
9
+ 'updatecounter',
10
+ 'setcounter',
11
+ 'incrementcounter',
12
+ 'decrementcounter',
13
+ 'updatethreshold',
14
+ 'setthreshold',
15
+ 'checkthreshold',
16
+ ],
17
+ },
18
+ ];
19
+ exports.parallelizeAsyncOperations = (0, createRule_1.createRule)({
20
+ name: 'parallelize-async-operations',
21
+ meta: {
22
+ type: 'suggestion',
23
+ docs: {
24
+ description: 'Enforce the use of Promise.all() when multiple independent asynchronous operations are awaited sequentially',
25
+ recommended: 'error',
26
+ },
27
+ fixable: 'code',
28
+ schema: [
29
+ {
30
+ type: 'object',
31
+ properties: {
32
+ sideEffectPatterns: {
33
+ type: 'array',
34
+ items: {
35
+ anyOf: [
36
+ { type: 'string' },
37
+ { type: 'object', instanceof: 'RegExp' },
38
+ ],
39
+ },
40
+ default: [],
41
+ },
42
+ },
43
+ additionalProperties: false,
44
+ },
45
+ ],
46
+ messages: {
47
+ parallelizeAsyncOperations: 'Awaiting {{awaitCount}} independent async operations sequentially makes their network and I/O latency add up, which slows responses and wastes compute. These awaits have no data dependency or per-call error handling, so run them together with Promise.all([...]) and destructure the results when you need individual values.',
48
+ },
49
+ },
50
+ defaultOptions,
51
+ create(context, [options]) {
52
+ const sourceCode = context.sourceCode;
53
+ const sideEffectMatchers = (options?.sideEffectPatterns ?? []).map((pattern) => typeof pattern === 'string' ? new RegExp(pattern, 'i') : pattern);
54
+ const reportedRanges = new Set();
55
+ /**
56
+ * Checks if a node is an await expression
57
+ */
58
+ function isAwaitExpression(node) {
59
+ return node.type === utils_1.AST_NODE_TYPES.AwaitExpression;
60
+ }
61
+ /**
62
+ * Checks if a node is a variable declaration with an await expression initializer
63
+ */
64
+ function isVariableDeclarationWithAwait(node) {
65
+ if (node.type !== utils_1.AST_NODE_TYPES.VariableDeclaration) {
66
+ return false;
67
+ }
68
+ return node.declarations.some((declaration) => declaration.init && isAwaitExpression(declaration.init));
69
+ }
70
+ /**
71
+ * Checks if a node is an expression statement with an await expression
72
+ */
73
+ function isExpressionStatementWithAwait(node) {
74
+ return (node.type === utils_1.AST_NODE_TYPES.ExpressionStatement &&
75
+ node.expression.type === utils_1.AST_NODE_TYPES.AwaitExpression);
76
+ }
77
+ /**
78
+ * Extracts the await expression from a node
79
+ */
80
+ function getAwaitExpression(node) {
81
+ if (isAwaitExpression(node)) {
82
+ return node;
83
+ }
84
+ if (node.type === utils_1.AST_NODE_TYPES.ExpressionStatement &&
85
+ isAwaitExpression(node.expression)) {
86
+ return node.expression;
87
+ }
88
+ if (node.type === utils_1.AST_NODE_TYPES.VariableDeclaration) {
89
+ for (const declaration of node.declarations) {
90
+ if (declaration.init && isAwaitExpression(declaration.init)) {
91
+ return declaration.init;
92
+ }
93
+ }
94
+ }
95
+ return null;
96
+ }
97
+ /**
98
+ * Checks if an identifier is used in a node
99
+ */
100
+ function isIdentifierUsedInNode(identifier, node) {
101
+ let isUsed = false;
102
+ function visit(node) {
103
+ if (node.type === utils_1.AST_NODE_TYPES.Identifier &&
104
+ node.name === identifier) {
105
+ isUsed = true;
106
+ return;
107
+ }
108
+ // Recursively visit all child nodes
109
+ for (const key in node) {
110
+ if (key === 'parent' || key === 'range' || key === 'loc')
111
+ continue;
112
+ const child = node[key];
113
+ if (child && typeof child === 'object') {
114
+ if (Array.isArray(child)) {
115
+ for (const item of child) {
116
+ if (item && typeof item === 'object' && 'type' in item) {
117
+ visit(item);
118
+ }
119
+ }
120
+ }
121
+ else if ('type' in child) {
122
+ visit(child);
123
+ }
124
+ }
125
+ }
126
+ }
127
+ visit(node);
128
+ return isUsed;
129
+ }
130
+ /**
131
+ * Checks if there are dependencies between await expressions
132
+ */
133
+ function hasDependencies(awaitNodes, variableNames, sideEffectPatterns) {
134
+ // If we have fewer than 2 nodes, there are no dependencies to check
135
+ if (awaitNodes.length < 2) {
136
+ return false;
137
+ }
138
+ // For each await node (except the first), check if it depends on previous variables
139
+ for (let i = 1; i < awaitNodes.length; i++) {
140
+ const currentNode = awaitNodes[i];
141
+ // Check if any previous variable is used in the current await expression
142
+ for (const varName of variableNames) {
143
+ const awaitExpr = getAwaitExpression(currentNode);
144
+ if (awaitExpr &&
145
+ isIdentifierUsedInNode(varName, awaitExpr.argument)) {
146
+ return true;
147
+ }
148
+ }
149
+ // Check for operations that might have side effects that affect subsequent operations
150
+ // This is a conservative heuristic - we only flag very specific patterns
151
+ const awaitExpr = getAwaitExpression(currentNode);
152
+ if (awaitExpr &&
153
+ awaitExpr.argument.type === utils_1.AST_NODE_TYPES.CallExpression) {
154
+ const callee = awaitExpr.argument.callee;
155
+ // Check for method calls that might indicate side effects
156
+ if (callee.type === utils_1.AST_NODE_TYPES.MemberExpression &&
157
+ callee.property.type === utils_1.AST_NODE_TYPES.Identifier) {
158
+ const methodName = callee.property.name;
159
+ if (sideEffectPatterns.some((pattern) => pattern.test(methodName))) {
160
+ return true;
161
+ }
162
+ }
163
+ if (callee.type === utils_1.AST_NODE_TYPES.Identifier) {
164
+ const functionName = callee.name;
165
+ if (sideEffectPatterns.some((pattern) => pattern.test(functionName))) {
166
+ return true;
167
+ }
168
+ }
169
+ }
170
+ }
171
+ // If any node is a variable declaration with destructuring, consider it as having dependencies
172
+ // This is because destructuring often creates variables that are used later
173
+ for (const node of awaitNodes) {
174
+ if (node.type === utils_1.AST_NODE_TYPES.VariableDeclaration) {
175
+ for (const declaration of node.declarations) {
176
+ if (declaration.id.type === utils_1.AST_NODE_TYPES.ObjectPattern) {
177
+ return true;
178
+ }
179
+ }
180
+ }
181
+ }
182
+ return false;
183
+ }
184
+ /**
185
+ * Extracts variable names from variable declarations
186
+ */
187
+ function extractVariableNames(nodes) {
188
+ const variableNames = new Set();
189
+ /**
190
+ * Recursively extract identifiers from patterns
191
+ */
192
+ function extractIdentifiersFromPattern(pattern) {
193
+ switch (pattern.type) {
194
+ case utils_1.AST_NODE_TYPES.Identifier:
195
+ variableNames.add(pattern.name);
196
+ break;
197
+ case utils_1.AST_NODE_TYPES.ObjectPattern:
198
+ for (const property of pattern.properties) {
199
+ if (property.type === utils_1.AST_NODE_TYPES.Property) {
200
+ extractIdentifiersFromPattern(property.value);
201
+ }
202
+ else if (property.type === utils_1.AST_NODE_TYPES.RestElement) {
203
+ extractIdentifiersFromPattern(property.argument);
204
+ }
205
+ }
206
+ break;
207
+ case utils_1.AST_NODE_TYPES.ArrayPattern:
208
+ for (const element of pattern.elements) {
209
+ if (element) {
210
+ extractIdentifiersFromPattern(element);
211
+ }
212
+ }
213
+ break;
214
+ case utils_1.AST_NODE_TYPES.RestElement:
215
+ extractIdentifiersFromPattern(pattern.argument);
216
+ break;
217
+ case utils_1.AST_NODE_TYPES.AssignmentPattern:
218
+ extractIdentifiersFromPattern(pattern.left);
219
+ break;
220
+ }
221
+ }
222
+ for (const node of nodes) {
223
+ if (node.type === utils_1.AST_NODE_TYPES.VariableDeclaration) {
224
+ for (const declaration of node.declarations) {
225
+ extractIdentifiersFromPattern(declaration.id);
226
+ }
227
+ }
228
+ }
229
+ return variableNames;
230
+ }
231
+ /**
232
+ * Checks if nodes are in try-catch blocks (either individual or shared)
233
+ */
234
+ function areInTryCatchBlocks(nodes) {
235
+ for (const node of nodes) {
236
+ let current = node;
237
+ // Traverse up to find if the node is in a try block
238
+ while (current && current.parent) {
239
+ if (current.parent.type === utils_1.AST_NODE_TYPES.TryStatement &&
240
+ current.parent.block === current) {
241
+ // If we find a try block, we should not parallelize
242
+ // This applies to both individual and shared try-catch blocks
243
+ return true;
244
+ }
245
+ current = current.parent;
246
+ }
247
+ }
248
+ return false;
249
+ }
250
+ /**
251
+ * Checks if nodes are in a loop
252
+ */
253
+ function areInLoop(nodes) {
254
+ for (const node of nodes) {
255
+ let current = node;
256
+ // Traverse up to find if the node is in a loop
257
+ while (current && current.parent) {
258
+ if (current.parent.type === utils_1.AST_NODE_TYPES.ForStatement ||
259
+ current.parent.type === utils_1.AST_NODE_TYPES.ForInStatement ||
260
+ current.parent.type === utils_1.AST_NODE_TYPES.ForOfStatement ||
261
+ current.parent.type === utils_1.AST_NODE_TYPES.WhileStatement ||
262
+ current.parent.type === utils_1.AST_NODE_TYPES.DoWhileStatement) {
263
+ return true;
264
+ }
265
+ current = current.parent;
266
+ }
267
+ }
268
+ return false;
269
+ }
270
+ /**
271
+ * Generates a fix for sequential awaits
272
+ *
273
+ * Returns null when the sequential awaits cannot be safely rewritten as a Promise.all.
274
+ */
275
+ function generateFix(fixer, awaitNodes) {
276
+ if (awaitNodes.length < 2) {
277
+ return null;
278
+ }
279
+ // Extract the await expressions
280
+ const awaitExpressions = awaitNodes
281
+ .map((node) => getAwaitExpression(node))
282
+ .filter((node) => node !== null);
283
+ if (awaitExpressions.length < 2) {
284
+ return null;
285
+ }
286
+ // Get the text of each await argument
287
+ const awaitArguments = awaitExpressions.map((expr) => sourceCode.getText(expr.argument));
288
+ const idsText = [];
289
+ const declKinds = new Set();
290
+ let hasVariableDeclarations = false;
291
+ for (const node of awaitNodes) {
292
+ if (node.type === utils_1.AST_NODE_TYPES.VariableDeclaration) {
293
+ hasVariableDeclarations = true;
294
+ declKinds.add(node.kind);
295
+ for (const declarator of node.declarations) {
296
+ idsText.push(sourceCode.getText(declarator.id));
297
+ }
298
+ }
299
+ else if (node.type === utils_1.AST_NODE_TYPES.ExpressionStatement) {
300
+ idsText.push('');
301
+ }
302
+ }
303
+ let promiseAllText;
304
+ if (hasVariableDeclarations) {
305
+ if (declKinds.size !== 1) {
306
+ return null;
307
+ }
308
+ if (idsText.length !== awaitArguments.length) {
309
+ return null;
310
+ }
311
+ const destructuringPattern = idsText.join(', ');
312
+ const declKind = Array.from(declKinds)[0];
313
+ promiseAllText = `${declKind} [${destructuringPattern}] = await Promise.all([\n ${awaitArguments.join(',\n ')}\n]);`;
314
+ }
315
+ else {
316
+ // Simple Promise.all without variable assignments
317
+ promiseAllText = `await Promise.all([\n ${awaitArguments.join(',\n ')}\n]);`;
318
+ }
319
+ // Find the start position, accounting for leading comments
320
+ const startPos = awaitNodes[0].range[0];
321
+ // Replace the range from the start of the first await to the end of the last await
322
+ const endPos = awaitNodes[awaitNodes.length - 1].range[1];
323
+ return fixer.replaceTextRange([startPos, endPos], promiseAllText);
324
+ }
325
+ /**
326
+ * Generates a deduplication key from await nodes' range metadata.
327
+ */
328
+ function getDeduplicationKey(awaitNodes) {
329
+ const rangeStart = awaitNodes[0].range[0];
330
+ const rangeEnd = awaitNodes[awaitNodes.length - 1].range[1];
331
+ return `${rangeStart}-${rangeEnd}`;
332
+ }
333
+ const processStatementList = (statements) => {
334
+ const awaitNodes = [];
335
+ for (const statement of statements) {
336
+ if (isExpressionStatementWithAwait(statement) ||
337
+ isVariableDeclarationWithAwait(statement)) {
338
+ awaitNodes.push(statement);
339
+ }
340
+ else if (awaitNodes.length >= 2) {
341
+ const variableNames = extractVariableNames(awaitNodes);
342
+ if (!hasDependencies(awaitNodes, variableNames, sideEffectMatchers) &&
343
+ !areInTryCatchBlocks(awaitNodes) &&
344
+ !areInLoop(awaitNodes)) {
345
+ const key = getDeduplicationKey(awaitNodes);
346
+ if (!reportedRanges.has(key)) {
347
+ reportedRanges.add(key);
348
+ context.report({
349
+ node: awaitNodes[0],
350
+ messageId: 'parallelizeAsyncOperations',
351
+ data: {
352
+ awaitCount: awaitNodes.length.toString(),
353
+ },
354
+ fix: (fixer) => generateFix(fixer, awaitNodes),
355
+ });
356
+ }
357
+ }
358
+ awaitNodes.length = 0;
359
+ }
360
+ else {
361
+ awaitNodes.length = 0;
362
+ }
363
+ }
364
+ if (awaitNodes.length >= 2) {
365
+ const variableNames = extractVariableNames(awaitNodes);
366
+ if (!hasDependencies(awaitNodes, variableNames, sideEffectMatchers) &&
367
+ !areInTryCatchBlocks(awaitNodes) &&
368
+ !areInLoop(awaitNodes)) {
369
+ const key = getDeduplicationKey(awaitNodes);
370
+ if (!reportedRanges.has(key)) {
371
+ reportedRanges.add(key);
372
+ context.report({
373
+ node: awaitNodes[0],
374
+ messageId: 'parallelizeAsyncOperations',
375
+ data: {
376
+ awaitCount: awaitNodes.length.toString(),
377
+ },
378
+ fix: (fixer) => generateFix(fixer, awaitNodes),
379
+ });
380
+ }
381
+ }
382
+ }
383
+ };
384
+ return {
385
+ Program(node) {
386
+ processStatementList(node.body);
387
+ },
388
+ BlockStatement(node) {
389
+ processStatementList(node.body);
390
+ },
391
+ };
392
+ },
393
+ });
394
+ //# sourceMappingURL=parallelize-async-operations.js.map
@@ -1,3 +1 @@
1
- type MessageIds = 'preferSetAll' | 'preferOverwriteAll';
2
- export declare const preferBatchOperations: import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleModule<MessageIds, [], import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleListener>;
3
- export {};
1
+ export declare const preferBatchOperations: import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleModule<"preferBatch", [], import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleListener>;