eslint-plugin-react-web-api 3.0.0-next.6 → 3.0.0-next.60

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.ts CHANGED
@@ -1,20 +1,9 @@
1
- import * as _eslint_react_shared0 from "@eslint-react/shared";
1
+ import { ESLint, Linter } from "eslint";
2
2
 
3
3
  //#region src/index.d.ts
4
- declare const _default: {
5
- configs: {
6
- recommended: {
7
- plugins: {};
8
- name?: string;
9
- rules?: Record<string, _eslint_react_shared0.RuleConfig>;
10
- settings?: _eslint_react_shared0.SettingsConfig;
11
- };
12
- };
13
- meta: {
14
- name: string;
15
- version: string;
16
- };
17
- rules: Record<string, _eslint_react_shared0.CompatibleRule>;
4
+ type ConfigName = "recommended";
5
+ declare const finalPlugin: ESLint.Plugin & {
6
+ configs: Record<ConfigName, Linter.Config>;
18
7
  };
19
8
  //#endregion
20
- export { _default as default };
9
+ export { finalPlugin as default };
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
- import { DEFAULT_ESLINT_REACT_SETTINGS, WEBSITE_URL, getConfigAdapters } from "@eslint-react/shared";
1
+ import { DEFAULT_ESLINT_REACT_SETTINGS, WEBSITE_URL, defineRuleListener } from "@eslint-react/shared";
2
2
  import * as ast from "@eslint-react/ast";
3
3
  import * as core from "@eslint-react/core";
4
4
  import { dual, or, unit } from "@eslint-react/eff";
5
- import { findEnclosingAssignmentTarget, findProperty, findVariable, getVariableDefinitionNode, isAssignmentTargetEqual, isNodeEqual } from "@eslint-react/var";
5
+ import { findEnclosingAssignmentTarget, findVariable, getVariableInitializer, isAssignmentTargetEqual, isValueEqual } from "@eslint-react/var";
6
6
  import { AST_NODE_TYPES, ESLintUtils } from "@typescript-eslint/utils";
7
7
  import { getStaticValue } from "@typescript-eslint/utils/ast-utils";
8
8
  import { P, isMatching, match } from "ts-pattern";
@@ -24,26 +24,10 @@ var __exportAll = (all, no_symbols) => {
24
24
  return target;
25
25
  };
26
26
 
27
- //#endregion
28
- //#region src/configs/recommended.ts
29
- var recommended_exports = /* @__PURE__ */ __exportAll({
30
- name: () => name$1,
31
- rules: () => rules,
32
- settings: () => settings
33
- });
34
- const name$1 = "react-web-api/recommended";
35
- const rules = {
36
- "react-web-api/no-leaked-event-listener": "warn",
37
- "react-web-api/no-leaked-interval": "warn",
38
- "react-web-api/no-leaked-resize-observer": "warn",
39
- "react-web-api/no-leaked-timeout": "warn"
40
- };
41
- const settings = { "react-x": DEFAULT_ESLINT_REACT_SETTINGS };
42
-
43
27
  //#endregion
44
28
  //#region package.json
45
- var name = "eslint-plugin-react-web-api";
46
- var version = "3.0.0-next.6";
29
+ var name$1 = "eslint-plugin-react-web-api";
30
+ var version = "3.0.0-next.60";
47
31
 
48
32
  //#endregion
49
33
  //#region src/types/component-phase.ts
@@ -64,7 +48,7 @@ function getDocsUrl(ruleName) {
64
48
  const createRule = ESLintUtils.RuleCreator(getDocsUrl);
65
49
 
66
50
  //#endregion
67
- //#region src/rules/no-leaked-event-listener.ts
51
+ //#region src/rules/no-leaked-event-listener/no-leaked-event-listener.ts
68
52
  const RULE_NAME$3 = "no-leaked-event-listener";
69
53
  const defaultOptions = {
70
54
  capture: false,
@@ -83,19 +67,16 @@ function getFunctionKind$1(node) {
83
67
  function getSignalValueExpression(node, initialScope) {
84
68
  if (node == null) return unit;
85
69
  switch (node.type) {
86
- case AST_NODE_TYPES.Identifier: return getSignalValueExpression(getVariableDefinitionNode(findVariable(node, initialScope), 0), initialScope);
70
+ case AST_NODE_TYPES.Identifier: return getSignalValueExpression(getVariableInitializer(findVariable(node, initialScope), 0), initialScope);
87
71
  case AST_NODE_TYPES.MemberExpression: return node;
88
72
  default: return unit;
89
73
  }
90
74
  }
91
75
  function getOptions(node, initialScope) {
92
- function findProp(properties, propName) {
93
- return findProperty(propName, properties, initialScope);
94
- }
95
76
  function getOpts(node) {
96
77
  switch (node.type) {
97
78
  case AST_NODE_TYPES.Identifier: {
98
- const variableNode = getVariableDefinitionNode(findVariable(node, initialScope), 0);
79
+ const variableNode = getVariableInitializer(findVariable(node, initialScope), 0);
99
80
  if (variableNode?.type === AST_NODE_TYPES.ObjectExpression) return getOpts(variableNode);
100
81
  return defaultOptions;
101
82
  }
@@ -104,14 +85,14 @@ function getOptions(node, initialScope) {
104
85
  capture: Boolean(node.value)
105
86
  };
106
87
  case AST_NODE_TYPES.ObjectExpression: {
107
- const vCapture = match(findProp(node.properties, "capture")).with(P.nullish, () => false).with({ type: AST_NODE_TYPES.Property }, (prop) => {
88
+ const vCapture = match(ast.findProperty(node.properties, "capture")).with(P.nullish, () => false).with({ type: AST_NODE_TYPES.Property }, (prop) => {
108
89
  const value = prop.value;
109
90
  switch (value.type) {
110
91
  case AST_NODE_TYPES.Literal: return Boolean(value.value);
111
92
  default: return Boolean(getStaticValue(value, initialScope)?.value);
112
93
  }
113
94
  }).otherwise(() => false);
114
- const pSignal = findProp(node.properties, "signal");
95
+ const pSignal = ast.findProperty(node.properties, "signal");
115
96
  return {
116
97
  capture: vCapture,
117
98
  signal: pSignal?.type === AST_NODE_TYPES.Property ? getSignalValueExpression(pSignal.value, initialScope) : unit
@@ -154,19 +135,19 @@ function create$3(context) {
154
135
  const { type: aType, callee: aCallee, capture: aCapture, listener: aListener, phase: aPhase } = aEntry;
155
136
  const { type: rType, callee: rCallee, capture: rCapture, listener: rListener, phase: rPhase } = rEntry;
156
137
  if (!isInversePhase(aPhase, rPhase)) return false;
157
- return isSameObject(aCallee, rCallee) && ast.isNodeEqual(aListener, rListener) && isNodeEqual(aType, rType, [context.sourceCode.getScope(aType), context.sourceCode.getScope(rType)]) && aCapture === rCapture;
138
+ return isSameObject(aCallee, rCallee) && ast.isNodeEqual(aListener, rListener) && isValueEqual(aType, rType, [context.sourceCode.getScope(aType), context.sourceCode.getScope(rType)]) && aCapture === rCapture;
158
139
  }
159
140
  function checkInlineFunction(node, callKind, options) {
160
141
  const listener = node.arguments.at(1);
161
142
  if (!ast.isFunction(listener)) return;
162
143
  if (options.signal != null) return;
163
144
  context.report({
145
+ data: { eventMethodKind: callKind },
164
146
  messageId: "unexpectedInlineFunction",
165
- node: listener,
166
- data: { eventMethodKind: callKind }
147
+ node: listener
167
148
  });
168
149
  }
169
- return {
150
+ return defineRuleListener({
170
151
  [":function"](node) {
171
152
  const kind = getFunctionKind$1(node);
172
153
  fEntries.push({
@@ -191,10 +172,10 @@ function create$3(context) {
191
172
  aEntries.push({
192
173
  ...opts,
193
174
  type,
194
- node,
195
175
  callee,
196
176
  listener,
197
177
  method: "addEventListener",
178
+ node,
198
179
  phase: fKind
199
180
  });
200
181
  }).with("removeEventListener", (callKind) => {
@@ -206,10 +187,10 @@ function create$3(context) {
206
187
  rEntries.push({
207
188
  ...opts,
208
189
  type,
209
- node,
210
190
  callee,
211
191
  listener,
212
192
  method: "removeEventListener",
193
+ node,
213
194
  phase: fKind
214
195
  });
215
196
  }).with("abort", () => {
@@ -224,9 +205,9 @@ function create$3(context) {
224
205
  case "setup":
225
206
  case "cleanup":
226
207
  context.report({
208
+ data: { effectMethodKind: "useEffect" },
227
209
  messageId: "expectedRemoveEventListenerInCleanup",
228
- node: aEntry.node,
229
- data: { effectMethodKind: "useEffect" }
210
+ node: aEntry.node
230
211
  });
231
212
  continue;
232
213
  case "mount":
@@ -239,11 +220,11 @@ function create$3(context) {
239
220
  }
240
221
  }
241
222
  }
242
- };
223
+ });
243
224
  }
244
225
 
245
226
  //#endregion
246
- //#region src/rules/no-leaked-interval.ts
227
+ //#region src/rules/no-leaked-interval/no-leaked-interval.ts
247
228
  const RULE_NAME$2 = "no-leaked-interval";
248
229
  function getCallKind$2(node) {
249
230
  switch (true) {
@@ -275,7 +256,7 @@ function create$2(context) {
275
256
  function isInverseEntry(a, b) {
276
257
  return isAssignmentTargetEqual(context, a.timerId, b.timerId);
277
258
  }
278
- return {
259
+ return defineRuleListener({
279
260
  [":function"](node) {
280
261
  const kind = getPhaseKindOfFunction(node) ?? "other";
281
262
  fEntries.push({
@@ -302,8 +283,8 @@ function create$2(context) {
302
283
  }
303
284
  sEntries.push({
304
285
  kind: "interval",
305
- node,
306
286
  callee: node.callee,
287
+ node,
307
288
  phase: fEntry.kind,
308
289
  timerId: intervalIdNode
309
290
  });
@@ -317,8 +298,8 @@ function create$2(context) {
317
298
  if (intervalIdNode == null) break;
318
299
  cEntries.push({
319
300
  kind: "interval",
320
- node,
321
301
  callee: node.callee,
302
+ node,
322
303
  phase: fEntry.kind,
323
304
  timerId: intervalIdNode
324
305
  });
@@ -333,34 +314,34 @@ function create$2(context) {
333
314
  case "setup":
334
315
  case "cleanup":
335
316
  context.report({
317
+ data: { kind: "useEffect" },
336
318
  messageId: "expectedClearIntervalInCleanup",
337
- node: sEntry.node,
338
- data: { kind: "useEffect" }
319
+ node: sEntry.node
339
320
  });
340
321
  continue;
341
322
  case "mount":
342
323
  case "unmount":
343
324
  context.report({
325
+ data: { kind: "componentDidMount" },
344
326
  messageId: "expectedClearIntervalInUnmount",
345
- node: sEntry.node,
346
- data: { kind: "componentDidMount" }
327
+ node: sEntry.node
347
328
  });
348
329
  continue;
349
330
  }
350
331
  }
351
332
  }
352
- };
333
+ });
353
334
  }
354
335
 
355
336
  //#endregion
356
- //#region src/rules/no-leaked-resize-observer.ts
337
+ //#region src/rules/no-leaked-resize-observer/no-leaked-resize-observer.ts
357
338
  const RULE_NAME$1 = "no-leaked-resize-observer";
358
339
  function isNewResizeObserver(node) {
359
340
  return node?.type === AST_NODE_TYPES.NewExpression && node.callee.type === AST_NODE_TYPES.Identifier && node.callee.name === "ResizeObserver";
360
341
  }
361
342
  function isFromObserver(context, node) {
362
343
  switch (true) {
363
- case node.type === AST_NODE_TYPES.Identifier: return isNewResizeObserver(getVariableDefinitionNode(findVariable(node, context.sourceCode.getScope(node)), 0));
344
+ case node.type === AST_NODE_TYPES.Identifier: return isNewResizeObserver(getVariableInitializer(findVariable(node, context.sourceCode.getScope(node)), 0));
364
345
  case node.type === AST_NODE_TYPES.MemberExpression: return isFromObserver(context, node.object);
365
346
  default: return false;
366
347
  }
@@ -397,7 +378,7 @@ function create$1(context) {
397
378
  const oEntries = [];
398
379
  const uEntries = [];
399
380
  const dEntries = [];
400
- return {
381
+ return defineRuleListener({
401
382
  [":function"](node) {
402
383
  const kind = getFunctionKind(node);
403
384
  fEntries.push({
@@ -416,9 +397,9 @@ function create$1(context) {
416
397
  match(getCallKind$1(context, node)).with("disconnect", () => {
417
398
  dEntries.push({
418
399
  kind: "ResizeObserver",
419
- node,
420
400
  callee: node.callee,
421
401
  method: "disconnect",
402
+ node,
422
403
  observer: object,
423
404
  phase: fKind
424
405
  });
@@ -427,10 +408,10 @@ function create$1(context) {
427
408
  if (element == null) return;
428
409
  oEntries.push({
429
410
  kind: "ResizeObserver",
430
- node,
431
411
  callee: node.callee,
432
412
  element,
433
413
  method: "observe",
414
+ node,
434
415
  observer: object,
435
416
  phase: fKind
436
417
  });
@@ -439,10 +420,10 @@ function create$1(context) {
439
420
  if (element == null) return;
440
421
  uEntries.push({
441
422
  kind: "ResizeObserver",
442
- node,
443
423
  callee: node.callee,
444
424
  element,
445
425
  method: "unobserve",
426
+ node,
446
427
  observer: object,
447
428
  phase: fKind
448
429
  });
@@ -491,11 +472,11 @@ function create$1(context) {
491
472
  }
492
473
  }
493
474
  }
494
- };
475
+ });
495
476
  }
496
477
 
497
478
  //#endregion
498
- //#region src/rules/no-leaked-timeout.ts
479
+ //#region src/rules/no-leaked-timeout/no-leaked-timeout.ts
499
480
  const RULE_NAME = "no-leaked-timeout";
500
481
  function getCallKind(node) {
501
482
  switch (true) {
@@ -527,7 +508,7 @@ function create(context) {
527
508
  function isInverseEntry(a, b) {
528
509
  return isAssignmentTargetEqual(context, a.timerId, b.timerId);
529
510
  }
530
- return {
511
+ return defineRuleListener({
531
512
  [":function"](node) {
532
513
  const kind = getPhaseKindOfFunction(node) ?? "other";
533
514
  fEntries.push({
@@ -553,8 +534,8 @@ function create(context) {
553
534
  }
554
535
  sEntries.push({
555
536
  kind: "timeout",
556
- node,
557
537
  callee: node.callee,
538
+ node,
558
539
  phase: fEntry.kind,
559
540
  timerId: timeoutIdNode
560
541
  });
@@ -565,8 +546,8 @@ function create(context) {
565
546
  if (timeoutIdNode == null) break;
566
547
  rEntries.push({
567
548
  kind: "timeout",
568
- node,
569
549
  callee: node.callee,
550
+ node,
570
551
  phase: fEntry.kind,
571
552
  timerId: timeoutIdNode
572
553
  });
@@ -581,30 +562,30 @@ function create(context) {
581
562
  case "setup":
582
563
  case "cleanup":
583
564
  context.report({
565
+ data: { kind: "useEffect" },
584
566
  messageId: "expectedClearTimeoutInCleanup",
585
- node: sEntry.node,
586
- data: { kind: "useEffect" }
567
+ node: sEntry.node
587
568
  });
588
569
  continue;
589
570
  case "mount":
590
571
  case "unmount":
591
572
  context.report({
573
+ data: { kind: "componentDidMount" },
592
574
  messageId: "expectedClearTimeoutInUnmount",
593
- node: sEntry.node,
594
- data: { kind: "componentDidMount" }
575
+ node: sEntry.node
595
576
  });
596
577
  continue;
597
578
  }
598
579
  }
599
580
  }
600
- };
581
+ });
601
582
  }
602
583
 
603
584
  //#endregion
604
585
  //#region src/plugin.ts
605
586
  const plugin = {
606
587
  meta: {
607
- name,
588
+ name: name$1,
608
589
  version
609
590
  },
610
591
  rules: {
@@ -615,13 +596,30 @@ const plugin = {
615
596
  }
616
597
  };
617
598
 
599
+ //#endregion
600
+ //#region src/configs/recommended.ts
601
+ var recommended_exports = /* @__PURE__ */ __exportAll({
602
+ name: () => name,
603
+ plugins: () => plugins,
604
+ rules: () => rules,
605
+ settings: () => settings
606
+ });
607
+ const name = "react-web-api/recommended";
608
+ const rules = {
609
+ "react-web-api/no-leaked-event-listener": "warn",
610
+ "react-web-api/no-leaked-interval": "warn",
611
+ "react-web-api/no-leaked-resize-observer": "warn",
612
+ "react-web-api/no-leaked-timeout": "warn"
613
+ };
614
+ const plugins = { "react-web-api": plugin };
615
+ const settings = { "react-x": DEFAULT_ESLINT_REACT_SETTINGS };
616
+
618
617
  //#endregion
619
618
  //#region src/index.ts
620
- const { toFlatConfig } = getConfigAdapters("react-web-api", plugin);
621
- var src_default = {
619
+ const finalPlugin = {
622
620
  ...plugin,
623
- configs: { ["recommended"]: toFlatConfig(recommended_exports) }
621
+ configs: { ["recommended"]: recommended_exports }
624
622
  };
625
623
 
626
624
  //#endregion
627
- export { src_default as default };
625
+ export { finalPlugin as default };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-react-web-api",
3
- "version": "3.0.0-next.6",
3
+ "version": "3.0.0-next.60",
4
4
  "description": "ESLint React's ESLint plugin for interacting with Web APIs",
5
5
  "keywords": [
6
6
  "react",
@@ -43,16 +43,17 @@
43
43
  "@typescript-eslint/utils": "canary",
44
44
  "birecord": "^0.1.1",
45
45
  "ts-pattern": "^5.9.0",
46
- "@eslint-react/eff": "3.0.0-next.6",
47
- "@eslint-react/ast": "3.0.0-next.6",
48
- "@eslint-react/shared": "3.0.0-next.6",
49
- "@eslint-react/core": "3.0.0-next.6",
50
- "@eslint-react/var": "3.0.0-next.6"
46
+ "@eslint-react/ast": "3.0.0-next.60",
47
+ "@eslint-react/shared": "3.0.0-next.60",
48
+ "@eslint-react/eff": "3.0.0-next.60",
49
+ "@eslint-react/var": "3.0.0-next.60",
50
+ "@eslint-react/core": "3.0.0-next.60"
51
51
  },
52
52
  "devDependencies": {
53
53
  "@types/react": "^19.2.14",
54
54
  "@types/react-dom": "^19.2.3",
55
- "tsdown": "^0.20.3",
55
+ "eslint": "^10.0.2",
56
+ "tsdown": "^0.21.0-beta.2",
56
57
  "@local/configs": "0.0.0"
57
58
  },
58
59
  "peerDependencies": {
@@ -68,6 +69,6 @@
68
69
  "scripts": {
69
70
  "build": "tsdown",
70
71
  "lint:publish": "publint",
71
- "lint:ts": "tsc --noEmit"
72
+ "lint:ts": "tsl"
72
73
  }
73
74
  }