eslint-plugin-rxjs-x 0.9.0 → 0.9.2

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/README.md CHANGED
@@ -128,7 +128,7 @@ The package includes the following rules.
128
128
  | [no-async-subscribe](docs/rules/no-async-subscribe.md) | Disallow passing `async` functions to `subscribe`. | ✅ 🔒 | | | 💭 | |
129
129
  | [no-compat](docs/rules/no-compat.md) | Disallow the `rxjs-compat` package. | | | | | ❌ |
130
130
  | [no-connectable](docs/rules/no-connectable.md) | Disallow operators that return connectable observables. | | | | 💭 | |
131
- | [no-create](docs/rules/no-create.md) | Disallow the static `Observable.create` function. | ✅ 🔒 | | | 💭 | |
131
+ | [no-create](docs/rules/no-create.md) | Disallow the static `Observable.create` and `Subject.create` functions. | ✅ 🔒 | | | 💭 | |
132
132
  | [no-cyclic-action](docs/rules/no-cyclic-action.md) | Disallow cyclic actions in effects and epics. | | | | 💭 | |
133
133
  | [no-explicit-generics](docs/rules/no-explicit-generics.md) | Disallow unnecessary explicit generic type arguments. | | | | 💭 | |
134
134
  | [no-exposed-subjects](docs/rules/no-exposed-subjects.md) | Disallow public and protected subjects. | 🔒 | | | 💭 | |
@@ -142,7 +142,7 @@ The package includes the following rules.
142
142
  | [no-ignored-subscribe](docs/rules/no-ignored-subscribe.md) | Disallow calling `subscribe` without specifying arguments. | | | | 💭 | |
143
143
  | [no-ignored-subscription](docs/rules/no-ignored-subscription.md) | Disallow ignoring the subscription returned by `subscribe`. | | | | 💭 | |
144
144
  | [no-ignored-takewhile-value](docs/rules/no-ignored-takewhile-value.md) | Disallow ignoring the value within `takeWhile`. | ✅ 🔒 | | | | |
145
- | [no-implicit-any-catch](docs/rules/no-implicit-any-catch.md) | Disallow implicit `any` error parameters in `catchError` operators. | ✅ 🔒 | 🔧 | 💡 | 💭 | |
145
+ | [no-implicit-any-catch](docs/rules/no-implicit-any-catch.md) | Disallow implicit `any` error parameters in `catchError`, `subscribe`, and `tap`. | ✅ 🔒 | 🔧 | 💡 | 💭 | |
146
146
  | [no-index](docs/rules/no-index.md) | Disallow importing index modules. | ✅ 🔒 | | | | |
147
147
  | [no-internal](docs/rules/no-internal.md) | Disallow importing internal modules. | ✅ 🔒 | 🔧 | 💡 | | |
148
148
  | [no-misused-observables](docs/rules/no-misused-observables.md) | Disallow Observables in places not designed to handle them. | 🔒 | | | 💭 | |
@@ -167,6 +167,6 @@ The package includes the following rules.
167
167
  | [prefer-observer](docs/rules/prefer-observer.md) | Disallow passing separate handlers to `subscribe` and `tap`. | ✅ 🔒 | 🔧 | 💡 | 💭 | |
168
168
  | [prefer-root-operators](docs/rules/prefer-root-operators.md) | Disallow importing operators from `rxjs/operators`. | ✅ 🔒 | 🔧 | 💡 | | |
169
169
  | [suffix-subjects](docs/rules/suffix-subjects.md) | Enforce the use of a suffix in subject identifiers. | | | | 💭 | |
170
- | [throw-error](docs/rules/throw-error.md) | Enforce passing only `Error` values to `throwError` or `Subject.error`. | ✅ 🔒 | | | 💭 | |
170
+ | [throw-error](docs/rules/throw-error.md) | Enforce passing only `Error` values to `throwError` or `Subject.error`. | ✅ 🔒 | | 💡 | 💭 | |
171
171
 
172
172
  <!-- end auto-generated rules list -->
package/dist/index.d.mts CHANGED
@@ -18,12 +18,13 @@ declare const allRules: {
18
18
  description: "Disallow banned operators.";
19
19
  requiresTypeChecking: true;
20
20
  }, TSESLint.RuleListener>;
21
- finnish: TSESLint.RuleModule<"shouldBeFinnish" | "shouldNotBeFinnish", readonly {
21
+ finnish: TSESLint.RuleModule<"shouldBeFinnish" | "shouldBeFinnishProperty" | "shouldNotBeFinnish", readonly {
22
22
  functions?: boolean;
23
23
  methods?: boolean;
24
24
  names?: Record<string, boolean>;
25
25
  parameters?: boolean;
26
26
  properties?: boolean;
27
+ objects?: boolean;
27
28
  strict?: boolean;
28
29
  types?: Record<string, boolean>;
29
30
  variables?: boolean;
@@ -49,8 +50,8 @@ declare const allRules: {
49
50
  description: "Disallow operators that return connectable observables.";
50
51
  requiresTypeChecking: true;
51
52
  }, TSESLint.RuleListener>;
52
- 'no-create': TSESLint.RuleModule<"forbidden", [], {
53
- description: "Disallow the static `Observable.create` function.";
53
+ 'no-create': TSESLint.RuleModule<"forbidden" | "forbiddenSubject", [], {
54
+ description: "Disallow the static `Observable.create` and `Subject.create` functions.";
54
55
  recommended: "recommended";
55
56
  requiresTypeChecking: true;
56
57
  }, TSESLint.RuleListener>;
@@ -119,10 +120,11 @@ declare const allRules: {
119
120
  description: "Disallow ignoring the value within `takeWhile`.";
120
121
  recommended: "recommended";
121
122
  }, TSESLint.RuleListener>;
122
- 'no-implicit-any-catch': TSESLint.RuleModule<"explicitAny" | "implicitAny" | "narrowed" | "suggestExplicitUnknown" | "suggestExplicitAny", readonly {
123
+ 'no-implicit-any-catch': TSESLint.RuleModule<"explicitAny" | "implicitAny" | "narrowed" | "narrowedAllowError" | "suggestExplicitUnknown" | "suggestExplicitAny" | "suggestExplicitError", readonly {
123
124
  allowExplicitAny?: boolean;
125
+ allowExplicitError?: boolean;
124
126
  }[], {
125
- description: "Disallow implicit `any` error parameters in `catchError` operators.";
127
+ description: "Disallow implicit `any` error parameters in `catchError`, `subscribe`, and `tap`.";
126
128
  recommended: {
127
129
  recommended: true;
128
130
  strict: [{
@@ -266,7 +268,7 @@ declare const allRules: {
266
268
  description: "Enforce the use of a suffix in subject identifiers.";
267
269
  requiresTypeChecking: true;
268
270
  }, TSESLint.RuleListener>;
269
- 'throw-error': TSESLint.RuleModule<"forbidden", readonly {
271
+ 'throw-error': TSESLint.RuleModule<"forbidden" | "suggestErrorConstructor", readonly {
270
272
  allowThrowingAny?: boolean;
271
273
  allowThrowingUnknown?: boolean;
272
274
  }[], {
package/dist/index.d.ts CHANGED
@@ -18,12 +18,13 @@ declare const allRules: {
18
18
  description: "Disallow banned operators.";
19
19
  requiresTypeChecking: true;
20
20
  }, TSESLint.RuleListener>;
21
- finnish: TSESLint.RuleModule<"shouldBeFinnish" | "shouldNotBeFinnish", readonly {
21
+ finnish: TSESLint.RuleModule<"shouldBeFinnish" | "shouldBeFinnishProperty" | "shouldNotBeFinnish", readonly {
22
22
  functions?: boolean;
23
23
  methods?: boolean;
24
24
  names?: Record<string, boolean>;
25
25
  parameters?: boolean;
26
26
  properties?: boolean;
27
+ objects?: boolean;
27
28
  strict?: boolean;
28
29
  types?: Record<string, boolean>;
29
30
  variables?: boolean;
@@ -49,8 +50,8 @@ declare const allRules: {
49
50
  description: "Disallow operators that return connectable observables.";
50
51
  requiresTypeChecking: true;
51
52
  }, TSESLint.RuleListener>;
52
- 'no-create': TSESLint.RuleModule<"forbidden", [], {
53
- description: "Disallow the static `Observable.create` function.";
53
+ 'no-create': TSESLint.RuleModule<"forbidden" | "forbiddenSubject", [], {
54
+ description: "Disallow the static `Observable.create` and `Subject.create` functions.";
54
55
  recommended: "recommended";
55
56
  requiresTypeChecking: true;
56
57
  }, TSESLint.RuleListener>;
@@ -119,10 +120,11 @@ declare const allRules: {
119
120
  description: "Disallow ignoring the value within `takeWhile`.";
120
121
  recommended: "recommended";
121
122
  }, TSESLint.RuleListener>;
122
- 'no-implicit-any-catch': TSESLint.RuleModule<"explicitAny" | "implicitAny" | "narrowed" | "suggestExplicitUnknown" | "suggestExplicitAny", readonly {
123
+ 'no-implicit-any-catch': TSESLint.RuleModule<"explicitAny" | "implicitAny" | "narrowed" | "narrowedAllowError" | "suggestExplicitUnknown" | "suggestExplicitAny" | "suggestExplicitError", readonly {
123
124
  allowExplicitAny?: boolean;
125
+ allowExplicitError?: boolean;
124
126
  }[], {
125
- description: "Disallow implicit `any` error parameters in `catchError` operators.";
127
+ description: "Disallow implicit `any` error parameters in `catchError`, `subscribe`, and `tap`.";
126
128
  recommended: {
127
129
  recommended: true;
128
130
  strict: [{
@@ -266,7 +268,7 @@ declare const allRules: {
266
268
  description: "Enforce the use of a suffix in subject identifiers.";
267
269
  requiresTypeChecking: true;
268
270
  }, TSESLint.RuleListener>;
269
- 'throw-error': TSESLint.RuleModule<"forbidden", readonly {
271
+ 'throw-error': TSESLint.RuleModule<"forbidden" | "suggestErrorConstructor", readonly {
270
272
  allowThrowingAny?: boolean;
271
273
  allowThrowingUnknown?: boolean;
272
274
  }[], {
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }// package.json
2
2
  var name = "eslint-plugin-rxjs-x";
3
- var version = "0.9.0";
3
+ var version = "0.9.2";
4
4
 
5
5
  // src/configs/recommended.ts
6
6
  var createRecommendedConfig = (plugin2) => ({
@@ -274,6 +274,9 @@ function isJSXExpressionContainer(node) {
274
274
  function isLiteral(node) {
275
275
  return node.type === _utils.AST_NODE_TYPES.Literal;
276
276
  }
277
+ function isTemplateLiteral(node) {
278
+ return node.type === _utils.AST_NODE_TYPES.TemplateLiteral;
279
+ }
277
280
  function isMemberExpression(node) {
278
281
  return node.type === _utils.AST_NODE_TYPES.MemberExpression;
279
282
  }
@@ -298,12 +301,21 @@ function isPropertyDefinition(node) {
298
301
  function isSpreadElement(node) {
299
302
  return node.type === _utils.AST_NODE_TYPES.SpreadElement;
300
303
  }
304
+ function isTSAsExpression(node) {
305
+ return node.type === _utils.AST_NODE_TYPES.TSAsExpression;
306
+ }
307
+ function isTSSatisfiesExpression(node) {
308
+ return node.type === _utils.AST_NODE_TYPES.TSSatisfiesExpression;
309
+ }
301
310
  function isUnaryExpression(node) {
302
311
  return node.type === _utils.AST_NODE_TYPES.UnaryExpression;
303
312
  }
304
313
  function isUnionType(node) {
305
314
  return node.type === _utils.AST_NODE_TYPES.TSUnionType;
306
315
  }
316
+ function isVariableDeclarator(node) {
317
+ return node.type === _utils.AST_NODE_TYPES.VariableDeclarator;
318
+ }
307
319
 
308
320
  // src/etc/get-type-services.ts
309
321
  function getTypeServices(context) {
@@ -583,6 +595,7 @@ var banOperatorsRule = ruleCreator({
583
595
  // src/rules/finnish.ts
584
596
 
585
597
  var defaultOptions3 = [];
598
+ var baseShouldBeFinnish = "Finnish notation should be used here.";
586
599
  var finnishRule = ruleCreator({
587
600
  defaultOptions: defaultOptions3,
588
601
  meta: {
@@ -591,7 +604,8 @@ var finnishRule = ruleCreator({
591
604
  requiresTypeChecking: true
592
605
  },
593
606
  messages: {
594
- shouldBeFinnish: "Finnish notation should be used here.",
607
+ shouldBeFinnish: baseShouldBeFinnish,
608
+ shouldBeFinnishProperty: `${baseShouldBeFinnish} Add a type annotation, assertion, or 'satisfies' to silence this rule.`,
595
609
  shouldNotBeFinnish: "Finnish notation should not be used here."
596
610
  },
597
611
  schema: [
@@ -601,7 +615,8 @@ var finnishRule = ruleCreator({
601
615
  methods: { type: "boolean", description: "Require for methods." },
602
616
  names: { type: "object", description: "Enforce for specific names. Keys are a RegExp, values are a boolean." },
603
617
  parameters: { type: "boolean", description: "Require for parameters." },
604
- properties: { type: "boolean", description: "Require for properties." },
618
+ properties: { type: "boolean", description: 'Require for properties, except object literal keys (see "objects" option).' },
619
+ objects: { type: "boolean", description: "Require for object literal keys." },
605
620
  strict: { type: "boolean", description: "Disallow Finnish notation for non-Observables." },
606
621
  types: { type: "object", description: "Enforce for specific types. Keys are a RegExp, values are a boolean." },
607
622
  variables: { type: "boolean", description: "Require for variables." }
@@ -627,6 +642,7 @@ var finnishRule = ruleCreator({
627
642
  methods: true,
628
643
  parameters: true,
629
644
  properties: true,
645
+ objects: true,
630
646
  variables: true,
631
647
  ...config
632
648
  };
@@ -656,7 +672,7 @@ var finnishRule = ruleCreator({
656
672
  validate: false
657
673
  });
658
674
  }
659
- function checkNode(nameNode, typeNode) {
675
+ function checkNode(nameNode, typeNode, shouldMessage = "shouldBeFinnish") {
660
676
  const tsNode = esTreeNodeToTSNodeMap.get(nameNode);
661
677
  const text = tsNode.getText();
662
678
  const hasFinnish = text.endsWith("$");
@@ -667,7 +683,7 @@ var finnishRule = ruleCreator({
667
683
  } : () => {
668
684
  context.report({
669
685
  loc: getLoc(tsNode),
670
- messageId: "shouldBeFinnish"
686
+ messageId: shouldMessage
671
687
  });
672
688
  };
673
689
  const shouldNotBeFinnish = hasFinnish ? () => {
@@ -718,7 +734,7 @@ var finnishRule = ruleCreator({
718
734
  if (!found) {
719
735
  return;
720
736
  }
721
- if (!validate.variables && found.type === _utils.AST_NODE_TYPES.VariableDeclarator) {
737
+ if (!validate.variables && isVariableDeclarator(found)) {
722
738
  return;
723
739
  }
724
740
  if (!validate.parameters) {
@@ -779,12 +795,29 @@ var finnishRule = ruleCreator({
779
795
  }
780
796
  },
781
797
  "ObjectExpression > Property[computed=false] > Identifier": (node) => {
782
- if (validate.properties) {
783
- const parent = node.parent;
784
- if (node === parent.key && !isSourcesObjectAcceptingStaticObservableCreator(parent.parent.parent)) {
785
- checkNode(node);
798
+ if (!validate.objects) {
799
+ return;
800
+ }
801
+ const found = findParent(
802
+ node,
803
+ "CallExpression",
804
+ "VariableDeclarator",
805
+ "TSSatisfiesExpression",
806
+ "TSAsExpression"
807
+ );
808
+ if (found) {
809
+ if (isCallExpression(found)) {
810
+ return;
811
+ } else if (isVariableDeclarator(found) && !!found.id.typeAnnotation) {
812
+ return;
813
+ } else if (isTSAsExpression(found) || isTSSatisfiesExpression(found)) {
814
+ return;
786
815
  }
787
816
  }
817
+ const parent = node.parent;
818
+ if (node === parent.key) {
819
+ checkNode(node, void 0, "shouldBeFinnishProperty");
820
+ }
788
821
  },
789
822
  "ObjectPattern > Property > Identifier": (node) => {
790
823
  const found = findParent(
@@ -797,7 +830,7 @@ var finnishRule = ruleCreator({
797
830
  if (!found) {
798
831
  return;
799
832
  }
800
- if (!validate.variables && found.type === _utils.AST_NODE_TYPES.VariableDeclarator) {
833
+ if (!validate.variables && isVariableDeclarator(found)) {
801
834
  return;
802
835
  }
803
836
  if (!validate.parameters) {
@@ -1073,19 +1106,20 @@ var noCreateRule = ruleCreator({
1073
1106
  defaultOptions: [],
1074
1107
  meta: {
1075
1108
  docs: {
1076
- description: "Disallow the static `Observable.create` function.",
1109
+ description: "Disallow the static `Observable.create` and `Subject.create` functions.",
1077
1110
  recommended: "recommended",
1078
1111
  requiresTypeChecking: true
1079
1112
  },
1080
1113
  messages: {
1081
- forbidden: "Observable.create is forbidden; use new Observable."
1114
+ forbidden: "Observable.create is forbidden; use new Observable.",
1115
+ forbiddenSubject: "Subject.create is forbidden."
1082
1116
  },
1083
1117
  schema: [],
1084
1118
  type: "problem"
1085
1119
  },
1086
1120
  name: "no-create",
1087
1121
  create: (context) => {
1088
- const { couldBeObservable } = getTypeServices(context);
1122
+ const { couldBeObservable, couldBeType: couldBeType2 } = getTypeServices(context);
1089
1123
  return {
1090
1124
  "CallExpression > MemberExpression[object.name='Observable'] > Identifier[name='create']": (node) => {
1091
1125
  const memberExpression = node.parent;
@@ -1095,6 +1129,15 @@ var noCreateRule = ruleCreator({
1095
1129
  node
1096
1130
  });
1097
1131
  }
1132
+ },
1133
+ "CallExpression > MemberExpression[object.name=/^(Subject|BehaviorSubject|AsyncSubject|ReplaySubject)$/] > Identifier[name='create']": (node) => {
1134
+ const memberExpression = node.parent;
1135
+ if (couldBeType2(memberExpression.object, /^(Subject|BehaviorSubject|AsyncSubject|ReplaySubject)$/)) {
1136
+ context.report({
1137
+ messageId: "forbiddenSubject",
1138
+ node
1139
+ });
1140
+ }
1098
1141
  }
1099
1142
  };
1100
1143
  }
@@ -2060,7 +2103,7 @@ var noImplicitAnyCatchRule = ruleCreator({
2060
2103
  defaultOptions: defaultOptions8,
2061
2104
  meta: {
2062
2105
  docs: {
2063
- description: "Disallow implicit `any` error parameters in `catchError` operators.",
2106
+ description: "Disallow implicit `any` error parameters in `catchError`, `subscribe`, and `tap`.",
2064
2107
  recommended: {
2065
2108
  recommended: true,
2066
2109
  strict: [{
@@ -2075,8 +2118,10 @@ var noImplicitAnyCatchRule = ruleCreator({
2075
2118
  explicitAny: "Explicit `any` in error callback.",
2076
2119
  implicitAny: "Implicit `any` in error callback.",
2077
2120
  narrowed: "Error type must be `unknown` or `any`.",
2121
+ narrowedAllowError: "Error type must be `unknown`, `any`, or `Error`.",
2078
2122
  suggestExplicitUnknown: "Use `unknown` instead to explicitly and safely assert the type is correct.",
2079
- suggestExplicitAny: "Use `any` instead to explicitly opt out of type safety."
2123
+ suggestExplicitAny: "Use `any` instead to explicitly opt out of type safety.",
2124
+ suggestExplicitError: "Use `Error` instead."
2080
2125
  },
2081
2126
  schema: [
2082
2127
  {
@@ -2086,6 +2131,11 @@ var noImplicitAnyCatchRule = ruleCreator({
2086
2131
  type: "boolean",
2087
2132
  description: "Allow error variable to be explicitly typed as `any`.",
2088
2133
  default: true
2134
+ },
2135
+ allowExplicitError: {
2136
+ type: "boolean",
2137
+ description: "Allow narrowing error type to `Error`.",
2138
+ default: false
2089
2139
  }
2090
2140
  },
2091
2141
  type: "object"
@@ -2096,7 +2146,7 @@ var noImplicitAnyCatchRule = ruleCreator({
2096
2146
  name: "no-implicit-any-catch",
2097
2147
  create: (context) => {
2098
2148
  const [config = {}] = context.options;
2099
- const { allowExplicitAny = true } = config;
2149
+ const { allowExplicitAny = true, allowExplicitError = false } = config;
2100
2150
  const { couldBeObservable } = getTypeServices(context);
2101
2151
  const sourceCode = context.sourceCode;
2102
2152
  function createReplacerFix(typeAnnotation, replaceWith) {
@@ -2141,20 +2191,33 @@ var noImplicitAnyCatchRule = ruleCreator({
2141
2191
  ]
2142
2192
  });
2143
2193
  } else if (type !== _utils.AST_NODE_TYPES.TSUnknownKeyword) {
2144
- context.report({
2145
- messageId: "narrowed",
2146
- node: param,
2147
- suggest: [
2148
- {
2149
- messageId: "suggestExplicitUnknown",
2150
- fix: createReplacerFix(typeAnnotation, "unknown")
2151
- },
2152
- allowExplicitAny ? {
2153
- messageId: "suggestExplicitAny",
2154
- fix: createReplacerFix(typeAnnotation, "any")
2155
- } : null
2156
- ].filter((x) => !!x)
2157
- });
2194
+ let isAllowedError = false;
2195
+ if (allowExplicitError && type === _utils.AST_NODE_TYPES.TSTypeReference) {
2196
+ const typeRef = typeAnnotation.typeAnnotation;
2197
+ if (isIdentifier(typeRef.typeName)) {
2198
+ isAllowedError = typeRef.typeName.name === "Error";
2199
+ }
2200
+ }
2201
+ if (!isAllowedError) {
2202
+ context.report({
2203
+ messageId: allowExplicitError ? "narrowedAllowError" : "narrowed",
2204
+ node: param,
2205
+ suggest: [
2206
+ {
2207
+ messageId: "suggestExplicitUnknown",
2208
+ fix: createReplacerFix(typeAnnotation, "unknown")
2209
+ },
2210
+ allowExplicitAny ? {
2211
+ messageId: "suggestExplicitAny",
2212
+ fix: createReplacerFix(typeAnnotation, "any")
2213
+ } : null,
2214
+ allowExplicitError && !isAllowedError ? {
2215
+ messageId: "suggestExplicitError",
2216
+ fix: createReplacerFix(typeAnnotation, "Error")
2217
+ } : null
2218
+ ].filter((x) => !!x)
2219
+ });
2220
+ }
2158
2221
  }
2159
2222
  } else {
2160
2223
  const hasRestParams = restParams.length > 0;
@@ -4287,7 +4350,8 @@ var throwErrorRule = ruleCreator({
4287
4350
  requiresTypeChecking: true
4288
4351
  },
4289
4352
  messages: {
4290
- forbidden: "Passing non-Error values is forbidden."
4353
+ forbidden: "Passing non-Error values is forbidden.",
4354
+ suggestErrorConstructor: "Wrap string in Error constructor."
4291
4355
  },
4292
4356
  schema: [
4293
4357
  {
@@ -4298,7 +4362,8 @@ var throwErrorRule = ruleCreator({
4298
4362
  type: "object"
4299
4363
  }
4300
4364
  ],
4301
- type: "problem"
4365
+ type: "problem",
4366
+ hasSuggestions: true
4302
4367
  },
4303
4368
  name: "throw-error",
4304
4369
  create: (context) => {
@@ -4326,9 +4391,22 @@ var throwErrorRule = ruleCreator({
4326
4391
  if (couldBeType(type, /^Error$/)) {
4327
4392
  return;
4328
4393
  }
4394
+ const isString = isTemplateLiteral(reportNode) || isLiteral(reportNode) && typeof reportNode.value === "string";
4329
4395
  context.report({
4330
4396
  messageId: "forbidden",
4331
- node: reportNode
4397
+ node: reportNode,
4398
+ ...isString && {
4399
+ suggest: [
4400
+ {
4401
+ messageId: "suggestErrorConstructor",
4402
+ fix: (fixer) => {
4403
+ const sourceCode = context.sourceCode;
4404
+ const nodeText = sourceCode.getText(reportNode);
4405
+ return fixer.replaceText(reportNode, `new Error(${nodeText})`);
4406
+ }
4407
+ }
4408
+ ]
4409
+ }
4332
4410
  });
4333
4411
  }
4334
4412
  function checkThrowError(node) {
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  // package.json
2
2
  var name = "eslint-plugin-rxjs-x";
3
- var version = "0.9.0";
3
+ var version = "0.9.2";
4
4
 
5
5
  // src/configs/recommended.ts
6
6
  var createRecommendedConfig = (plugin2) => ({
@@ -274,6 +274,9 @@ function isJSXExpressionContainer(node) {
274
274
  function isLiteral(node) {
275
275
  return node.type === AST_NODE_TYPES.Literal;
276
276
  }
277
+ function isTemplateLiteral(node) {
278
+ return node.type === AST_NODE_TYPES.TemplateLiteral;
279
+ }
277
280
  function isMemberExpression(node) {
278
281
  return node.type === AST_NODE_TYPES.MemberExpression;
279
282
  }
@@ -298,12 +301,21 @@ function isPropertyDefinition(node) {
298
301
  function isSpreadElement(node) {
299
302
  return node.type === AST_NODE_TYPES.SpreadElement;
300
303
  }
304
+ function isTSAsExpression(node) {
305
+ return node.type === AST_NODE_TYPES.TSAsExpression;
306
+ }
307
+ function isTSSatisfiesExpression(node) {
308
+ return node.type === AST_NODE_TYPES.TSSatisfiesExpression;
309
+ }
301
310
  function isUnaryExpression(node) {
302
311
  return node.type === AST_NODE_TYPES.UnaryExpression;
303
312
  }
304
313
  function isUnionType(node) {
305
314
  return node.type === AST_NODE_TYPES.TSUnionType;
306
315
  }
316
+ function isVariableDeclarator(node) {
317
+ return node.type === AST_NODE_TYPES.VariableDeclarator;
318
+ }
307
319
 
308
320
  // src/etc/get-type-services.ts
309
321
  function getTypeServices(context) {
@@ -581,8 +593,9 @@ var banOperatorsRule = ruleCreator({
581
593
  });
582
594
 
583
595
  // src/rules/finnish.ts
584
- import { AST_NODE_TYPES as AST_NODE_TYPES4, ESLintUtils as ESLintUtils3 } from "@typescript-eslint/utils";
596
+ import { ESLintUtils as ESLintUtils3 } from "@typescript-eslint/utils";
585
597
  var defaultOptions3 = [];
598
+ var baseShouldBeFinnish = "Finnish notation should be used here.";
586
599
  var finnishRule = ruleCreator({
587
600
  defaultOptions: defaultOptions3,
588
601
  meta: {
@@ -591,7 +604,8 @@ var finnishRule = ruleCreator({
591
604
  requiresTypeChecking: true
592
605
  },
593
606
  messages: {
594
- shouldBeFinnish: "Finnish notation should be used here.",
607
+ shouldBeFinnish: baseShouldBeFinnish,
608
+ shouldBeFinnishProperty: `${baseShouldBeFinnish} Add a type annotation, assertion, or 'satisfies' to silence this rule.`,
595
609
  shouldNotBeFinnish: "Finnish notation should not be used here."
596
610
  },
597
611
  schema: [
@@ -601,7 +615,8 @@ var finnishRule = ruleCreator({
601
615
  methods: { type: "boolean", description: "Require for methods." },
602
616
  names: { type: "object", description: "Enforce for specific names. Keys are a RegExp, values are a boolean." },
603
617
  parameters: { type: "boolean", description: "Require for parameters." },
604
- properties: { type: "boolean", description: "Require for properties." },
618
+ properties: { type: "boolean", description: 'Require for properties, except object literal keys (see "objects" option).' },
619
+ objects: { type: "boolean", description: "Require for object literal keys." },
605
620
  strict: { type: "boolean", description: "Disallow Finnish notation for non-Observables." },
606
621
  types: { type: "object", description: "Enforce for specific types. Keys are a RegExp, values are a boolean." },
607
622
  variables: { type: "boolean", description: "Require for variables." }
@@ -627,6 +642,7 @@ var finnishRule = ruleCreator({
627
642
  methods: true,
628
643
  parameters: true,
629
644
  properties: true,
645
+ objects: true,
630
646
  variables: true,
631
647
  ...config
632
648
  };
@@ -656,7 +672,7 @@ var finnishRule = ruleCreator({
656
672
  validate: false
657
673
  });
658
674
  }
659
- function checkNode(nameNode, typeNode) {
675
+ function checkNode(nameNode, typeNode, shouldMessage = "shouldBeFinnish") {
660
676
  const tsNode = esTreeNodeToTSNodeMap.get(nameNode);
661
677
  const text = tsNode.getText();
662
678
  const hasFinnish = text.endsWith("$");
@@ -667,7 +683,7 @@ var finnishRule = ruleCreator({
667
683
  } : () => {
668
684
  context.report({
669
685
  loc: getLoc(tsNode),
670
- messageId: "shouldBeFinnish"
686
+ messageId: shouldMessage
671
687
  });
672
688
  };
673
689
  const shouldNotBeFinnish = hasFinnish ? () => {
@@ -718,7 +734,7 @@ var finnishRule = ruleCreator({
718
734
  if (!found) {
719
735
  return;
720
736
  }
721
- if (!validate.variables && found.type === AST_NODE_TYPES4.VariableDeclarator) {
737
+ if (!validate.variables && isVariableDeclarator(found)) {
722
738
  return;
723
739
  }
724
740
  if (!validate.parameters) {
@@ -779,12 +795,29 @@ var finnishRule = ruleCreator({
779
795
  }
780
796
  },
781
797
  "ObjectExpression > Property[computed=false] > Identifier": (node) => {
782
- if (validate.properties) {
783
- const parent = node.parent;
784
- if (node === parent.key && !isSourcesObjectAcceptingStaticObservableCreator(parent.parent.parent)) {
785
- checkNode(node);
798
+ if (!validate.objects) {
799
+ return;
800
+ }
801
+ const found = findParent(
802
+ node,
803
+ "CallExpression",
804
+ "VariableDeclarator",
805
+ "TSSatisfiesExpression",
806
+ "TSAsExpression"
807
+ );
808
+ if (found) {
809
+ if (isCallExpression(found)) {
810
+ return;
811
+ } else if (isVariableDeclarator(found) && !!found.id.typeAnnotation) {
812
+ return;
813
+ } else if (isTSAsExpression(found) || isTSSatisfiesExpression(found)) {
814
+ return;
786
815
  }
787
816
  }
817
+ const parent = node.parent;
818
+ if (node === parent.key) {
819
+ checkNode(node, void 0, "shouldBeFinnishProperty");
820
+ }
788
821
  },
789
822
  "ObjectPattern > Property > Identifier": (node) => {
790
823
  const found = findParent(
@@ -797,7 +830,7 @@ var finnishRule = ruleCreator({
797
830
  if (!found) {
798
831
  return;
799
832
  }
800
- if (!validate.variables && found.type === AST_NODE_TYPES4.VariableDeclarator) {
833
+ if (!validate.variables && isVariableDeclarator(found)) {
801
834
  return;
802
835
  }
803
836
  if (!validate.parameters) {
@@ -1073,19 +1106,20 @@ var noCreateRule = ruleCreator({
1073
1106
  defaultOptions: [],
1074
1107
  meta: {
1075
1108
  docs: {
1076
- description: "Disallow the static `Observable.create` function.",
1109
+ description: "Disallow the static `Observable.create` and `Subject.create` functions.",
1077
1110
  recommended: "recommended",
1078
1111
  requiresTypeChecking: true
1079
1112
  },
1080
1113
  messages: {
1081
- forbidden: "Observable.create is forbidden; use new Observable."
1114
+ forbidden: "Observable.create is forbidden; use new Observable.",
1115
+ forbiddenSubject: "Subject.create is forbidden."
1082
1116
  },
1083
1117
  schema: [],
1084
1118
  type: "problem"
1085
1119
  },
1086
1120
  name: "no-create",
1087
1121
  create: (context) => {
1088
- const { couldBeObservable } = getTypeServices(context);
1122
+ const { couldBeObservable, couldBeType: couldBeType2 } = getTypeServices(context);
1089
1123
  return {
1090
1124
  "CallExpression > MemberExpression[object.name='Observable'] > Identifier[name='create']": (node) => {
1091
1125
  const memberExpression = node.parent;
@@ -1095,6 +1129,15 @@ var noCreateRule = ruleCreator({
1095
1129
  node
1096
1130
  });
1097
1131
  }
1132
+ },
1133
+ "CallExpression > MemberExpression[object.name=/^(Subject|BehaviorSubject|AsyncSubject|ReplaySubject)$/] > Identifier[name='create']": (node) => {
1134
+ const memberExpression = node.parent;
1135
+ if (couldBeType2(memberExpression.object, /^(Subject|BehaviorSubject|AsyncSubject|ReplaySubject)$/)) {
1136
+ context.report({
1137
+ messageId: "forbiddenSubject",
1138
+ node
1139
+ });
1140
+ }
1098
1141
  }
1099
1142
  };
1100
1143
  }
@@ -2048,7 +2091,7 @@ var noIgnoredTakewhileValueRule = ruleCreator({
2048
2091
 
2049
2092
  // src/rules/no-implicit-any-catch.ts
2050
2093
  import {
2051
- AST_NODE_TYPES as AST_NODE_TYPES5
2094
+ AST_NODE_TYPES as AST_NODE_TYPES4
2052
2095
  } from "@typescript-eslint/utils";
2053
2096
  function isParenthesised(sourceCode, node) {
2054
2097
  const before = sourceCode.getTokenBefore(node);
@@ -2060,7 +2103,7 @@ var noImplicitAnyCatchRule = ruleCreator({
2060
2103
  defaultOptions: defaultOptions8,
2061
2104
  meta: {
2062
2105
  docs: {
2063
- description: "Disallow implicit `any` error parameters in `catchError` operators.",
2106
+ description: "Disallow implicit `any` error parameters in `catchError`, `subscribe`, and `tap`.",
2064
2107
  recommended: {
2065
2108
  recommended: true,
2066
2109
  strict: [{
@@ -2075,8 +2118,10 @@ var noImplicitAnyCatchRule = ruleCreator({
2075
2118
  explicitAny: "Explicit `any` in error callback.",
2076
2119
  implicitAny: "Implicit `any` in error callback.",
2077
2120
  narrowed: "Error type must be `unknown` or `any`.",
2121
+ narrowedAllowError: "Error type must be `unknown`, `any`, or `Error`.",
2078
2122
  suggestExplicitUnknown: "Use `unknown` instead to explicitly and safely assert the type is correct.",
2079
- suggestExplicitAny: "Use `any` instead to explicitly opt out of type safety."
2123
+ suggestExplicitAny: "Use `any` instead to explicitly opt out of type safety.",
2124
+ suggestExplicitError: "Use `Error` instead."
2080
2125
  },
2081
2126
  schema: [
2082
2127
  {
@@ -2086,6 +2131,11 @@ var noImplicitAnyCatchRule = ruleCreator({
2086
2131
  type: "boolean",
2087
2132
  description: "Allow error variable to be explicitly typed as `any`.",
2088
2133
  default: true
2134
+ },
2135
+ allowExplicitError: {
2136
+ type: "boolean",
2137
+ description: "Allow narrowing error type to `Error`.",
2138
+ default: false
2089
2139
  }
2090
2140
  },
2091
2141
  type: "object"
@@ -2096,7 +2146,7 @@ var noImplicitAnyCatchRule = ruleCreator({
2096
2146
  name: "no-implicit-any-catch",
2097
2147
  create: (context) => {
2098
2148
  const [config = {}] = context.options;
2099
- const { allowExplicitAny = true } = config;
2149
+ const { allowExplicitAny = true, allowExplicitError = false } = config;
2100
2150
  const { couldBeObservable } = getTypeServices(context);
2101
2151
  const sourceCode = context.sourceCode;
2102
2152
  function createReplacerFix(typeAnnotation, replaceWith) {
@@ -2126,7 +2176,7 @@ var noImplicitAnyCatchRule = ruleCreator({
2126
2176
  const {
2127
2177
  typeAnnotation: { type }
2128
2178
  } = typeAnnotation;
2129
- if (type === AST_NODE_TYPES5.TSAnyKeyword) {
2179
+ if (type === AST_NODE_TYPES4.TSAnyKeyword) {
2130
2180
  if (allowExplicitAny) {
2131
2181
  return;
2132
2182
  }
@@ -2140,21 +2190,34 @@ var noImplicitAnyCatchRule = ruleCreator({
2140
2190
  }
2141
2191
  ]
2142
2192
  });
2143
- } else if (type !== AST_NODE_TYPES5.TSUnknownKeyword) {
2144
- context.report({
2145
- messageId: "narrowed",
2146
- node: param,
2147
- suggest: [
2148
- {
2149
- messageId: "suggestExplicitUnknown",
2150
- fix: createReplacerFix(typeAnnotation, "unknown")
2151
- },
2152
- allowExplicitAny ? {
2153
- messageId: "suggestExplicitAny",
2154
- fix: createReplacerFix(typeAnnotation, "any")
2155
- } : null
2156
- ].filter((x) => !!x)
2157
- });
2193
+ } else if (type !== AST_NODE_TYPES4.TSUnknownKeyword) {
2194
+ let isAllowedError = false;
2195
+ if (allowExplicitError && type === AST_NODE_TYPES4.TSTypeReference) {
2196
+ const typeRef = typeAnnotation.typeAnnotation;
2197
+ if (isIdentifier(typeRef.typeName)) {
2198
+ isAllowedError = typeRef.typeName.name === "Error";
2199
+ }
2200
+ }
2201
+ if (!isAllowedError) {
2202
+ context.report({
2203
+ messageId: allowExplicitError ? "narrowedAllowError" : "narrowed",
2204
+ node: param,
2205
+ suggest: [
2206
+ {
2207
+ messageId: "suggestExplicitUnknown",
2208
+ fix: createReplacerFix(typeAnnotation, "unknown")
2209
+ },
2210
+ allowExplicitAny ? {
2211
+ messageId: "suggestExplicitAny",
2212
+ fix: createReplacerFix(typeAnnotation, "any")
2213
+ } : null,
2214
+ allowExplicitError && !isAllowedError ? {
2215
+ messageId: "suggestExplicitError",
2216
+ fix: createReplacerFix(typeAnnotation, "Error")
2217
+ } : null
2218
+ ].filter((x) => !!x)
2219
+ });
2220
+ }
2158
2221
  }
2159
2222
  } else {
2160
2223
  const hasRestParams = restParams.length > 0;
@@ -2309,7 +2372,7 @@ var noInternalRule = ruleCreator({
2309
2372
  });
2310
2373
 
2311
2374
  // src/rules/no-misused-observables.ts
2312
- import { AST_NODE_TYPES as AST_NODE_TYPES6, ESLintUtils as ESLintUtils9 } from "@typescript-eslint/utils";
2375
+ import { AST_NODE_TYPES as AST_NODE_TYPES5, ESLintUtils as ESLintUtils9 } from "@typescript-eslint/utils";
2313
2376
  import { getFunctionHeadLocation, isFunction } from "@typescript-eslint/utils/ast-utils";
2314
2377
  import * as tsutils4 from "ts-api-utils";
2315
2378
  import ts5 from "typescript";
@@ -2675,55 +2738,55 @@ function getPropertyContextualType(checker, tsNode) {
2675
2738
  }
2676
2739
  function isPossiblyFunctionType(node) {
2677
2740
  switch (node.typeAnnotation.type) {
2678
- case AST_NODE_TYPES6.TSConditionalType:
2679
- case AST_NODE_TYPES6.TSConstructorType:
2680
- case AST_NODE_TYPES6.TSFunctionType:
2681
- case AST_NODE_TYPES6.TSImportType:
2682
- case AST_NODE_TYPES6.TSIndexedAccessType:
2683
- case AST_NODE_TYPES6.TSInferType:
2684
- case AST_NODE_TYPES6.TSIntersectionType:
2685
- case AST_NODE_TYPES6.TSQualifiedName:
2686
- case AST_NODE_TYPES6.TSThisType:
2687
- case AST_NODE_TYPES6.TSTypeOperator:
2688
- case AST_NODE_TYPES6.TSTypeQuery:
2689
- case AST_NODE_TYPES6.TSTypeReference:
2690
- case AST_NODE_TYPES6.TSUnionType:
2741
+ case AST_NODE_TYPES5.TSConditionalType:
2742
+ case AST_NODE_TYPES5.TSConstructorType:
2743
+ case AST_NODE_TYPES5.TSFunctionType:
2744
+ case AST_NODE_TYPES5.TSImportType:
2745
+ case AST_NODE_TYPES5.TSIndexedAccessType:
2746
+ case AST_NODE_TYPES5.TSInferType:
2747
+ case AST_NODE_TYPES5.TSIntersectionType:
2748
+ case AST_NODE_TYPES5.TSQualifiedName:
2749
+ case AST_NODE_TYPES5.TSThisType:
2750
+ case AST_NODE_TYPES5.TSTypeOperator:
2751
+ case AST_NODE_TYPES5.TSTypeQuery:
2752
+ case AST_NODE_TYPES5.TSTypeReference:
2753
+ case AST_NODE_TYPES5.TSUnionType:
2691
2754
  return true;
2692
- case AST_NODE_TYPES6.TSTypeLiteral:
2755
+ case AST_NODE_TYPES5.TSTypeLiteral:
2693
2756
  return node.typeAnnotation.members.some(
2694
- (member) => member.type === AST_NODE_TYPES6.TSCallSignatureDeclaration || member.type === AST_NODE_TYPES6.TSConstructSignatureDeclaration
2757
+ (member) => member.type === AST_NODE_TYPES5.TSCallSignatureDeclaration || member.type === AST_NODE_TYPES5.TSConstructSignatureDeclaration
2695
2758
  );
2696
- case AST_NODE_TYPES6.TSAbstractKeyword:
2697
- case AST_NODE_TYPES6.TSAnyKeyword:
2698
- case AST_NODE_TYPES6.TSArrayType:
2699
- case AST_NODE_TYPES6.TSAsyncKeyword:
2700
- case AST_NODE_TYPES6.TSBigIntKeyword:
2701
- case AST_NODE_TYPES6.TSBooleanKeyword:
2702
- case AST_NODE_TYPES6.TSDeclareKeyword:
2703
- case AST_NODE_TYPES6.TSExportKeyword:
2704
- case AST_NODE_TYPES6.TSIntrinsicKeyword:
2705
- case AST_NODE_TYPES6.TSLiteralType:
2706
- case AST_NODE_TYPES6.TSMappedType:
2707
- case AST_NODE_TYPES6.TSNamedTupleMember:
2708
- case AST_NODE_TYPES6.TSNeverKeyword:
2709
- case AST_NODE_TYPES6.TSNullKeyword:
2710
- case AST_NODE_TYPES6.TSNumberKeyword:
2711
- case AST_NODE_TYPES6.TSObjectKeyword:
2712
- case AST_NODE_TYPES6.TSOptionalType:
2713
- case AST_NODE_TYPES6.TSPrivateKeyword:
2714
- case AST_NODE_TYPES6.TSProtectedKeyword:
2715
- case AST_NODE_TYPES6.TSPublicKeyword:
2716
- case AST_NODE_TYPES6.TSReadonlyKeyword:
2717
- case AST_NODE_TYPES6.TSRestType:
2718
- case AST_NODE_TYPES6.TSStaticKeyword:
2719
- case AST_NODE_TYPES6.TSStringKeyword:
2720
- case AST_NODE_TYPES6.TSSymbolKeyword:
2721
- case AST_NODE_TYPES6.TSTemplateLiteralType:
2722
- case AST_NODE_TYPES6.TSTupleType:
2723
- case AST_NODE_TYPES6.TSTypePredicate:
2724
- case AST_NODE_TYPES6.TSUndefinedKeyword:
2725
- case AST_NODE_TYPES6.TSUnknownKeyword:
2726
- case AST_NODE_TYPES6.TSVoidKeyword:
2759
+ case AST_NODE_TYPES5.TSAbstractKeyword:
2760
+ case AST_NODE_TYPES5.TSAnyKeyword:
2761
+ case AST_NODE_TYPES5.TSArrayType:
2762
+ case AST_NODE_TYPES5.TSAsyncKeyword:
2763
+ case AST_NODE_TYPES5.TSBigIntKeyword:
2764
+ case AST_NODE_TYPES5.TSBooleanKeyword:
2765
+ case AST_NODE_TYPES5.TSDeclareKeyword:
2766
+ case AST_NODE_TYPES5.TSExportKeyword:
2767
+ case AST_NODE_TYPES5.TSIntrinsicKeyword:
2768
+ case AST_NODE_TYPES5.TSLiteralType:
2769
+ case AST_NODE_TYPES5.TSMappedType:
2770
+ case AST_NODE_TYPES5.TSNamedTupleMember:
2771
+ case AST_NODE_TYPES5.TSNeverKeyword:
2772
+ case AST_NODE_TYPES5.TSNullKeyword:
2773
+ case AST_NODE_TYPES5.TSNumberKeyword:
2774
+ case AST_NODE_TYPES5.TSObjectKeyword:
2775
+ case AST_NODE_TYPES5.TSOptionalType:
2776
+ case AST_NODE_TYPES5.TSPrivateKeyword:
2777
+ case AST_NODE_TYPES5.TSProtectedKeyword:
2778
+ case AST_NODE_TYPES5.TSPublicKeyword:
2779
+ case AST_NODE_TYPES5.TSReadonlyKeyword:
2780
+ case AST_NODE_TYPES5.TSRestType:
2781
+ case AST_NODE_TYPES5.TSStaticKeyword:
2782
+ case AST_NODE_TYPES5.TSStringKeyword:
2783
+ case AST_NODE_TYPES5.TSSymbolKeyword:
2784
+ case AST_NODE_TYPES5.TSTemplateLiteralType:
2785
+ case AST_NODE_TYPES5.TSTupleType:
2786
+ case AST_NODE_TYPES5.TSTypePredicate:
2787
+ case AST_NODE_TYPES5.TSUndefinedKeyword:
2788
+ case AST_NODE_TYPES5.TSUnknownKeyword:
2789
+ case AST_NODE_TYPES5.TSVoidKeyword:
2727
2790
  return false;
2728
2791
  }
2729
2792
  }
@@ -2850,7 +2913,7 @@ function isExpressionObserver(expressionStatement, couldBeType2) {
2850
2913
  }
2851
2914
 
2852
2915
  // src/rules/no-sharereplay.ts
2853
- import { AST_NODE_TYPES as AST_NODE_TYPES7 } from "@typescript-eslint/utils";
2916
+ import { AST_NODE_TYPES as AST_NODE_TYPES6 } from "@typescript-eslint/utils";
2854
2917
  var defaultOptions10 = [];
2855
2918
  var noSharereplayRule = ruleCreator({
2856
2919
  defaultOptions: defaultOptions10,
@@ -2881,7 +2944,7 @@ var noSharereplayRule = ruleCreator({
2881
2944
  "CallExpression[callee.name='shareReplay']": (node) => {
2882
2945
  let report = true;
2883
2946
  if (allowConfig) {
2884
- report = node.arguments.length !== 1 || node.arguments[0].type !== AST_NODE_TYPES7.ObjectExpression;
2947
+ report = node.arguments.length !== 1 || node.arguments[0].type !== AST_NODE_TYPES6.ObjectExpression;
2885
2948
  }
2886
2949
  if (report) {
2887
2950
  context.report({
@@ -3118,7 +3181,7 @@ var noSubscribeHandlersRule = ruleCreator({
3118
3181
  });
3119
3182
 
3120
3183
  // src/rules/no-subscribe-in-pipe.ts
3121
- import { AST_NODE_TYPES as AST_NODE_TYPES8 } from "@typescript-eslint/utils";
3184
+ import { AST_NODE_TYPES as AST_NODE_TYPES7 } from "@typescript-eslint/utils";
3122
3185
  var noSubscribeInPipeRule = ruleCreator({
3123
3186
  defaultOptions: [],
3124
3187
  meta: {
@@ -3139,7 +3202,7 @@ var noSubscribeInPipeRule = ruleCreator({
3139
3202
  function isWithinPipe(node) {
3140
3203
  let parent = node.parent;
3141
3204
  while (parent) {
3142
- if (parent.type === AST_NODE_TYPES8.CallExpression && parent.callee.type === AST_NODE_TYPES8.MemberExpression && parent.callee.property.type === AST_NODE_TYPES8.Identifier && parent.callee.property.name === "pipe") {
3205
+ if (parent.type === AST_NODE_TYPES7.CallExpression && parent.callee.type === AST_NODE_TYPES7.MemberExpression && parent.callee.property.type === AST_NODE_TYPES7.Identifier && parent.callee.property.name === "pipe") {
3143
3206
  return true;
3144
3207
  }
3145
3208
  parent = parent.parent;
@@ -4074,7 +4137,7 @@ var preferRootOperatorsRule = ruleCreator({
4074
4137
  });
4075
4138
 
4076
4139
  // src/rules/suffix-subjects.ts
4077
- import { AST_NODE_TYPES as AST_NODE_TYPES9, ESLintUtils as ESLintUtils12 } from "@typescript-eslint/utils";
4140
+ import { AST_NODE_TYPES as AST_NODE_TYPES8, ESLintUtils as ESLintUtils12 } from "@typescript-eslint/utils";
4078
4141
  var defaultOptions18 = [];
4079
4142
  var suffixSubjectsRule = ruleCreator({
4080
4143
  defaultOptions: defaultOptions18,
@@ -4158,7 +4221,7 @@ var suffixSubjectsRule = ruleCreator({
4158
4221
  if (!found) {
4159
4222
  return;
4160
4223
  }
4161
- if (!validate.variables && found.type === AST_NODE_TYPES9.VariableDeclarator) {
4224
+ if (!validate.variables && found.type === AST_NODE_TYPES8.VariableDeclarator) {
4162
4225
  return;
4163
4226
  }
4164
4227
  if (!validate.parameters) {
@@ -4225,7 +4288,7 @@ var suffixSubjectsRule = ruleCreator({
4225
4288
  if (!found) {
4226
4289
  return;
4227
4290
  }
4228
- if (!validate.variables && found.type === AST_NODE_TYPES9.VariableDeclarator) {
4291
+ if (!validate.variables && found.type === AST_NODE_TYPES8.VariableDeclarator) {
4229
4292
  return;
4230
4293
  }
4231
4294
  if (!validate.parameters) {
@@ -4287,7 +4350,8 @@ var throwErrorRule = ruleCreator({
4287
4350
  requiresTypeChecking: true
4288
4351
  },
4289
4352
  messages: {
4290
- forbidden: "Passing non-Error values is forbidden."
4353
+ forbidden: "Passing non-Error values is forbidden.",
4354
+ suggestErrorConstructor: "Wrap string in Error constructor."
4291
4355
  },
4292
4356
  schema: [
4293
4357
  {
@@ -4298,7 +4362,8 @@ var throwErrorRule = ruleCreator({
4298
4362
  type: "object"
4299
4363
  }
4300
4364
  ],
4301
- type: "problem"
4365
+ type: "problem",
4366
+ hasSuggestions: true
4302
4367
  },
4303
4368
  name: "throw-error",
4304
4369
  create: (context) => {
@@ -4326,9 +4391,22 @@ var throwErrorRule = ruleCreator({
4326
4391
  if (couldBeType(type, /^Error$/)) {
4327
4392
  return;
4328
4393
  }
4394
+ const isString = isTemplateLiteral(reportNode) || isLiteral(reportNode) && typeof reportNode.value === "string";
4329
4395
  context.report({
4330
4396
  messageId: "forbidden",
4331
- node: reportNode
4397
+ node: reportNode,
4398
+ ...isString && {
4399
+ suggest: [
4400
+ {
4401
+ messageId: "suggestErrorConstructor",
4402
+ fix: (fixer) => {
4403
+ const sourceCode = context.sourceCode;
4404
+ const nodeText = sourceCode.getText(reportNode);
4405
+ return fixer.replaceText(reportNode, `new Error(${nodeText})`);
4406
+ }
4407
+ }
4408
+ ]
4409
+ }
4332
4410
  });
4333
4411
  }
4334
4412
  function checkThrowError(node) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "eslint-plugin-rxjs-x",
3
3
  "type": "commonjs",
4
- "version": "0.9.0",
4
+ "version": "0.9.2",
5
5
  "packageManager": "yarn@4.12.0+sha512.f45ab632439a67f8bc759bf32ead036a1f413287b9042726b7cc4818b7b49e14e9423ba49b18f9e06ea4941c1ad062385b1d8760a8d5091a1a31e5f6219afca8",
6
6
  "description": "Modern ESLint plugin for RxJS",
7
7
  "author": "Jason Weinzierl <weinzierljason@gmail.com>",
@@ -84,7 +84,7 @@
84
84
  "@typescript/vfs": "^1.6.2",
85
85
  "@vitest/coverage-v8": "^3.2.4",
86
86
  "@vitest/eslint-plugin": "^1.4.0",
87
- "bumpp": "^10.4.0",
87
+ "bumpp": "^10.4.1",
88
88
  "eslint": "^9.39.2",
89
89
  "eslint-config-flat-gitignore": "^2.1.0",
90
90
  "eslint-doc-generator": "^2.4.0",