eslint-plugin-react-hooks-extra 1.15.0-beta.0 → 1.15.0-beta.8

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/dist/index.d.mts CHANGED
@@ -7,6 +7,7 @@ declare const _default: {
7
7
  };
8
8
  readonly rules: {
9
9
  readonly "no-direct-set-state-in-use-effect": _typescript_eslint_utils_ts_eslint.RuleModule<"noDirectSetStateInUseEffect", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
10
+ readonly "no-direct-set-state-in-use-layout-effect": _typescript_eslint_utils_ts_eslint.RuleModule<"noDirectSetStateInUseLayoutEffect", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
10
11
  readonly "no-redundant-custom-hook": _typescript_eslint_utils_ts_eslint.RuleModule<"noRedundantCustomHook", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
11
12
  readonly "no-unnecessary-use-callback": _typescript_eslint_utils_ts_eslint.RuleModule<"noUnnecessaryUseCallback", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
12
13
  readonly "no-unnecessary-use-memo": _typescript_eslint_utils_ts_eslint.RuleModule<"noUnnecessaryUseMemo", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
@@ -15,8 +16,6 @@ declare const _default: {
15
16
  readonly "ensure-custom-hooks-using-other-hooks": _typescript_eslint_utils_ts_eslint.RuleModule<"noRedundantCustomHook", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
16
17
  /** @deprecated Use `no-unnecessary-use-memo` instead */
17
18
  readonly "ensure-use-memo-has-non-empty-deps": _typescript_eslint_utils_ts_eslint.RuleModule<"noUnnecessaryUseMemo", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
18
- /** @deprecated Use `no-direct-set-state-in-use-effect` instead */
19
- readonly "no-direct-set-state-in-use-layout-effect": _typescript_eslint_utils_ts_eslint.RuleModule<"noDirectSetStateInUseEffect", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
20
19
  };
21
20
  };
22
21
 
package/dist/index.d.ts CHANGED
@@ -7,6 +7,7 @@ declare const _default: {
7
7
  };
8
8
  readonly rules: {
9
9
  readonly "no-direct-set-state-in-use-effect": _typescript_eslint_utils_ts_eslint.RuleModule<"noDirectSetStateInUseEffect", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
10
+ readonly "no-direct-set-state-in-use-layout-effect": _typescript_eslint_utils_ts_eslint.RuleModule<"noDirectSetStateInUseLayoutEffect", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
10
11
  readonly "no-redundant-custom-hook": _typescript_eslint_utils_ts_eslint.RuleModule<"noRedundantCustomHook", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
11
12
  readonly "no-unnecessary-use-callback": _typescript_eslint_utils_ts_eslint.RuleModule<"noUnnecessaryUseCallback", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
12
13
  readonly "no-unnecessary-use-memo": _typescript_eslint_utils_ts_eslint.RuleModule<"noUnnecessaryUseMemo", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
@@ -15,8 +16,6 @@ declare const _default: {
15
16
  readonly "ensure-custom-hooks-using-other-hooks": _typescript_eslint_utils_ts_eslint.RuleModule<"noRedundantCustomHook", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
16
17
  /** @deprecated Use `no-unnecessary-use-memo` instead */
17
18
  readonly "ensure-use-memo-has-non-empty-deps": _typescript_eslint_utils_ts_eslint.RuleModule<"noUnnecessaryUseMemo", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
18
- /** @deprecated Use `no-direct-set-state-in-use-effect` instead */
19
- readonly "no-direct-set-state-in-use-layout-effect": _typescript_eslint_utils_ts_eslint.RuleModule<"noDirectSetStateInUseEffect", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
20
19
  };
21
20
  };
22
21
 
package/dist/index.js CHANGED
@@ -4,11 +4,10 @@ var AST2 = require('@eslint-react/ast');
4
4
  var core = require('@eslint-react/core');
5
5
  var shared = require('@eslint-react/shared');
6
6
  var tools = require('@eslint-react/tools');
7
- var VAR3 = require('@eslint-react/var');
7
+ var VAR4 = require('@eslint-react/var');
8
8
  var types = require('@typescript-eslint/types');
9
9
  var tsPattern = require('ts-pattern');
10
10
  var astUtils = require('@typescript-eslint/utils/ast-utils');
11
- require('@typescript-eslint/utils');
12
11
 
13
12
  function _interopNamespace(e) {
14
13
  if (e && e.__esModule) return e;
@@ -29,17 +28,17 @@ function _interopNamespace(e) {
29
28
  }
30
29
 
31
30
  var AST2__namespace = /*#__PURE__*/_interopNamespace(AST2);
32
- var VAR3__namespace = /*#__PURE__*/_interopNamespace(VAR3);
31
+ var VAR4__namespace = /*#__PURE__*/_interopNamespace(VAR4);
33
32
 
34
33
  // package.json
35
34
  var name = "eslint-plugin-react-hooks-extra";
36
- var version = "1.15.0-beta.0";
35
+ var version = "1.15.0-beta.8";
37
36
  var createRule = shared.createRuleForPlugin("hooks-extra");
38
37
  function isFromHookCall(name2, context, settings, predicate = tools.F.constTrue) {
39
38
  const hookAlias = settings.additionalHooks?.[name2] ?? [];
40
39
  return (topLevelId) => tools.F.pipe(
41
- VAR3__namespace.findVariable(topLevelId, context.sourceCode.getScope(topLevelId)),
42
- tools.O.flatMap(VAR3__namespace.getVariableNode(0)),
40
+ VAR4__namespace.findVariable(topLevelId, context.sourceCode.getScope(topLevelId)),
41
+ tools.O.flatMap(VAR4__namespace.getVariableNode(0)),
43
42
  tools.O.filter(AST2__namespace.is(types.AST_NODE_TYPES.CallExpression)),
44
43
  tools.O.filter(core.isReactHookCallWithNameAlias(name2, context, hookAlias)),
45
44
  tools.O.exists((call) => predicate(topLevelId, call))
@@ -132,17 +131,7 @@ var no_direct_set_state_in_use_effect_default = createRule({
132
131
  if (!/use\w*Effect/u.test(context.sourceCode.text)) return {};
133
132
  const settings = shared.decodeSettings(context.settings);
134
133
  const additionalHooks = settings.additionalHooks ?? {};
135
- const isUseEffectLikeCall = core.isReactHookCallWithNameAlias(
136
- "useEffect",
137
- context,
138
- [
139
- "useLayoutEffect",
140
- "useInsertionEffect",
141
- ...additionalHooks.useEffect ?? [],
142
- ...additionalHooks.useLayoutEffect ?? [],
143
- ...additionalHooks.useInsertionEffect ?? []
144
- ]
145
- );
134
+ const isUseEffectLikeCall = core.isReactHookCallWithNameAlias("useEffect", context, additionalHooks.useEffect ?? []);
146
135
  const isUseStateCall2 = core.isReactHookCallWithNameAlias("useState", context, additionalHooks.useState ?? []);
147
136
  const isUseMemoCall2 = core.isReactHookCallWithNameAlias("useMemo", context, additionalHooks.useMemo ?? []);
148
137
  const isUseCallbackCall2 = core.isReactHookCallWithNameAlias("useCallback", context, additionalHooks.useCallback ?? []);
@@ -250,7 +239,7 @@ var no_direct_set_state_in_use_effect_default = createRule({
250
239
  },
251
240
  "Program:exit"() {
252
241
  const getSetStateCalls = (id, initialScope) => {
253
- const node = tools.O.flatMap(VAR3__namespace.findVariable(id, initialScope), VAR3__namespace.getVariableNode(0)).pipe(tools.O.getOrNull);
242
+ const node = tools.O.flatMap(VAR4__namespace.findVariable(id, initialScope), VAR4__namespace.getVariableNode(0)).pipe(tools.O.getOrNull);
254
243
  switch (node?.type) {
255
244
  case types.AST_NODE_TYPES.FunctionDeclaration:
256
245
  case types.AST_NODE_TYPES.FunctionExpression:
@@ -301,7 +290,187 @@ var no_direct_set_state_in_use_effect_default = createRule({
301
290
  },
302
291
  defaultOptions: []
303
292
  });
304
- var RULE_NAME2 = "no-redundant-custom-hook";
293
+ var RULE_NAME2 = "no-direct-set-state-in-use-layout-effect";
294
+ var no_direct_set_state_in_use_layout_effect_default = createRule({
295
+ meta: {
296
+ type: "problem",
297
+ docs: {
298
+ description: "disallow direct calls to the 'set' function of 'useState' in 'useLayoutEffect'"
299
+ },
300
+ messages: {
301
+ noDirectSetStateInUseLayoutEffect: "Do not call the 'set' function '{{name}}' of 'useState' directly in 'useLayoutEffect'."
302
+ },
303
+ schema: []
304
+ },
305
+ name: RULE_NAME2,
306
+ create(context) {
307
+ if (!/use\w*Effect/u.test(context.sourceCode.text)) return {};
308
+ const settings = shared.decodeSettings(context.settings);
309
+ const additionalHooks = settings.additionalHooks ?? {};
310
+ const isUseEffectLikeCall = core.isReactHookCallWithNameAlias(
311
+ "useLayoutEffect",
312
+ context,
313
+ additionalHooks.useLayoutEffect ?? []
314
+ );
315
+ const isUseStateCall2 = core.isReactHookCallWithNameAlias("useState", context, additionalHooks.useState ?? []);
316
+ const isUseMemoCall2 = core.isReactHookCallWithNameAlias("useMemo", context, additionalHooks.useMemo ?? []);
317
+ const isUseCallbackCall2 = core.isReactHookCallWithNameAlias("useCallback", context, additionalHooks.useCallback ?? []);
318
+ const isSetStateCall = isSetFunctionCall(context, settings);
319
+ const isIdFromUseStateCall = isFromUseStateCall(context, settings);
320
+ const functionStack = [];
321
+ const setupFunctionRef = tools.MutRef.make(null);
322
+ const setupFunctionIdentifiers = [];
323
+ const indirectFunctionCalls = [];
324
+ const indirectSetStateCalls = /* @__PURE__ */ new WeakMap();
325
+ const indirectSetStateCallsAsArgs = /* @__PURE__ */ new WeakMap();
326
+ const indirectSetStateCallsAsSetups = /* @__PURE__ */ new Map();
327
+ const indirectSetStateCallsInHooks = /* @__PURE__ */ new WeakMap();
328
+ const onSetupFunctionEnter = (node) => {
329
+ tools.MutRef.set(setupFunctionRef, node);
330
+ };
331
+ const onSetupFunctionExit = (node) => {
332
+ tools.MutRef.update(setupFunctionRef, (current) => current === node ? null : current);
333
+ };
334
+ function isSetupFunction(node) {
335
+ return node.parent?.type === types.AST_NODE_TYPES.CallExpression && node.parent.callee !== node && isUseEffectLikeCall(node.parent);
336
+ }
337
+ function getCallKind(node) {
338
+ return tsPattern.match(node).when(isUseStateCall2, () => "useState").when(isUseEffectLikeCall, () => "useLayoutEffect").when(isSetStateCall, () => "setState").when(isThenCall, () => "then").otherwise(() => "other");
339
+ }
340
+ function getFunctionKind(node) {
341
+ return tsPattern.match(node).when(isSetupFunction, () => "setup").when(AST2__namespace.isFunctionOfImmediatelyInvoked, () => "immediate").otherwise(() => "other");
342
+ }
343
+ return {
344
+ ":function"(node) {
345
+ const functionKind = getFunctionKind(node);
346
+ functionStack.push([node, functionKind]);
347
+ if (functionKind === "setup") onSetupFunctionEnter(node);
348
+ },
349
+ ":function:exit"(node) {
350
+ const [_, functionKind] = functionStack.at(-1) ?? [];
351
+ functionStack.pop();
352
+ if (functionKind === "setup") onSetupFunctionExit(node);
353
+ },
354
+ CallExpression(node) {
355
+ const effectFn = tools.MutRef.get(setupFunctionRef);
356
+ const [parentFn, parentFnKind] = functionStack.at(-1) ?? [];
357
+ if (parentFn?.async) return;
358
+ tsPattern.match(getCallKind(node)).with("setState", () => {
359
+ if (!parentFn) return;
360
+ if (parentFn !== effectFn && parentFnKind !== "immediate") {
361
+ const maybeVd = AST2__namespace.traverseUpGuard(node, isVariableDeclaratorFromHookCall);
362
+ if (tools.O.isSome(maybeVd)) {
363
+ const vd = maybeVd.value;
364
+ const calls2 = indirectSetStateCallsInHooks.get(vd.init) ?? [];
365
+ indirectSetStateCallsInHooks.set(vd.init, [...calls2, node]);
366
+ return;
367
+ }
368
+ const calls = indirectSetStateCalls.get(parentFn) ?? [];
369
+ indirectSetStateCalls.set(parentFn, [...calls, node]);
370
+ return;
371
+ }
372
+ context.report({
373
+ messageId: "noDirectSetStateInUseLayoutEffect",
374
+ node,
375
+ data: { name: context.sourceCode.getText(node.callee) }
376
+ });
377
+ }).with("useLayoutEffect", () => {
378
+ const [firstArg] = node.arguments;
379
+ if (AST2__namespace.isFunction(firstArg)) return;
380
+ const identifiers = AST2__namespace.getNestedIdentifiers(node);
381
+ setupFunctionIdentifiers.push(...identifiers);
382
+ }).with("other", () => {
383
+ const isInSetupFunction = effectFn === parentFn;
384
+ if (!isInSetupFunction) return;
385
+ indirectFunctionCalls.push(node);
386
+ }).otherwise(tools.F.constVoid);
387
+ },
388
+ Identifier(node) {
389
+ if (node.parent.type === types.AST_NODE_TYPES.CallExpression && node.parent.callee === node) return;
390
+ if (!isIdFromUseStateCall(node)) return;
391
+ switch (node.parent.type) {
392
+ case types.AST_NODE_TYPES.CallExpression: {
393
+ const [firstArg] = node.parent.arguments;
394
+ if (node !== firstArg) break;
395
+ if (isUseCallbackCall2(node.parent)) {
396
+ const maybeVd = AST2__namespace.traverseUpGuard(node.parent, isVariableDeclaratorFromHookCall);
397
+ if (tools.O.isNone(maybeVd)) break;
398
+ const vd = maybeVd.value;
399
+ const calls = indirectSetStateCallsAsArgs.get(vd.init) ?? [];
400
+ indirectSetStateCallsAsArgs.set(vd.init, [...calls, node]);
401
+ }
402
+ if (isUseEffectLikeCall(node.parent)) {
403
+ const calls = indirectSetStateCallsAsArgs.get(node.parent) ?? [];
404
+ indirectSetStateCallsAsSetups.set(node.parent, [...calls, node]);
405
+ }
406
+ break;
407
+ }
408
+ case types.AST_NODE_TYPES.ArrowFunctionExpression: {
409
+ const parent = node.parent.parent;
410
+ if (parent.type !== types.AST_NODE_TYPES.CallExpression) break;
411
+ if (!isUseMemoCall2(parent)) break;
412
+ const maybeVd = AST2__namespace.traverseUpGuard(parent, isVariableDeclaratorFromHookCall);
413
+ if (tools.O.isNone(maybeVd)) break;
414
+ const vd = maybeVd.value;
415
+ const calls = indirectSetStateCallsAsArgs.get(vd.init) ?? [];
416
+ indirectSetStateCallsAsArgs.set(vd.init, [...calls, node]);
417
+ }
418
+ }
419
+ },
420
+ "Program:exit"() {
421
+ const getSetStateCalls = (id, initialScope) => {
422
+ const node = tools.O.flatMap(VAR4__namespace.findVariable(id, initialScope), VAR4__namespace.getVariableNode(0)).pipe(tools.O.getOrNull);
423
+ switch (node?.type) {
424
+ case types.AST_NODE_TYPES.FunctionDeclaration:
425
+ case types.AST_NODE_TYPES.FunctionExpression:
426
+ case types.AST_NODE_TYPES.ArrowFunctionExpression:
427
+ return indirectSetStateCalls.get(node) ?? [];
428
+ case types.AST_NODE_TYPES.CallExpression:
429
+ return indirectSetStateCallsInHooks.get(node) ?? indirectSetStateCallsAsArgs.get(node) ?? [];
430
+ }
431
+ return [];
432
+ };
433
+ for (const [_, calls] of indirectSetStateCallsAsSetups) {
434
+ for (const call of calls) {
435
+ context.report({
436
+ messageId: "noDirectSetStateInUseLayoutEffect",
437
+ node: call,
438
+ data: { name: call.name }
439
+ });
440
+ }
441
+ }
442
+ for (const { callee } of indirectFunctionCalls) {
443
+ if (!("name" in callee)) continue;
444
+ const { name: name2 } = callee;
445
+ const setStateCalls = getSetStateCalls(name2, context.sourceCode.getScope(callee));
446
+ for (const setStateCall of setStateCalls) {
447
+ context.report({
448
+ messageId: "noDirectSetStateInUseLayoutEffect",
449
+ node: setStateCall,
450
+ data: {
451
+ name: AST2__namespace.toReadableNodeName(setStateCall, (n) => context.sourceCode.getText(n))
452
+ }
453
+ });
454
+ }
455
+ }
456
+ for (const id of setupFunctionIdentifiers) {
457
+ const setStateCalls = getSetStateCalls(id.name, context.sourceCode.getScope(id));
458
+ for (const setStateCall of setStateCalls) {
459
+ context.report({
460
+ messageId: "noDirectSetStateInUseLayoutEffect",
461
+ node: setStateCall,
462
+ data: {
463
+ name: AST2__namespace.toReadableNodeName(setStateCall, (n) => context.sourceCode.getText(n))
464
+ }
465
+ });
466
+ }
467
+ }
468
+ }
469
+ };
470
+ },
471
+ defaultOptions: []
472
+ });
473
+ var RULE_NAME3 = "no-redundant-custom-hook";
305
474
  var no_redundant_custom_hook_default = createRule({
306
475
  meta: {
307
476
  type: "problem",
@@ -313,7 +482,7 @@ var no_redundant_custom_hook_default = createRule({
313
482
  },
314
483
  schema: []
315
484
  },
316
- name: RULE_NAME2,
485
+ name: RULE_NAME3,
317
486
  create(context) {
318
487
  const { ctx, listeners } = core.useHookCollector();
319
488
  return {
@@ -336,7 +505,7 @@ var no_redundant_custom_hook_default = createRule({
336
505
  },
337
506
  defaultOptions: []
338
507
  });
339
- var RULE_NAME3 = "no-unnecessary-use-callback";
508
+ var RULE_NAME4 = "no-unnecessary-use-callback";
340
509
  var no_unnecessary_use_callback_default = createRule({
341
510
  meta: {
342
511
  type: "problem",
@@ -348,7 +517,7 @@ var no_unnecessary_use_callback_default = createRule({
348
517
  },
349
518
  schema: []
350
519
  },
351
- name: RULE_NAME3,
520
+ name: RULE_NAME4,
352
521
  create(context) {
353
522
  if (!context.sourceCode.text.includes("use")) return {};
354
523
  const alias = shared.decodeSettings(context.settings).additionalHooks?.useCallback ?? [];
@@ -373,8 +542,8 @@ var no_unnecessary_use_callback_default = createRule({
373
542
  const hasEmptyDeps = tools.F.pipe(
374
543
  tsPattern.match(deps).with({ type: types.AST_NODE_TYPES.ArrayExpression }, tools.O.some).with({ type: types.AST_NODE_TYPES.Identifier }, (n) => {
375
544
  return tools.F.pipe(
376
- VAR3__namespace.findVariable(n.name, initialScope),
377
- tools.O.flatMap(VAR3__namespace.getVariableNode(0)),
545
+ VAR4__namespace.findVariable(n.name, initialScope),
546
+ tools.O.flatMap(VAR4__namespace.getVariableNode(0)),
378
547
  tools.O.filter(AST2__namespace.is(types.AST_NODE_TYPES.ArrayExpression))
379
548
  );
380
549
  }).otherwise(tools.O.none),
@@ -396,13 +565,13 @@ var no_unnecessary_use_callback_default = createRule({
396
565
  return tools.O.some(n);
397
566
  }).with({ type: types.AST_NODE_TYPES.FunctionExpression }, tools.O.some).with({ type: types.AST_NODE_TYPES.Identifier }, (n) => {
398
567
  return tools.F.pipe(
399
- VAR3__namespace.findVariable(n.name, initialScope),
400
- tools.O.flatMap(VAR3__namespace.getVariableNode(0)),
568
+ VAR4__namespace.findVariable(n.name, initialScope),
569
+ tools.O.flatMap(VAR4__namespace.getVariableNode(0)),
401
570
  tools.O.filter(AST2__namespace.isFunction)
402
571
  );
403
572
  }).otherwise(tools.O.none),
404
573
  tools.O.map((n) => context.sourceCode.getScope(n)),
405
- tools.O.map((s) => VAR3__namespace.getChidScopes(s).flatMap((x) => x.references)),
574
+ tools.O.map((s) => VAR4__namespace.getChidScopes(s).flatMap((x) => x.references)),
406
575
  tools.O.exists((refs) => refs.some((x) => x.resolved?.scope.block === component))
407
576
  );
408
577
  if (isReferencedToComponentScope) return;
@@ -415,7 +584,7 @@ var no_unnecessary_use_callback_default = createRule({
415
584
  },
416
585
  defaultOptions: []
417
586
  });
418
- var RULE_NAME4 = "no-unnecessary-use-memo";
587
+ var RULE_NAME5 = "no-unnecessary-use-memo";
419
588
  var no_unnecessary_use_memo_default = createRule({
420
589
  meta: {
421
590
  type: "problem",
@@ -427,7 +596,7 @@ var no_unnecessary_use_memo_default = createRule({
427
596
  },
428
597
  schema: []
429
598
  },
430
- name: RULE_NAME4,
599
+ name: RULE_NAME5,
431
600
  create(context) {
432
601
  if (!context.sourceCode.text.includes("use")) return {};
433
602
  const alias = shared.decodeSettings(context.settings).additionalHooks?.useMemo ?? [];
@@ -452,8 +621,8 @@ var no_unnecessary_use_memo_default = createRule({
452
621
  const hasEmptyDeps = tools.F.pipe(
453
622
  tsPattern.match(deps).with({ type: types.AST_NODE_TYPES.ArrayExpression }, tools.O.some).with({ type: types.AST_NODE_TYPES.Identifier }, (n) => {
454
623
  return tools.F.pipe(
455
- VAR3__namespace.findVariable(n.name, initialScope),
456
- tools.O.flatMap(VAR3__namespace.getVariableNode(0)),
624
+ VAR4__namespace.findVariable(n.name, initialScope),
625
+ tools.O.flatMap(VAR4__namespace.getVariableNode(0)),
457
626
  tools.O.filter(AST2__namespace.is(types.AST_NODE_TYPES.ArrayExpression))
458
627
  );
459
628
  }).otherwise(tools.O.none),
@@ -475,13 +644,13 @@ var no_unnecessary_use_memo_default = createRule({
475
644
  return tools.O.some(n);
476
645
  }).with({ type: types.AST_NODE_TYPES.FunctionExpression }, tools.O.some).with({ type: types.AST_NODE_TYPES.Identifier }, (n) => {
477
646
  return tools.F.pipe(
478
- VAR3__namespace.findVariable(n.name, initialScope),
479
- tools.O.flatMap(VAR3__namespace.getVariableNode(0)),
647
+ VAR4__namespace.findVariable(n.name, initialScope),
648
+ tools.O.flatMap(VAR4__namespace.getVariableNode(0)),
480
649
  tools.O.filter(AST2__namespace.isFunction)
481
650
  );
482
651
  }).otherwise(tools.O.none),
483
652
  tools.O.map((n) => context.sourceCode.getScope(n)),
484
- tools.O.map((s) => VAR3__namespace.getChidScopes(s).flatMap((x) => x.references)),
653
+ tools.O.map((s) => VAR4__namespace.getChidScopes(s).flatMap((x) => x.references)),
485
654
  tools.O.exists((refs) => refs.some((x) => x.resolved?.scope.block === component))
486
655
  );
487
656
  if (isReferencedToComponentScope) return;
@@ -494,7 +663,7 @@ var no_unnecessary_use_memo_default = createRule({
494
663
  },
495
664
  defaultOptions: []
496
665
  });
497
- var RULE_NAME5 = "prefer-use-state-lazy-initialization";
666
+ var RULE_NAME6 = "prefer-use-state-lazy-initialization";
498
667
  var ALLOW_LIST = ["Boolean", "String", "Number"];
499
668
  var prefer_use_state_lazy_initialization_default = createRule({
500
669
  meta: {
@@ -507,7 +676,7 @@ var prefer_use_state_lazy_initialization_default = createRule({
507
676
  },
508
677
  schema: []
509
678
  },
510
- name: RULE_NAME5,
679
+ name: RULE_NAME6,
511
680
  create(context) {
512
681
  if (!context.sourceCode.text.includes("use")) return {};
513
682
  const alias = shared.decodeSettings(context.settings).additionalHooks?.useState ?? [];
@@ -543,6 +712,7 @@ var src_default = {
543
712
  },
544
713
  rules: {
545
714
  "no-direct-set-state-in-use-effect": no_direct_set_state_in_use_effect_default,
715
+ "no-direct-set-state-in-use-layout-effect": no_direct_set_state_in_use_layout_effect_default,
546
716
  "no-redundant-custom-hook": no_redundant_custom_hook_default,
547
717
  "no-unnecessary-use-callback": no_unnecessary_use_callback_default,
548
718
  "no-unnecessary-use-memo": no_unnecessary_use_memo_default,
@@ -551,9 +721,7 @@ var src_default = {
551
721
  /** @deprecated Use `no-redundant-custom-hook` instead */
552
722
  "ensure-custom-hooks-using-other-hooks": no_redundant_custom_hook_default,
553
723
  /** @deprecated Use `no-unnecessary-use-memo` instead */
554
- "ensure-use-memo-has-non-empty-deps": no_unnecessary_use_memo_default,
555
- /** @deprecated Use `no-direct-set-state-in-use-effect` instead */
556
- "no-direct-set-state-in-use-layout-effect": no_direct_set_state_in_use_effect_default
724
+ "ensure-use-memo-has-non-empty-deps": no_unnecessary_use_memo_default
557
725
  }
558
726
  };
559
727
 
package/dist/index.mjs CHANGED
@@ -2,21 +2,20 @@ import * as AST2 from '@eslint-react/ast';
2
2
  import { isReactHookCallWithNameAlias, useHookCollector, isReactHookCall, isUseCallbackCall, isReactHookCallWithNameLoose, isUseMemoCall, isUseStateCall, isReactHookName } from '@eslint-react/core';
3
3
  import { createRuleForPlugin, decodeSettings } from '@eslint-react/shared';
4
4
  import { MutRef, O, F } from '@eslint-react/tools';
5
- import * as VAR3 from '@eslint-react/var';
5
+ import * as VAR4 from '@eslint-react/var';
6
6
  import { AST_NODE_TYPES } from '@typescript-eslint/types';
7
7
  import { match, isMatching } from 'ts-pattern';
8
8
  import { getStaticValue } from '@typescript-eslint/utils/ast-utils';
9
- import '@typescript-eslint/utils';
10
9
 
11
10
  // package.json
12
11
  var name = "eslint-plugin-react-hooks-extra";
13
- var version = "1.15.0-beta.0";
12
+ var version = "1.15.0-beta.8";
14
13
  var createRule = createRuleForPlugin("hooks-extra");
15
14
  function isFromHookCall(name2, context, settings, predicate = F.constTrue) {
16
15
  const hookAlias = settings.additionalHooks?.[name2] ?? [];
17
16
  return (topLevelId) => F.pipe(
18
- VAR3.findVariable(topLevelId, context.sourceCode.getScope(topLevelId)),
19
- O.flatMap(VAR3.getVariableNode(0)),
17
+ VAR4.findVariable(topLevelId, context.sourceCode.getScope(topLevelId)),
18
+ O.flatMap(VAR4.getVariableNode(0)),
20
19
  O.filter(AST2.is(AST_NODE_TYPES.CallExpression)),
21
20
  O.filter(isReactHookCallWithNameAlias(name2, context, hookAlias)),
22
21
  O.exists((call) => predicate(topLevelId, call))
@@ -109,17 +108,7 @@ var no_direct_set_state_in_use_effect_default = createRule({
109
108
  if (!/use\w*Effect/u.test(context.sourceCode.text)) return {};
110
109
  const settings = decodeSettings(context.settings);
111
110
  const additionalHooks = settings.additionalHooks ?? {};
112
- const isUseEffectLikeCall = isReactHookCallWithNameAlias(
113
- "useEffect",
114
- context,
115
- [
116
- "useLayoutEffect",
117
- "useInsertionEffect",
118
- ...additionalHooks.useEffect ?? [],
119
- ...additionalHooks.useLayoutEffect ?? [],
120
- ...additionalHooks.useInsertionEffect ?? []
121
- ]
122
- );
111
+ const isUseEffectLikeCall = isReactHookCallWithNameAlias("useEffect", context, additionalHooks.useEffect ?? []);
123
112
  const isUseStateCall2 = isReactHookCallWithNameAlias("useState", context, additionalHooks.useState ?? []);
124
113
  const isUseMemoCall2 = isReactHookCallWithNameAlias("useMemo", context, additionalHooks.useMemo ?? []);
125
114
  const isUseCallbackCall2 = isReactHookCallWithNameAlias("useCallback", context, additionalHooks.useCallback ?? []);
@@ -227,7 +216,7 @@ var no_direct_set_state_in_use_effect_default = createRule({
227
216
  },
228
217
  "Program:exit"() {
229
218
  const getSetStateCalls = (id, initialScope) => {
230
- const node = O.flatMap(VAR3.findVariable(id, initialScope), VAR3.getVariableNode(0)).pipe(O.getOrNull);
219
+ const node = O.flatMap(VAR4.findVariable(id, initialScope), VAR4.getVariableNode(0)).pipe(O.getOrNull);
231
220
  switch (node?.type) {
232
221
  case AST_NODE_TYPES.FunctionDeclaration:
233
222
  case AST_NODE_TYPES.FunctionExpression:
@@ -278,7 +267,187 @@ var no_direct_set_state_in_use_effect_default = createRule({
278
267
  },
279
268
  defaultOptions: []
280
269
  });
281
- var RULE_NAME2 = "no-redundant-custom-hook";
270
+ var RULE_NAME2 = "no-direct-set-state-in-use-layout-effect";
271
+ var no_direct_set_state_in_use_layout_effect_default = createRule({
272
+ meta: {
273
+ type: "problem",
274
+ docs: {
275
+ description: "disallow direct calls to the 'set' function of 'useState' in 'useLayoutEffect'"
276
+ },
277
+ messages: {
278
+ noDirectSetStateInUseLayoutEffect: "Do not call the 'set' function '{{name}}' of 'useState' directly in 'useLayoutEffect'."
279
+ },
280
+ schema: []
281
+ },
282
+ name: RULE_NAME2,
283
+ create(context) {
284
+ if (!/use\w*Effect/u.test(context.sourceCode.text)) return {};
285
+ const settings = decodeSettings(context.settings);
286
+ const additionalHooks = settings.additionalHooks ?? {};
287
+ const isUseEffectLikeCall = isReactHookCallWithNameAlias(
288
+ "useLayoutEffect",
289
+ context,
290
+ additionalHooks.useLayoutEffect ?? []
291
+ );
292
+ const isUseStateCall2 = isReactHookCallWithNameAlias("useState", context, additionalHooks.useState ?? []);
293
+ const isUseMemoCall2 = isReactHookCallWithNameAlias("useMemo", context, additionalHooks.useMemo ?? []);
294
+ const isUseCallbackCall2 = isReactHookCallWithNameAlias("useCallback", context, additionalHooks.useCallback ?? []);
295
+ const isSetStateCall = isSetFunctionCall(context, settings);
296
+ const isIdFromUseStateCall = isFromUseStateCall(context, settings);
297
+ const functionStack = [];
298
+ const setupFunctionRef = MutRef.make(null);
299
+ const setupFunctionIdentifiers = [];
300
+ const indirectFunctionCalls = [];
301
+ const indirectSetStateCalls = /* @__PURE__ */ new WeakMap();
302
+ const indirectSetStateCallsAsArgs = /* @__PURE__ */ new WeakMap();
303
+ const indirectSetStateCallsAsSetups = /* @__PURE__ */ new Map();
304
+ const indirectSetStateCallsInHooks = /* @__PURE__ */ new WeakMap();
305
+ const onSetupFunctionEnter = (node) => {
306
+ MutRef.set(setupFunctionRef, node);
307
+ };
308
+ const onSetupFunctionExit = (node) => {
309
+ MutRef.update(setupFunctionRef, (current) => current === node ? null : current);
310
+ };
311
+ function isSetupFunction(node) {
312
+ return node.parent?.type === AST_NODE_TYPES.CallExpression && node.parent.callee !== node && isUseEffectLikeCall(node.parent);
313
+ }
314
+ function getCallKind(node) {
315
+ return match(node).when(isUseStateCall2, () => "useState").when(isUseEffectLikeCall, () => "useLayoutEffect").when(isSetStateCall, () => "setState").when(isThenCall, () => "then").otherwise(() => "other");
316
+ }
317
+ function getFunctionKind(node) {
318
+ return match(node).when(isSetupFunction, () => "setup").when(AST2.isFunctionOfImmediatelyInvoked, () => "immediate").otherwise(() => "other");
319
+ }
320
+ return {
321
+ ":function"(node) {
322
+ const functionKind = getFunctionKind(node);
323
+ functionStack.push([node, functionKind]);
324
+ if (functionKind === "setup") onSetupFunctionEnter(node);
325
+ },
326
+ ":function:exit"(node) {
327
+ const [_, functionKind] = functionStack.at(-1) ?? [];
328
+ functionStack.pop();
329
+ if (functionKind === "setup") onSetupFunctionExit(node);
330
+ },
331
+ CallExpression(node) {
332
+ const effectFn = MutRef.get(setupFunctionRef);
333
+ const [parentFn, parentFnKind] = functionStack.at(-1) ?? [];
334
+ if (parentFn?.async) return;
335
+ match(getCallKind(node)).with("setState", () => {
336
+ if (!parentFn) return;
337
+ if (parentFn !== effectFn && parentFnKind !== "immediate") {
338
+ const maybeVd = AST2.traverseUpGuard(node, isVariableDeclaratorFromHookCall);
339
+ if (O.isSome(maybeVd)) {
340
+ const vd = maybeVd.value;
341
+ const calls2 = indirectSetStateCallsInHooks.get(vd.init) ?? [];
342
+ indirectSetStateCallsInHooks.set(vd.init, [...calls2, node]);
343
+ return;
344
+ }
345
+ const calls = indirectSetStateCalls.get(parentFn) ?? [];
346
+ indirectSetStateCalls.set(parentFn, [...calls, node]);
347
+ return;
348
+ }
349
+ context.report({
350
+ messageId: "noDirectSetStateInUseLayoutEffect",
351
+ node,
352
+ data: { name: context.sourceCode.getText(node.callee) }
353
+ });
354
+ }).with("useLayoutEffect", () => {
355
+ const [firstArg] = node.arguments;
356
+ if (AST2.isFunction(firstArg)) return;
357
+ const identifiers = AST2.getNestedIdentifiers(node);
358
+ setupFunctionIdentifiers.push(...identifiers);
359
+ }).with("other", () => {
360
+ const isInSetupFunction = effectFn === parentFn;
361
+ if (!isInSetupFunction) return;
362
+ indirectFunctionCalls.push(node);
363
+ }).otherwise(F.constVoid);
364
+ },
365
+ Identifier(node) {
366
+ if (node.parent.type === AST_NODE_TYPES.CallExpression && node.parent.callee === node) return;
367
+ if (!isIdFromUseStateCall(node)) return;
368
+ switch (node.parent.type) {
369
+ case AST_NODE_TYPES.CallExpression: {
370
+ const [firstArg] = node.parent.arguments;
371
+ if (node !== firstArg) break;
372
+ if (isUseCallbackCall2(node.parent)) {
373
+ const maybeVd = AST2.traverseUpGuard(node.parent, isVariableDeclaratorFromHookCall);
374
+ if (O.isNone(maybeVd)) break;
375
+ const vd = maybeVd.value;
376
+ const calls = indirectSetStateCallsAsArgs.get(vd.init) ?? [];
377
+ indirectSetStateCallsAsArgs.set(vd.init, [...calls, node]);
378
+ }
379
+ if (isUseEffectLikeCall(node.parent)) {
380
+ const calls = indirectSetStateCallsAsArgs.get(node.parent) ?? [];
381
+ indirectSetStateCallsAsSetups.set(node.parent, [...calls, node]);
382
+ }
383
+ break;
384
+ }
385
+ case AST_NODE_TYPES.ArrowFunctionExpression: {
386
+ const parent = node.parent.parent;
387
+ if (parent.type !== AST_NODE_TYPES.CallExpression) break;
388
+ if (!isUseMemoCall2(parent)) break;
389
+ const maybeVd = AST2.traverseUpGuard(parent, isVariableDeclaratorFromHookCall);
390
+ if (O.isNone(maybeVd)) break;
391
+ const vd = maybeVd.value;
392
+ const calls = indirectSetStateCallsAsArgs.get(vd.init) ?? [];
393
+ indirectSetStateCallsAsArgs.set(vd.init, [...calls, node]);
394
+ }
395
+ }
396
+ },
397
+ "Program:exit"() {
398
+ const getSetStateCalls = (id, initialScope) => {
399
+ const node = O.flatMap(VAR4.findVariable(id, initialScope), VAR4.getVariableNode(0)).pipe(O.getOrNull);
400
+ switch (node?.type) {
401
+ case AST_NODE_TYPES.FunctionDeclaration:
402
+ case AST_NODE_TYPES.FunctionExpression:
403
+ case AST_NODE_TYPES.ArrowFunctionExpression:
404
+ return indirectSetStateCalls.get(node) ?? [];
405
+ case AST_NODE_TYPES.CallExpression:
406
+ return indirectSetStateCallsInHooks.get(node) ?? indirectSetStateCallsAsArgs.get(node) ?? [];
407
+ }
408
+ return [];
409
+ };
410
+ for (const [_, calls] of indirectSetStateCallsAsSetups) {
411
+ for (const call of calls) {
412
+ context.report({
413
+ messageId: "noDirectSetStateInUseLayoutEffect",
414
+ node: call,
415
+ data: { name: call.name }
416
+ });
417
+ }
418
+ }
419
+ for (const { callee } of indirectFunctionCalls) {
420
+ if (!("name" in callee)) continue;
421
+ const { name: name2 } = callee;
422
+ const setStateCalls = getSetStateCalls(name2, context.sourceCode.getScope(callee));
423
+ for (const setStateCall of setStateCalls) {
424
+ context.report({
425
+ messageId: "noDirectSetStateInUseLayoutEffect",
426
+ node: setStateCall,
427
+ data: {
428
+ name: AST2.toReadableNodeName(setStateCall, (n) => context.sourceCode.getText(n))
429
+ }
430
+ });
431
+ }
432
+ }
433
+ for (const id of setupFunctionIdentifiers) {
434
+ const setStateCalls = getSetStateCalls(id.name, context.sourceCode.getScope(id));
435
+ for (const setStateCall of setStateCalls) {
436
+ context.report({
437
+ messageId: "noDirectSetStateInUseLayoutEffect",
438
+ node: setStateCall,
439
+ data: {
440
+ name: AST2.toReadableNodeName(setStateCall, (n) => context.sourceCode.getText(n))
441
+ }
442
+ });
443
+ }
444
+ }
445
+ }
446
+ };
447
+ },
448
+ defaultOptions: []
449
+ });
450
+ var RULE_NAME3 = "no-redundant-custom-hook";
282
451
  var no_redundant_custom_hook_default = createRule({
283
452
  meta: {
284
453
  type: "problem",
@@ -290,7 +459,7 @@ var no_redundant_custom_hook_default = createRule({
290
459
  },
291
460
  schema: []
292
461
  },
293
- name: RULE_NAME2,
462
+ name: RULE_NAME3,
294
463
  create(context) {
295
464
  const { ctx, listeners } = useHookCollector();
296
465
  return {
@@ -313,7 +482,7 @@ var no_redundant_custom_hook_default = createRule({
313
482
  },
314
483
  defaultOptions: []
315
484
  });
316
- var RULE_NAME3 = "no-unnecessary-use-callback";
485
+ var RULE_NAME4 = "no-unnecessary-use-callback";
317
486
  var no_unnecessary_use_callback_default = createRule({
318
487
  meta: {
319
488
  type: "problem",
@@ -325,7 +494,7 @@ var no_unnecessary_use_callback_default = createRule({
325
494
  },
326
495
  schema: []
327
496
  },
328
- name: RULE_NAME3,
497
+ name: RULE_NAME4,
329
498
  create(context) {
330
499
  if (!context.sourceCode.text.includes("use")) return {};
331
500
  const alias = decodeSettings(context.settings).additionalHooks?.useCallback ?? [];
@@ -350,8 +519,8 @@ var no_unnecessary_use_callback_default = createRule({
350
519
  const hasEmptyDeps = F.pipe(
351
520
  match(deps).with({ type: AST_NODE_TYPES.ArrayExpression }, O.some).with({ type: AST_NODE_TYPES.Identifier }, (n) => {
352
521
  return F.pipe(
353
- VAR3.findVariable(n.name, initialScope),
354
- O.flatMap(VAR3.getVariableNode(0)),
522
+ VAR4.findVariable(n.name, initialScope),
523
+ O.flatMap(VAR4.getVariableNode(0)),
355
524
  O.filter(AST2.is(AST_NODE_TYPES.ArrayExpression))
356
525
  );
357
526
  }).otherwise(O.none),
@@ -373,13 +542,13 @@ var no_unnecessary_use_callback_default = createRule({
373
542
  return O.some(n);
374
543
  }).with({ type: AST_NODE_TYPES.FunctionExpression }, O.some).with({ type: AST_NODE_TYPES.Identifier }, (n) => {
375
544
  return F.pipe(
376
- VAR3.findVariable(n.name, initialScope),
377
- O.flatMap(VAR3.getVariableNode(0)),
545
+ VAR4.findVariable(n.name, initialScope),
546
+ O.flatMap(VAR4.getVariableNode(0)),
378
547
  O.filter(AST2.isFunction)
379
548
  );
380
549
  }).otherwise(O.none),
381
550
  O.map((n) => context.sourceCode.getScope(n)),
382
- O.map((s) => VAR3.getChidScopes(s).flatMap((x) => x.references)),
551
+ O.map((s) => VAR4.getChidScopes(s).flatMap((x) => x.references)),
383
552
  O.exists((refs) => refs.some((x) => x.resolved?.scope.block === component))
384
553
  );
385
554
  if (isReferencedToComponentScope) return;
@@ -392,7 +561,7 @@ var no_unnecessary_use_callback_default = createRule({
392
561
  },
393
562
  defaultOptions: []
394
563
  });
395
- var RULE_NAME4 = "no-unnecessary-use-memo";
564
+ var RULE_NAME5 = "no-unnecessary-use-memo";
396
565
  var no_unnecessary_use_memo_default = createRule({
397
566
  meta: {
398
567
  type: "problem",
@@ -404,7 +573,7 @@ var no_unnecessary_use_memo_default = createRule({
404
573
  },
405
574
  schema: []
406
575
  },
407
- name: RULE_NAME4,
576
+ name: RULE_NAME5,
408
577
  create(context) {
409
578
  if (!context.sourceCode.text.includes("use")) return {};
410
579
  const alias = decodeSettings(context.settings).additionalHooks?.useMemo ?? [];
@@ -429,8 +598,8 @@ var no_unnecessary_use_memo_default = createRule({
429
598
  const hasEmptyDeps = F.pipe(
430
599
  match(deps).with({ type: AST_NODE_TYPES.ArrayExpression }, O.some).with({ type: AST_NODE_TYPES.Identifier }, (n) => {
431
600
  return F.pipe(
432
- VAR3.findVariable(n.name, initialScope),
433
- O.flatMap(VAR3.getVariableNode(0)),
601
+ VAR4.findVariable(n.name, initialScope),
602
+ O.flatMap(VAR4.getVariableNode(0)),
434
603
  O.filter(AST2.is(AST_NODE_TYPES.ArrayExpression))
435
604
  );
436
605
  }).otherwise(O.none),
@@ -452,13 +621,13 @@ var no_unnecessary_use_memo_default = createRule({
452
621
  return O.some(n);
453
622
  }).with({ type: AST_NODE_TYPES.FunctionExpression }, O.some).with({ type: AST_NODE_TYPES.Identifier }, (n) => {
454
623
  return F.pipe(
455
- VAR3.findVariable(n.name, initialScope),
456
- O.flatMap(VAR3.getVariableNode(0)),
624
+ VAR4.findVariable(n.name, initialScope),
625
+ O.flatMap(VAR4.getVariableNode(0)),
457
626
  O.filter(AST2.isFunction)
458
627
  );
459
628
  }).otherwise(O.none),
460
629
  O.map((n) => context.sourceCode.getScope(n)),
461
- O.map((s) => VAR3.getChidScopes(s).flatMap((x) => x.references)),
630
+ O.map((s) => VAR4.getChidScopes(s).flatMap((x) => x.references)),
462
631
  O.exists((refs) => refs.some((x) => x.resolved?.scope.block === component))
463
632
  );
464
633
  if (isReferencedToComponentScope) return;
@@ -471,7 +640,7 @@ var no_unnecessary_use_memo_default = createRule({
471
640
  },
472
641
  defaultOptions: []
473
642
  });
474
- var RULE_NAME5 = "prefer-use-state-lazy-initialization";
643
+ var RULE_NAME6 = "prefer-use-state-lazy-initialization";
475
644
  var ALLOW_LIST = ["Boolean", "String", "Number"];
476
645
  var prefer_use_state_lazy_initialization_default = createRule({
477
646
  meta: {
@@ -484,7 +653,7 @@ var prefer_use_state_lazy_initialization_default = createRule({
484
653
  },
485
654
  schema: []
486
655
  },
487
- name: RULE_NAME5,
656
+ name: RULE_NAME6,
488
657
  create(context) {
489
658
  if (!context.sourceCode.text.includes("use")) return {};
490
659
  const alias = decodeSettings(context.settings).additionalHooks?.useState ?? [];
@@ -520,6 +689,7 @@ var src_default = {
520
689
  },
521
690
  rules: {
522
691
  "no-direct-set-state-in-use-effect": no_direct_set_state_in_use_effect_default,
692
+ "no-direct-set-state-in-use-layout-effect": no_direct_set_state_in_use_layout_effect_default,
523
693
  "no-redundant-custom-hook": no_redundant_custom_hook_default,
524
694
  "no-unnecessary-use-callback": no_unnecessary_use_callback_default,
525
695
  "no-unnecessary-use-memo": no_unnecessary_use_memo_default,
@@ -528,9 +698,7 @@ var src_default = {
528
698
  /** @deprecated Use `no-redundant-custom-hook` instead */
529
699
  "ensure-custom-hooks-using-other-hooks": no_redundant_custom_hook_default,
530
700
  /** @deprecated Use `no-unnecessary-use-memo` instead */
531
- "ensure-use-memo-has-non-empty-deps": no_unnecessary_use_memo_default,
532
- /** @deprecated Use `no-direct-set-state-in-use-effect` instead */
533
- "no-direct-set-state-in-use-layout-effect": no_direct_set_state_in_use_effect_default
701
+ "ensure-use-memo-has-non-empty-deps": no_unnecessary_use_memo_default
534
702
  }
535
703
  };
536
704
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-react-hooks-extra",
3
- "version": "1.15.0-beta.0",
3
+ "version": "1.15.0-beta.8",
4
4
  "description": "ESLint React's ESLint plugin for React Hooks related rules.",
5
5
  "keywords": [
6
6
  "eslint",
@@ -41,18 +41,18 @@
41
41
  "./package.json"
42
42
  ],
43
43
  "dependencies": {
44
- "@typescript-eslint/scope-manager": "^8.8.0",
45
- "@typescript-eslint/type-utils": "^8.8.0",
46
- "@typescript-eslint/types": "^8.8.0",
47
- "@typescript-eslint/utils": "^8.8.0",
44
+ "@typescript-eslint/scope-manager": "^8.8.1",
45
+ "@typescript-eslint/type-utils": "^8.8.1",
46
+ "@typescript-eslint/types": "^8.8.1",
47
+ "@typescript-eslint/utils": "^8.8.1",
48
48
  "ts-pattern": "^5.4.0",
49
- "@eslint-react/ast": "1.15.0-beta.0",
50
- "@eslint-react/core": "1.15.0-beta.0",
51
- "@eslint-react/shared": "1.15.0-beta.0",
52
- "@eslint-react/types": "1.15.0-beta.0",
53
- "@eslint-react/jsx": "1.15.0-beta.0",
54
- "@eslint-react/var": "1.15.0-beta.0",
55
- "@eslint-react/tools": "1.15.0-beta.0"
49
+ "@eslint-react/ast": "1.15.0-beta.8",
50
+ "@eslint-react/jsx": "1.15.0-beta.8",
51
+ "@eslint-react/core": "1.15.0-beta.8",
52
+ "@eslint-react/shared": "1.15.0-beta.8",
53
+ "@eslint-react/tools": "1.15.0-beta.8",
54
+ "@eslint-react/var": "1.15.0-beta.8",
55
+ "@eslint-react/types": "1.15.0-beta.8"
56
56
  },
57
57
  "devDependencies": {
58
58
  "@types/react": "^18.3.11",