@blumintinc/eslint-plugin-blumint 1.18.9 → 1.18.11
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/lib/index.js +1 -1
- package/lib/rules/parallelize-async-operations.js +63 -21
- package/package.json +1 -1
- package/release-manifest.json +28 -0
package/lib/index.js
CHANGED
|
@@ -169,7 +169,43 @@ exports.parallelizeAsyncOperations = (0, createRule_1.createRule)({
|
|
|
169
169
|
* "transactionCollector", etc. This may produce false positives for
|
|
170
170
|
* unrelated managers, but errs on the side of safety.
|
|
171
171
|
*/
|
|
172
|
-
const COORDINATOR_PATTERN = /batch|manager|collector|transaction|tx|unitofwork|accumulator/i;
|
|
172
|
+
const COORDINATOR_PATTERN = /batch|manager|collector|transaction|tx|coordinator|unitofwork|accumulator|aggregator/i;
|
|
173
|
+
/**
|
|
174
|
+
* Matches guard/assertion callees by their leading verb. Anchored at the
|
|
175
|
+
* start so it fires on the callee's own verb (assertStartable,
|
|
176
|
+
* validateInput, ensureExists, requireAuth, checkAccess, verifyOwnership,
|
|
177
|
+
* guardAgainstX) rather than on an arbitrary substring elsewhere in the
|
|
178
|
+
* name.
|
|
179
|
+
*/
|
|
180
|
+
const GUARD_PATTERN = /^(assert|ensure|require|validate|verify|guard|check)/i;
|
|
181
|
+
/**
|
|
182
|
+
* Extracts the callee's method name (the identifier bearing the leading
|
|
183
|
+
* verb) from an await expression argument. Handles both direct
|
|
184
|
+
* CallExpressions and optional-call ChainExpressions, and both bare
|
|
185
|
+
* identifier callees and member-expression callees.
|
|
186
|
+
*/
|
|
187
|
+
function getCalleeMethodName(awaitExpr) {
|
|
188
|
+
let callExpr = null;
|
|
189
|
+
if (awaitExpr.argument.type === utils_1.AST_NODE_TYPES.CallExpression) {
|
|
190
|
+
callExpr = awaitExpr.argument;
|
|
191
|
+
}
|
|
192
|
+
else if (awaitExpr.argument.type === utils_1.AST_NODE_TYPES.ChainExpression &&
|
|
193
|
+
awaitExpr.argument.expression.type === utils_1.AST_NODE_TYPES.CallExpression) {
|
|
194
|
+
callExpr = awaitExpr.argument.expression;
|
|
195
|
+
}
|
|
196
|
+
if (!callExpr) {
|
|
197
|
+
return null;
|
|
198
|
+
}
|
|
199
|
+
const callee = callExpr.callee;
|
|
200
|
+
if (callee.type === utils_1.AST_NODE_TYPES.MemberExpression &&
|
|
201
|
+
callee.property.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
202
|
+
return callee.property.name;
|
|
203
|
+
}
|
|
204
|
+
if (callee.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
205
|
+
return callee.name;
|
|
206
|
+
}
|
|
207
|
+
return null;
|
|
208
|
+
}
|
|
173
209
|
/**
|
|
174
210
|
* Checks if there are dependencies between await expressions
|
|
175
211
|
*/
|
|
@@ -214,28 +250,34 @@ exports.parallelizeAsyncOperations = (0, createRule_1.createRule)({
|
|
|
214
250
|
}
|
|
215
251
|
// 3. Check for operations that might have side effects
|
|
216
252
|
// If any node has a side effect, we should not parallelize the sequence
|
|
217
|
-
|
|
218
|
-
if (
|
|
219
|
-
|
|
253
|
+
const methodName = getCalleeMethodName(awaitExpr);
|
|
254
|
+
if (methodName &&
|
|
255
|
+
sideEffectPatterns.some((pattern) => pattern.test(methodName))) {
|
|
256
|
+
return true;
|
|
220
257
|
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
258
|
+
}
|
|
259
|
+
// 4. Guard-then-side-effect ordering barrier. A discarded-result await
|
|
260
|
+
// whose callee reads as a guard/assertion (assert*, ensure*, validate*,
|
|
261
|
+
// ...) is a control-flow gate: it throws to abort the run when its
|
|
262
|
+
// precondition fails, so any await after it must run ONLY if the guard
|
|
263
|
+
// resolves. Promise.all invokes every operand eagerly, so it would fire
|
|
264
|
+
// the gated side effect even when the guard rejects. Treat the guard's
|
|
265
|
+
// presence (when something follows it) as a sequencing dependency that
|
|
266
|
+
// blocks parallelizing the whole run. Only discarded-result awaits
|
|
267
|
+
// (ExpressionStatements) qualify; `const ok = await validate(x)` has a
|
|
268
|
+
// variable and is handled by the data-dependency path above.
|
|
269
|
+
for (let i = 0; i < awaitNodes.length - 1; i++) {
|
|
270
|
+
const node = awaitNodes[i];
|
|
271
|
+
if (node.type !== utils_1.AST_NODE_TYPES.ExpressionStatement) {
|
|
272
|
+
continue;
|
|
224
273
|
}
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
else if (callee.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
233
|
-
methodName = callee.name;
|
|
234
|
-
}
|
|
235
|
-
if (methodName &&
|
|
236
|
-
sideEffectPatterns.some((pattern) => pattern.test(methodName))) {
|
|
237
|
-
return true;
|
|
238
|
-
}
|
|
274
|
+
const awaitExpr = getAwaitExpression(node);
|
|
275
|
+
if (!awaitExpr) {
|
|
276
|
+
continue;
|
|
277
|
+
}
|
|
278
|
+
const methodName = getCalleeMethodName(awaitExpr);
|
|
279
|
+
if (methodName && GUARD_PATTERN.test(methodName)) {
|
|
280
|
+
return true;
|
|
239
281
|
}
|
|
240
282
|
}
|
|
241
283
|
// If any node is a variable declaration with destructuring, consider it as having dependencies
|
package/package.json
CHANGED
package/release-manifest.json
CHANGED
|
@@ -1,4 +1,32 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "1.18.11",
|
|
4
|
+
"date": "2026-07-11T16:25:05.418Z",
|
|
5
|
+
"rules": [
|
|
6
|
+
{
|
|
7
|
+
"name": "parallelize-async-operations",
|
|
8
|
+
"changeType": "fix",
|
|
9
|
+
"issues": [
|
|
10
|
+
1284
|
|
11
|
+
],
|
|
12
|
+
"summary": "treat throw-gated guard awaits as a sequencing barrier (closes #1284)"
|
|
13
|
+
}
|
|
14
|
+
]
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"version": "1.18.10",
|
|
18
|
+
"date": "2026-07-11T15:24:03.394Z",
|
|
19
|
+
"rules": [
|
|
20
|
+
{
|
|
21
|
+
"name": "parallelize-async-operations",
|
|
22
|
+
"changeType": "fix",
|
|
23
|
+
"issues": [
|
|
24
|
+
1283
|
|
25
|
+
],
|
|
26
|
+
"summary": "restore coordinator to COORDINATOR_PATTERN (closes #1283)"
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
},
|
|
2
30
|
{
|
|
3
31
|
"version": "1.18.9",
|
|
4
32
|
"date": "2026-07-11T01:51:22.294Z",
|