eslint-plugin-rxjs-x 0.9.2 → 0.9.4

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
@@ -258,9 +258,10 @@ declare const allRules: {
258
258
  description: "Disallow importing operators from `rxjs/operators`.";
259
259
  recommended: "recommended";
260
260
  }, TSESLint.RuleListener>;
261
- 'suffix-subjects': TSESLint.RuleModule<"forbidden", readonly {
261
+ 'suffix-subjects': TSESLint.RuleModule<"forbidden" | "forbiddenProperty", readonly {
262
262
  parameters?: boolean;
263
263
  properties?: boolean;
264
+ objects?: boolean;
264
265
  suffix?: string;
265
266
  types?: Record<string, boolean>;
266
267
  variables?: boolean;
package/dist/index.d.ts CHANGED
@@ -258,9 +258,10 @@ declare const allRules: {
258
258
  description: "Disallow importing operators from `rxjs/operators`.";
259
259
  recommended: "recommended";
260
260
  }, TSESLint.RuleListener>;
261
- 'suffix-subjects': TSESLint.RuleModule<"forbidden", readonly {
261
+ 'suffix-subjects': TSESLint.RuleModule<"forbidden" | "forbiddenProperty", readonly {
262
262
  parameters?: boolean;
263
263
  properties?: boolean;
264
+ objects?: boolean;
264
265
  suffix?: string;
265
266
  types?: Record<string, boolean>;
266
267
  variables?: boolean;
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.2";
3
+ var version = "0.9.4";
4
4
 
5
5
  // src/configs/recommended.ts
6
6
  var createRecommendedConfig = (plugin2) => ({
@@ -117,7 +117,10 @@ function couldBeType(type, name2, qualified) {
117
117
  if (tsutils.isTypeReference(type)) {
118
118
  type = type.target;
119
119
  }
120
- if (isType(type, name2, qualified)) {
120
+ if (isType(type.symbol, name2, qualified)) {
121
+ return true;
122
+ }
123
+ if (type.aliasSymbol && isType(type.aliasSymbol, name2, qualified)) {
121
124
  return true;
122
125
  }
123
126
  if (tsutils.isUnionOrIntersectionType(type)) {
@@ -132,16 +135,16 @@ function couldBeType(type, name2, qualified) {
132
135
  }
133
136
  return false;
134
137
  }
135
- function isType(type, name2, qualified) {
136
- if (!type.symbol) {
138
+ function isType(symbol, name2, qualified) {
139
+ if (!symbol) {
137
140
  return false;
138
141
  }
139
142
  if (qualified && !qualified.name.test(
140
- qualified.typeChecker.getFullyQualifiedName(type.symbol)
143
+ qualified.typeChecker.getFullyQualifiedName(symbol)
141
144
  )) {
142
145
  return false;
143
146
  }
144
- return typeof name2 === "string" ? type.symbol.name === name2 : Boolean(type.symbol.name.match(name2));
147
+ return typeof name2 === "string" ? symbol.name === name2 : Boolean(symbol.name.match(name2));
145
148
  }
146
149
  function couldImplement(type, name2, qualified) {
147
150
  const { symbol } = type;
@@ -409,52 +412,6 @@ function findIsLastOperatorOrderValid(pipeCallExpression, operatorsRegExp, allow
409
412
  return { isOrderValid, operatorNode };
410
413
  }
411
414
 
412
- // src/constants.ts
413
- var defaultObservable = String.raw`[Aa]ction(s|s\$|\$)$`;
414
- var SOURCES_OBJECT_ACCEPTING_STATIC_OBSERVABLE_CREATORS = [
415
- "combineLatest",
416
- "forkJoin"
417
- ];
418
- var MULTIPLE_OBSERVABLE_ACCEPTING_STATIC_OBSERVABLE_CREATORS = [
419
- "combineLatest",
420
- "forkJoin",
421
- "merge",
422
- "zip",
423
- "concat",
424
- "race"
425
- ];
426
- var DEFAULT_UNBOUND_ALLOWED_TYPES = [
427
- "Signal"
428
- ];
429
- var DEFAULT_VALID_POST_COMPLETION_OPERATORS = [
430
- "count",
431
- "defaultIfEmpty",
432
- "endWith",
433
- "every",
434
- "finalize",
435
- "finally",
436
- "isEmpty",
437
- "last",
438
- "max",
439
- "min",
440
- "publish",
441
- "publishBehavior",
442
- "publishLast",
443
- "publishReplay",
444
- "reduce",
445
- "share",
446
- "shareReplay",
447
- "skipLast",
448
- "takeLast",
449
- "throwIfEmpty",
450
- "toArray"
451
- ];
452
-
453
- // src/utils/is-sources-object-accepting-static-observable-creator.ts
454
- function isSourcesObjectAcceptingStaticObservableCreator(expression) {
455
- return isCallExpression(expression) && isIdentifier(expression.callee) && SOURCES_OBJECT_ACCEPTING_STATIC_OBSERVABLE_CREATORS.includes(expression.callee.name);
456
- }
457
-
458
415
  // src/utils/rule-creator.ts
459
416
 
460
417
  var REPO_URL = "https://github.com/JasonWeinzierl/eslint-plugin-rxjs-x";
@@ -752,6 +709,9 @@ var finnishRule = ruleCreator({
752
709
  },
753
710
  "PropertyDefinition[computed=false]": (node) => {
754
711
  if (validate.properties) {
712
+ if (node.override) {
713
+ return;
714
+ }
755
715
  checkNode(node.key);
756
716
  }
757
717
  },
@@ -781,19 +741,44 @@ var finnishRule = ruleCreator({
781
741
  },
782
742
  "MethodDefinition[kind='get'][computed=false]": (node) => {
783
743
  if (validate.properties) {
744
+ if (node.override) {
745
+ return;
746
+ }
784
747
  checkNode(node.key, node);
785
748
  }
786
749
  },
787
750
  "MethodDefinition[kind='method'][computed=false]": (node) => {
788
751
  if (validate.methods) {
752
+ if (node.override) {
753
+ return;
754
+ }
789
755
  checkNode(node.key, node);
790
756
  }
791
757
  },
792
758
  "MethodDefinition[kind='set'][computed=false]": (node) => {
793
759
  if (validate.properties) {
760
+ if (node.override) {
761
+ return;
762
+ }
794
763
  checkNode(node.key, node);
795
764
  }
796
765
  },
766
+ "TSAbstractMethodDefinition[computed=false]": (node) => {
767
+ if (node.override) {
768
+ return;
769
+ }
770
+ if (validate.methods && node.kind === "method") {
771
+ checkNode(node.key, node);
772
+ }
773
+ if (validate.properties && (node.kind === "get" || node.kind === "set")) {
774
+ checkNode(node.key, node);
775
+ }
776
+ if (validate.parameters) {
777
+ node.value.params.forEach((param) => {
778
+ checkNode(param);
779
+ });
780
+ }
781
+ },
797
782
  "ObjectExpression > Property[computed=false] > Identifier": (node) => {
798
783
  if (!validate.objects) {
799
784
  return;
@@ -1147,6 +1132,49 @@ var noCreateRule = ruleCreator({
1147
1132
 
1148
1133
 
1149
1134
 
1135
+
1136
+ // src/constants.ts
1137
+ var defaultObservable = String.raw`[Aa]ction(s|s\$|\$)$`;
1138
+ var SOURCES_OBJECT_ACCEPTING_STATIC_OBSERVABLE_CREATORS = [
1139
+ "combineLatest",
1140
+ "forkJoin"
1141
+ ];
1142
+ var MULTIPLE_OBSERVABLE_ACCEPTING_STATIC_OBSERVABLE_CREATORS = [
1143
+ "combineLatest",
1144
+ "forkJoin",
1145
+ "merge",
1146
+ "zip",
1147
+ "concat",
1148
+ "race"
1149
+ ];
1150
+ var DEFAULT_UNBOUND_ALLOWED_TYPES = [
1151
+ "Signal"
1152
+ ];
1153
+ var DEFAULT_VALID_POST_COMPLETION_OPERATORS = [
1154
+ "count",
1155
+ "defaultIfEmpty",
1156
+ "endWith",
1157
+ "every",
1158
+ "finalize",
1159
+ "finally",
1160
+ "isEmpty",
1161
+ "last",
1162
+ "max",
1163
+ "min",
1164
+ "publish",
1165
+ "publishBehavior",
1166
+ "publishLast",
1167
+ "publishReplay",
1168
+ "reduce",
1169
+ "share",
1170
+ "shareReplay",
1171
+ "skipLast",
1172
+ "takeLast",
1173
+ "throwIfEmpty",
1174
+ "toArray"
1175
+ ];
1176
+
1177
+ // src/rules/no-cyclic-action.ts
1150
1178
  function isTypeReference2(type) {
1151
1179
  return Boolean(type.target);
1152
1180
  }
@@ -3389,7 +3417,7 @@ var noUnboundMethodsRule = ruleCreator({
3389
3417
  const { couldBeObservable, couldBeSubscription } = getTypeServices(context);
3390
3418
  const nodeMap = /* @__PURE__ */ new WeakMap();
3391
3419
  const [config = {}] = context.options;
3392
- const { allowTypes = [] } = config;
3420
+ const { allowTypes = DEFAULT_UNBOUND_ALLOWED_TYPES } = config;
3393
3421
  function mapArguments(node) {
3394
3422
  node.arguments.filter(isMemberExpression).forEach((arg) => {
3395
3423
  const argType = getTypeAtLocation(arg);
@@ -3711,6 +3739,16 @@ var noUnsafeSubjectNext = ruleCreator({
3711
3739
  // src/rules/no-unsafe-switchmap.ts
3712
3740
 
3713
3741
  var _decamelize = require('decamelize'); var _decamelize2 = _interopRequireDefault(_decamelize);
3742
+ var DEFAULT_DISALLOW = [
3743
+ "add",
3744
+ "create",
3745
+ "delete",
3746
+ "post",
3747
+ "put",
3748
+ "remove",
3749
+ "set",
3750
+ "update"
3751
+ ];
3714
3752
  var defaultOptions15 = [];
3715
3753
  var noUnsafeSwitchmapRule = ruleCreator({
3716
3754
  defaultOptions: defaultOptions15,
@@ -3737,7 +3775,8 @@ var noUnsafeSwitchmapRule = ruleCreator({
3737
3775
  oneOf: [
3738
3776
  { type: "string", description: "A regular expression string." },
3739
3777
  { type: "array", items: { type: "string" }, description: "An array of words." }
3740
- ]
3778
+ ],
3779
+ default: DEFAULT_DISALLOW
3741
3780
  },
3742
3781
  observable: {
3743
3782
  type: "string",
@@ -3760,29 +3799,15 @@ var noUnsafeSwitchmapRule = ruleCreator({
3760
3799
  name: "no-unsafe-switchmap",
3761
3800
  create: (context) => {
3762
3801
  var _a, _b, _c;
3763
- const defaultDisallow = [
3764
- "add",
3765
- "create",
3766
- "delete",
3767
- "post",
3768
- "put",
3769
- "remove",
3770
- "set",
3771
- "update"
3772
- ];
3773
- let allowRegExp;
3774
- let disallowRegExp;
3775
- let observableRegExp;
3802
+ let allowRegExp = void 0;
3803
+ let disallowRegExp = void 0;
3776
3804
  const [config = {}] = context.options;
3777
- if (config.allow || config.disallow) {
3805
+ if (config.allow) {
3778
3806
  allowRegExp = createRegExpForWords((_a = config.allow) != null ? _a : []);
3779
- disallowRegExp = createRegExpForWords((_b = config.disallow) != null ? _b : []);
3780
- observableRegExp = new RegExp((_c = config.observable) != null ? _c : defaultObservable);
3781
3807
  } else {
3782
- allowRegExp = void 0;
3783
- disallowRegExp = createRegExpForWords(defaultDisallow);
3784
- observableRegExp = new RegExp(defaultObservable);
3808
+ disallowRegExp = createRegExpForWords((_b = config.disallow) != null ? _b : DEFAULT_DISALLOW);
3785
3809
  }
3810
+ const observableRegExp = new RegExp((_c = config.observable) != null ? _c : defaultObservable);
3786
3811
  const { couldBeObservable } = getTypeServices(context);
3787
3812
  function shouldDisallow(args) {
3788
3813
  const names = args.map((arg) => {
@@ -4139,6 +4164,7 @@ var preferRootOperatorsRule = ruleCreator({
4139
4164
  // src/rules/suffix-subjects.ts
4140
4165
 
4141
4166
  var defaultOptions18 = [];
4167
+ var baseShouldHaveSuffix = 'Subject identifiers must end with "{{suffix}}".';
4142
4168
  var suffixSubjectsRule = ruleCreator({
4143
4169
  defaultOptions: defaultOptions18,
4144
4170
  meta: {
@@ -4147,13 +4173,15 @@ var suffixSubjectsRule = ruleCreator({
4147
4173
  requiresTypeChecking: true
4148
4174
  },
4149
4175
  messages: {
4150
- forbidden: `Subject identifiers must end with "{{suffix}}".`
4176
+ forbidden: baseShouldHaveSuffix,
4177
+ forbiddenProperty: `${baseShouldHaveSuffix} Add a type annotation, assertion, or 'satisfies' to silence this rule.`
4151
4178
  },
4152
4179
  schema: [
4153
4180
  {
4154
4181
  properties: {
4155
4182
  parameters: { type: "boolean", description: "Require for parameters." },
4156
- properties: { type: "boolean", description: "Require for properties." },
4183
+ properties: { type: "boolean", description: 'Require for properties, except object literal keys (see "objects" option).' },
4184
+ objects: { type: "boolean", description: "Require for object literal keys." },
4157
4185
  suffix: { type: "string", description: "The suffix to enforce." },
4158
4186
  types: { type: "object", description: "Enforce for specific types. Keys are a RegExp, values are a boolean." },
4159
4187
  variables: { type: "boolean", description: "Require for variables." }
@@ -4171,6 +4199,7 @@ var suffixSubjectsRule = ruleCreator({
4171
4199
  const validate = {
4172
4200
  parameters: true,
4173
4201
  properties: true,
4202
+ objects: true,
4174
4203
  variables: true,
4175
4204
  ...config
4176
4205
  };
@@ -4192,7 +4221,7 @@ var suffixSubjectsRule = ruleCreator({
4192
4221
  String.raw`${escapeRegExp(suffix)}\$?$`,
4193
4222
  "i"
4194
4223
  );
4195
- function checkNode(nameNode, typeNode) {
4224
+ function checkNode(nameNode, typeNode, shouldMessage = "forbidden") {
4196
4225
  const tsNode = esTreeNodeToTSNodeMap.get(nameNode);
4197
4226
  const text = tsNode.getText();
4198
4227
  if (!suffixRegex.test(text) && couldBeType2(typeNode != null ? typeNode : nameNode, "Subject")) {
@@ -4205,7 +4234,7 @@ var suffixSubjectsRule = ruleCreator({
4205
4234
  context.report({
4206
4235
  data: { suffix },
4207
4236
  loc: getLoc(tsNode),
4208
- messageId: "forbidden"
4237
+ messageId: shouldMessage
4209
4238
  });
4210
4239
  }
4211
4240
  }
@@ -4221,7 +4250,7 @@ var suffixSubjectsRule = ruleCreator({
4221
4250
  if (!found) {
4222
4251
  return;
4223
4252
  }
4224
- if (!validate.variables && found.type === _utils.AST_NODE_TYPES.VariableDeclarator) {
4253
+ if (!validate.variables && isVariableDeclarator(found)) {
4225
4254
  return;
4226
4255
  }
4227
4256
  if (!validate.parameters) {
@@ -4240,6 +4269,9 @@ var suffixSubjectsRule = ruleCreator({
4240
4269
  "PropertyDefinition[computed=false]": (node) => {
4241
4270
  const anyNode = node;
4242
4271
  if (validate.properties) {
4272
+ if (node.override) {
4273
+ return;
4274
+ }
4243
4275
  checkNode(anyNode.key);
4244
4276
  }
4245
4277
  },
@@ -4261,21 +4293,58 @@ var suffixSubjectsRule = ruleCreator({
4261
4293
  },
4262
4294
  "MethodDefinition[kind='get'][computed=false]": (node) => {
4263
4295
  if (validate.properties) {
4296
+ if (node.override) {
4297
+ return;
4298
+ }
4264
4299
  checkNode(node.key, node);
4265
4300
  }
4266
4301
  },
4267
4302
  "MethodDefinition[kind='set'][computed=false]": (node) => {
4268
4303
  if (validate.properties) {
4304
+ if (node.override) {
4305
+ return;
4306
+ }
4269
4307
  checkNode(node.key, node);
4270
4308
  }
4271
4309
  },
4310
+ "TSAbstractMethodDefinition[computed=false]": (node) => {
4311
+ if (node.override) {
4312
+ return;
4313
+ }
4314
+ if (validate.properties && (node.kind === "get" || node.kind === "set")) {
4315
+ checkNode(node.key, node);
4316
+ }
4317
+ if (validate.parameters) {
4318
+ node.value.params.forEach((param) => {
4319
+ checkNode(param);
4320
+ });
4321
+ }
4322
+ },
4272
4323
  "ObjectExpression > Property[computed=false] > Identifier": (node) => {
4273
- if (validate.properties) {
4274
- const parent = node.parent;
4275
- if (node === parent.key && !isSourcesObjectAcceptingStaticObservableCreator(parent.parent.parent)) {
4276
- checkNode(node);
4324
+ if (!validate.objects) {
4325
+ return;
4326
+ }
4327
+ const parent = node.parent;
4328
+ if (node !== parent.key) {
4329
+ return;
4330
+ }
4331
+ const found = findParent(
4332
+ node,
4333
+ "CallExpression",
4334
+ "VariableDeclarator",
4335
+ "TSSatisfiesExpression",
4336
+ "TSAsExpression"
4337
+ );
4338
+ if (found) {
4339
+ if (isCallExpression(found)) {
4340
+ return;
4341
+ } else if (isVariableDeclarator(found) && !!found.id.typeAnnotation) {
4342
+ return;
4343
+ } else if (isTSAsExpression(found) || isTSSatisfiesExpression(found)) {
4344
+ return;
4277
4345
  }
4278
4346
  }
4347
+ checkNode(node, void 0, "forbiddenProperty");
4279
4348
  },
4280
4349
  "ObjectPattern > Property > Identifier": (node) => {
4281
4350
  const found = findParent(
@@ -4288,7 +4357,7 @@ var suffixSubjectsRule = ruleCreator({
4288
4357
  if (!found) {
4289
4358
  return;
4290
4359
  }
4291
- if (!validate.variables && found.type === _utils.AST_NODE_TYPES.VariableDeclarator) {
4360
+ if (!validate.variables && isVariableDeclarator(found)) {
4292
4361
  return;
4293
4362
  }
4294
4363
  if (!validate.parameters) {
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.2";
3
+ var version = "0.9.4";
4
4
 
5
5
  // src/configs/recommended.ts
6
6
  var createRecommendedConfig = (plugin2) => ({
@@ -117,7 +117,10 @@ function couldBeType(type, name2, qualified) {
117
117
  if (tsutils.isTypeReference(type)) {
118
118
  type = type.target;
119
119
  }
120
- if (isType(type, name2, qualified)) {
120
+ if (isType(type.symbol, name2, qualified)) {
121
+ return true;
122
+ }
123
+ if (type.aliasSymbol && isType(type.aliasSymbol, name2, qualified)) {
121
124
  return true;
122
125
  }
123
126
  if (tsutils.isUnionOrIntersectionType(type)) {
@@ -132,16 +135,16 @@ function couldBeType(type, name2, qualified) {
132
135
  }
133
136
  return false;
134
137
  }
135
- function isType(type, name2, qualified) {
136
- if (!type.symbol) {
138
+ function isType(symbol, name2, qualified) {
139
+ if (!symbol) {
137
140
  return false;
138
141
  }
139
142
  if (qualified && !qualified.name.test(
140
- qualified.typeChecker.getFullyQualifiedName(type.symbol)
143
+ qualified.typeChecker.getFullyQualifiedName(symbol)
141
144
  )) {
142
145
  return false;
143
146
  }
144
- return typeof name2 === "string" ? type.symbol.name === name2 : Boolean(type.symbol.name.match(name2));
147
+ return typeof name2 === "string" ? symbol.name === name2 : Boolean(symbol.name.match(name2));
145
148
  }
146
149
  function couldImplement(type, name2, qualified) {
147
150
  const { symbol } = type;
@@ -409,52 +412,6 @@ function findIsLastOperatorOrderValid(pipeCallExpression, operatorsRegExp, allow
409
412
  return { isOrderValid, operatorNode };
410
413
  }
411
414
 
412
- // src/constants.ts
413
- var defaultObservable = String.raw`[Aa]ction(s|s\$|\$)$`;
414
- var SOURCES_OBJECT_ACCEPTING_STATIC_OBSERVABLE_CREATORS = [
415
- "combineLatest",
416
- "forkJoin"
417
- ];
418
- var MULTIPLE_OBSERVABLE_ACCEPTING_STATIC_OBSERVABLE_CREATORS = [
419
- "combineLatest",
420
- "forkJoin",
421
- "merge",
422
- "zip",
423
- "concat",
424
- "race"
425
- ];
426
- var DEFAULT_UNBOUND_ALLOWED_TYPES = [
427
- "Signal"
428
- ];
429
- var DEFAULT_VALID_POST_COMPLETION_OPERATORS = [
430
- "count",
431
- "defaultIfEmpty",
432
- "endWith",
433
- "every",
434
- "finalize",
435
- "finally",
436
- "isEmpty",
437
- "last",
438
- "max",
439
- "min",
440
- "publish",
441
- "publishBehavior",
442
- "publishLast",
443
- "publishReplay",
444
- "reduce",
445
- "share",
446
- "shareReplay",
447
- "skipLast",
448
- "takeLast",
449
- "throwIfEmpty",
450
- "toArray"
451
- ];
452
-
453
- // src/utils/is-sources-object-accepting-static-observable-creator.ts
454
- function isSourcesObjectAcceptingStaticObservableCreator(expression) {
455
- return isCallExpression(expression) && isIdentifier(expression.callee) && SOURCES_OBJECT_ACCEPTING_STATIC_OBSERVABLE_CREATORS.includes(expression.callee.name);
456
- }
457
-
458
415
  // src/utils/rule-creator.ts
459
416
  import { ESLintUtils as ESLintUtils2 } from "@typescript-eslint/utils";
460
417
  var REPO_URL = "https://github.com/JasonWeinzierl/eslint-plugin-rxjs-x";
@@ -752,6 +709,9 @@ var finnishRule = ruleCreator({
752
709
  },
753
710
  "PropertyDefinition[computed=false]": (node) => {
754
711
  if (validate.properties) {
712
+ if (node.override) {
713
+ return;
714
+ }
755
715
  checkNode(node.key);
756
716
  }
757
717
  },
@@ -781,19 +741,44 @@ var finnishRule = ruleCreator({
781
741
  },
782
742
  "MethodDefinition[kind='get'][computed=false]": (node) => {
783
743
  if (validate.properties) {
744
+ if (node.override) {
745
+ return;
746
+ }
784
747
  checkNode(node.key, node);
785
748
  }
786
749
  },
787
750
  "MethodDefinition[kind='method'][computed=false]": (node) => {
788
751
  if (validate.methods) {
752
+ if (node.override) {
753
+ return;
754
+ }
789
755
  checkNode(node.key, node);
790
756
  }
791
757
  },
792
758
  "MethodDefinition[kind='set'][computed=false]": (node) => {
793
759
  if (validate.properties) {
760
+ if (node.override) {
761
+ return;
762
+ }
794
763
  checkNode(node.key, node);
795
764
  }
796
765
  },
766
+ "TSAbstractMethodDefinition[computed=false]": (node) => {
767
+ if (node.override) {
768
+ return;
769
+ }
770
+ if (validate.methods && node.kind === "method") {
771
+ checkNode(node.key, node);
772
+ }
773
+ if (validate.properties && (node.kind === "get" || node.kind === "set")) {
774
+ checkNode(node.key, node);
775
+ }
776
+ if (validate.parameters) {
777
+ node.value.params.forEach((param) => {
778
+ checkNode(param);
779
+ });
780
+ }
781
+ },
797
782
  "ObjectExpression > Property[computed=false] > Identifier": (node) => {
798
783
  if (!validate.objects) {
799
784
  return;
@@ -1147,6 +1132,49 @@ var noCreateRule = ruleCreator({
1147
1132
  import { ESLintUtils as ESLintUtils4 } from "@typescript-eslint/utils";
1148
1133
  import { stripIndent as stripIndent3 } from "common-tags";
1149
1134
  import ts4 from "typescript";
1135
+
1136
+ // src/constants.ts
1137
+ var defaultObservable = String.raw`[Aa]ction(s|s\$|\$)$`;
1138
+ var SOURCES_OBJECT_ACCEPTING_STATIC_OBSERVABLE_CREATORS = [
1139
+ "combineLatest",
1140
+ "forkJoin"
1141
+ ];
1142
+ var MULTIPLE_OBSERVABLE_ACCEPTING_STATIC_OBSERVABLE_CREATORS = [
1143
+ "combineLatest",
1144
+ "forkJoin",
1145
+ "merge",
1146
+ "zip",
1147
+ "concat",
1148
+ "race"
1149
+ ];
1150
+ var DEFAULT_UNBOUND_ALLOWED_TYPES = [
1151
+ "Signal"
1152
+ ];
1153
+ var DEFAULT_VALID_POST_COMPLETION_OPERATORS = [
1154
+ "count",
1155
+ "defaultIfEmpty",
1156
+ "endWith",
1157
+ "every",
1158
+ "finalize",
1159
+ "finally",
1160
+ "isEmpty",
1161
+ "last",
1162
+ "max",
1163
+ "min",
1164
+ "publish",
1165
+ "publishBehavior",
1166
+ "publishLast",
1167
+ "publishReplay",
1168
+ "reduce",
1169
+ "share",
1170
+ "shareReplay",
1171
+ "skipLast",
1172
+ "takeLast",
1173
+ "throwIfEmpty",
1174
+ "toArray"
1175
+ ];
1176
+
1177
+ // src/rules/no-cyclic-action.ts
1150
1178
  function isTypeReference2(type) {
1151
1179
  return Boolean(type.target);
1152
1180
  }
@@ -3389,7 +3417,7 @@ var noUnboundMethodsRule = ruleCreator({
3389
3417
  const { couldBeObservable, couldBeSubscription } = getTypeServices(context);
3390
3418
  const nodeMap = /* @__PURE__ */ new WeakMap();
3391
3419
  const [config = {}] = context.options;
3392
- const { allowTypes = [] } = config;
3420
+ const { allowTypes = DEFAULT_UNBOUND_ALLOWED_TYPES } = config;
3393
3421
  function mapArguments(node) {
3394
3422
  node.arguments.filter(isMemberExpression).forEach((arg) => {
3395
3423
  const argType = getTypeAtLocation(arg);
@@ -3711,6 +3739,16 @@ var noUnsafeSubjectNext = ruleCreator({
3711
3739
  // src/rules/no-unsafe-switchmap.ts
3712
3740
  import { stripIndent as stripIndent7 } from "common-tags";
3713
3741
  import decamelize from "decamelize";
3742
+ var DEFAULT_DISALLOW = [
3743
+ "add",
3744
+ "create",
3745
+ "delete",
3746
+ "post",
3747
+ "put",
3748
+ "remove",
3749
+ "set",
3750
+ "update"
3751
+ ];
3714
3752
  var defaultOptions15 = [];
3715
3753
  var noUnsafeSwitchmapRule = ruleCreator({
3716
3754
  defaultOptions: defaultOptions15,
@@ -3737,7 +3775,8 @@ var noUnsafeSwitchmapRule = ruleCreator({
3737
3775
  oneOf: [
3738
3776
  { type: "string", description: "A regular expression string." },
3739
3777
  { type: "array", items: { type: "string" }, description: "An array of words." }
3740
- ]
3778
+ ],
3779
+ default: DEFAULT_DISALLOW
3741
3780
  },
3742
3781
  observable: {
3743
3782
  type: "string",
@@ -3760,29 +3799,15 @@ var noUnsafeSwitchmapRule = ruleCreator({
3760
3799
  name: "no-unsafe-switchmap",
3761
3800
  create: (context) => {
3762
3801
  var _a, _b, _c;
3763
- const defaultDisallow = [
3764
- "add",
3765
- "create",
3766
- "delete",
3767
- "post",
3768
- "put",
3769
- "remove",
3770
- "set",
3771
- "update"
3772
- ];
3773
- let allowRegExp;
3774
- let disallowRegExp;
3775
- let observableRegExp;
3802
+ let allowRegExp = void 0;
3803
+ let disallowRegExp = void 0;
3776
3804
  const [config = {}] = context.options;
3777
- if (config.allow || config.disallow) {
3805
+ if (config.allow) {
3778
3806
  allowRegExp = createRegExpForWords((_a = config.allow) != null ? _a : []);
3779
- disallowRegExp = createRegExpForWords((_b = config.disallow) != null ? _b : []);
3780
- observableRegExp = new RegExp((_c = config.observable) != null ? _c : defaultObservable);
3781
3807
  } else {
3782
- allowRegExp = void 0;
3783
- disallowRegExp = createRegExpForWords(defaultDisallow);
3784
- observableRegExp = new RegExp(defaultObservable);
3808
+ disallowRegExp = createRegExpForWords((_b = config.disallow) != null ? _b : DEFAULT_DISALLOW);
3785
3809
  }
3810
+ const observableRegExp = new RegExp((_c = config.observable) != null ? _c : defaultObservable);
3786
3811
  const { couldBeObservable } = getTypeServices(context);
3787
3812
  function shouldDisallow(args) {
3788
3813
  const names = args.map((arg) => {
@@ -4137,8 +4162,9 @@ var preferRootOperatorsRule = ruleCreator({
4137
4162
  });
4138
4163
 
4139
4164
  // src/rules/suffix-subjects.ts
4140
- import { AST_NODE_TYPES as AST_NODE_TYPES8, ESLintUtils as ESLintUtils12 } from "@typescript-eslint/utils";
4165
+ import { ESLintUtils as ESLintUtils12 } from "@typescript-eslint/utils";
4141
4166
  var defaultOptions18 = [];
4167
+ var baseShouldHaveSuffix = 'Subject identifiers must end with "{{suffix}}".';
4142
4168
  var suffixSubjectsRule = ruleCreator({
4143
4169
  defaultOptions: defaultOptions18,
4144
4170
  meta: {
@@ -4147,13 +4173,15 @@ var suffixSubjectsRule = ruleCreator({
4147
4173
  requiresTypeChecking: true
4148
4174
  },
4149
4175
  messages: {
4150
- forbidden: `Subject identifiers must end with "{{suffix}}".`
4176
+ forbidden: baseShouldHaveSuffix,
4177
+ forbiddenProperty: `${baseShouldHaveSuffix} Add a type annotation, assertion, or 'satisfies' to silence this rule.`
4151
4178
  },
4152
4179
  schema: [
4153
4180
  {
4154
4181
  properties: {
4155
4182
  parameters: { type: "boolean", description: "Require for parameters." },
4156
- properties: { type: "boolean", description: "Require for properties." },
4183
+ properties: { type: "boolean", description: 'Require for properties, except object literal keys (see "objects" option).' },
4184
+ objects: { type: "boolean", description: "Require for object literal keys." },
4157
4185
  suffix: { type: "string", description: "The suffix to enforce." },
4158
4186
  types: { type: "object", description: "Enforce for specific types. Keys are a RegExp, values are a boolean." },
4159
4187
  variables: { type: "boolean", description: "Require for variables." }
@@ -4171,6 +4199,7 @@ var suffixSubjectsRule = ruleCreator({
4171
4199
  const validate = {
4172
4200
  parameters: true,
4173
4201
  properties: true,
4202
+ objects: true,
4174
4203
  variables: true,
4175
4204
  ...config
4176
4205
  };
@@ -4192,7 +4221,7 @@ var suffixSubjectsRule = ruleCreator({
4192
4221
  String.raw`${escapeRegExp(suffix)}\$?$`,
4193
4222
  "i"
4194
4223
  );
4195
- function checkNode(nameNode, typeNode) {
4224
+ function checkNode(nameNode, typeNode, shouldMessage = "forbidden") {
4196
4225
  const tsNode = esTreeNodeToTSNodeMap.get(nameNode);
4197
4226
  const text = tsNode.getText();
4198
4227
  if (!suffixRegex.test(text) && couldBeType2(typeNode != null ? typeNode : nameNode, "Subject")) {
@@ -4205,7 +4234,7 @@ var suffixSubjectsRule = ruleCreator({
4205
4234
  context.report({
4206
4235
  data: { suffix },
4207
4236
  loc: getLoc(tsNode),
4208
- messageId: "forbidden"
4237
+ messageId: shouldMessage
4209
4238
  });
4210
4239
  }
4211
4240
  }
@@ -4221,7 +4250,7 @@ var suffixSubjectsRule = ruleCreator({
4221
4250
  if (!found) {
4222
4251
  return;
4223
4252
  }
4224
- if (!validate.variables && found.type === AST_NODE_TYPES8.VariableDeclarator) {
4253
+ if (!validate.variables && isVariableDeclarator(found)) {
4225
4254
  return;
4226
4255
  }
4227
4256
  if (!validate.parameters) {
@@ -4240,6 +4269,9 @@ var suffixSubjectsRule = ruleCreator({
4240
4269
  "PropertyDefinition[computed=false]": (node) => {
4241
4270
  const anyNode = node;
4242
4271
  if (validate.properties) {
4272
+ if (node.override) {
4273
+ return;
4274
+ }
4243
4275
  checkNode(anyNode.key);
4244
4276
  }
4245
4277
  },
@@ -4261,21 +4293,58 @@ var suffixSubjectsRule = ruleCreator({
4261
4293
  },
4262
4294
  "MethodDefinition[kind='get'][computed=false]": (node) => {
4263
4295
  if (validate.properties) {
4296
+ if (node.override) {
4297
+ return;
4298
+ }
4264
4299
  checkNode(node.key, node);
4265
4300
  }
4266
4301
  },
4267
4302
  "MethodDefinition[kind='set'][computed=false]": (node) => {
4268
4303
  if (validate.properties) {
4304
+ if (node.override) {
4305
+ return;
4306
+ }
4269
4307
  checkNode(node.key, node);
4270
4308
  }
4271
4309
  },
4310
+ "TSAbstractMethodDefinition[computed=false]": (node) => {
4311
+ if (node.override) {
4312
+ return;
4313
+ }
4314
+ if (validate.properties && (node.kind === "get" || node.kind === "set")) {
4315
+ checkNode(node.key, node);
4316
+ }
4317
+ if (validate.parameters) {
4318
+ node.value.params.forEach((param) => {
4319
+ checkNode(param);
4320
+ });
4321
+ }
4322
+ },
4272
4323
  "ObjectExpression > Property[computed=false] > Identifier": (node) => {
4273
- if (validate.properties) {
4274
- const parent = node.parent;
4275
- if (node === parent.key && !isSourcesObjectAcceptingStaticObservableCreator(parent.parent.parent)) {
4276
- checkNode(node);
4324
+ if (!validate.objects) {
4325
+ return;
4326
+ }
4327
+ const parent = node.parent;
4328
+ if (node !== parent.key) {
4329
+ return;
4330
+ }
4331
+ const found = findParent(
4332
+ node,
4333
+ "CallExpression",
4334
+ "VariableDeclarator",
4335
+ "TSSatisfiesExpression",
4336
+ "TSAsExpression"
4337
+ );
4338
+ if (found) {
4339
+ if (isCallExpression(found)) {
4340
+ return;
4341
+ } else if (isVariableDeclarator(found) && !!found.id.typeAnnotation) {
4342
+ return;
4343
+ } else if (isTSAsExpression(found) || isTSSatisfiesExpression(found)) {
4344
+ return;
4277
4345
  }
4278
4346
  }
4347
+ checkNode(node, void 0, "forbiddenProperty");
4279
4348
  },
4280
4349
  "ObjectPattern > Property > Identifier": (node) => {
4281
4350
  const found = findParent(
@@ -4288,7 +4357,7 @@ var suffixSubjectsRule = ruleCreator({
4288
4357
  if (!found) {
4289
4358
  return;
4290
4359
  }
4291
- if (!validate.variables && found.type === AST_NODE_TYPES8.VariableDeclarator) {
4360
+ if (!validate.variables && isVariableDeclarator(found)) {
4292
4361
  return;
4293
4362
  }
4294
4363
  if (!validate.parameters) {
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.2",
4
+ "version": "0.9.4",
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>",
@@ -89,7 +89,7 @@
89
89
  "eslint-config-flat-gitignore": "^2.1.0",
90
90
  "eslint-doc-generator": "^2.4.0",
91
91
  "eslint-import-resolver-typescript": "^4.4.4",
92
- "eslint-plugin-eslint-plugin": "^7.3.0",
92
+ "eslint-plugin-eslint-plugin": "patch:eslint-plugin-eslint-plugin@npm%3A7.3.0#~/.yarn/patches/eslint-plugin-eslint-plugin-npm-7.3.0-d800475165.patch",
93
93
  "eslint-plugin-import-x": "^4.16.1",
94
94
  "eslint-plugin-n": "^17.23.2",
95
95
  "markdownlint-cli2": "~0.19.0",