eslint-plugin-rxjs-x 0.7.2 → 0.7.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.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  // package.json
2
2
  var name = "eslint-plugin-rxjs-x";
3
- var version = "0.7.2";
3
+ var version = "0.7.4";
4
4
 
5
5
  // src/configs/recommended.ts
6
6
  var createRecommendedConfig = (plugin2) => ({
@@ -74,11 +74,10 @@ var createStrictConfig = (plugin2) => ({
74
74
  });
75
75
 
76
76
  // src/rules/ban-observables.ts
77
- import { AST_NODE_TYPES } from "@typescript-eslint/utils";
77
+ import { AST_NODE_TYPES as AST_NODE_TYPES3 } from "@typescript-eslint/utils";
78
78
  import { stripIndent } from "common-tags";
79
79
 
80
- // src/utils.ts
81
- import { ESLintUtils } from "@typescript-eslint/utils";
80
+ // src/utils/create-regexp-for-words.ts
82
81
  function createRegExpForWords(config) {
83
82
  if (!(config == null ? void 0 : config.length)) {
84
83
  return void 0;
@@ -91,81 +90,11 @@ function createRegExpForWords(config) {
91
90
  const joined = words.map((word) => String.raw`(\b|_)${word}(\b|_)`).join("|");
92
91
  return new RegExp(`(${joined})`, flags);
93
92
  }
93
+
94
+ // src/utils/escape-regexp.ts
94
95
  function escapeRegExp(text) {
95
96
  return text.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
96
97
  }
97
- var REPO_URL = "https://github.com/JasonWeinzierl/eslint-plugin-rxjs-x";
98
- var ruleCreator = ESLintUtils.RuleCreator(
99
- (name2) => `${REPO_URL}/blob/v${version}/docs/rules/${name2}.md`
100
- );
101
-
102
- // src/rules/ban-observables.ts
103
- var defaultOptions = [];
104
- var banObservablesRule = ruleCreator({
105
- defaultOptions,
106
- meta: {
107
- docs: {
108
- description: "Disallow banned observable creators."
109
- },
110
- messages: {
111
- forbidden: "RxJS observable is banned: {{name}}{{explanation}}."
112
- },
113
- schema: [
114
- {
115
- type: "object",
116
- description: stripIndent`
117
- An object containing keys that are names of observable factory functions
118
- and values that are either booleans or strings containing the explanation for the ban.`
119
- }
120
- ],
121
- type: "problem"
122
- },
123
- name: "ban-observables",
124
- create: (context) => {
125
- const bans = [];
126
- const [config] = context.options;
127
- if (!config) {
128
- return {};
129
- }
130
- Object.entries(config).forEach(([key, value]) => {
131
- if (value !== false) {
132
- bans.push({
133
- explanation: typeof value === "string" ? value : "",
134
- regExp: new RegExp(`^${key}$`)
135
- });
136
- }
137
- });
138
- function getFailure(name2) {
139
- for (let b = 0, length = bans.length; b < length; ++b) {
140
- const ban = bans[b];
141
- if (ban.regExp.test(name2)) {
142
- const explanation = ban.explanation ? `: ${ban.explanation}` : "";
143
- return {
144
- messageId: "forbidden",
145
- data: { name: name2, explanation }
146
- };
147
- }
148
- }
149
- return void 0;
150
- }
151
- return {
152
- "ImportDeclaration[source.value='rxjs'] > ImportSpecifier": (node) => {
153
- const identifier = node.imported;
154
- const name2 = identifier.type === AST_NODE_TYPES.Identifier ? identifier.name : identifier.value;
155
- const failure = getFailure(name2);
156
- if (failure) {
157
- context.report({
158
- ...failure,
159
- node: identifier
160
- });
161
- }
162
- }
163
- };
164
- }
165
- });
166
-
167
- // src/rules/ban-operators.ts
168
- import { stripIndent as stripIndent2 } from "common-tags";
169
98
 
170
99
  // src/etc/could-be-function.ts
171
100
  import ts2 from "typescript";
@@ -281,84 +210,87 @@ function getLoc(node) {
281
210
  }
282
211
 
283
212
  // src/etc/get-type-services.ts
284
- import { ESLintUtils as ESLintUtils2 } from "@typescript-eslint/utils";
213
+ import { ESLintUtils } from "@typescript-eslint/utils";
285
214
  import ts4 from "typescript";
286
215
 
287
216
  // src/etc/is.ts
288
- import { AST_NODE_TYPES as AST_NODE_TYPES2 } from "@typescript-eslint/utils";
217
+ import { AST_NODE_TYPES } from "@typescript-eslint/utils";
289
218
  function hasTypeAnnotation(node) {
290
219
  return "typeAnnotation" in node && !!node.typeAnnotation;
291
220
  }
292
221
  function isArrayExpression(node) {
293
- return node.type === AST_NODE_TYPES2.ArrayExpression;
222
+ return node.type === AST_NODE_TYPES.ArrayExpression;
294
223
  }
295
224
  function isArrayPattern(node) {
296
- return node.type === AST_NODE_TYPES2.ArrayPattern;
225
+ return node.type === AST_NODE_TYPES.ArrayPattern;
297
226
  }
298
227
  function isArrowFunctionExpression(node) {
299
- return node.type === AST_NODE_TYPES2.ArrowFunctionExpression;
228
+ return node.type === AST_NODE_TYPES.ArrowFunctionExpression;
300
229
  }
301
230
  function isBlockStatement(node) {
302
- return node.type === AST_NODE_TYPES2.BlockStatement;
231
+ return node.type === AST_NODE_TYPES.BlockStatement;
303
232
  }
304
233
  function isCallExpression(node) {
305
- return node.type === AST_NODE_TYPES2.CallExpression;
234
+ return node.type === AST_NODE_TYPES.CallExpression;
306
235
  }
307
236
  function isChainExpression(node) {
308
- return node.type === AST_NODE_TYPES2.ChainExpression;
237
+ return node.type === AST_NODE_TYPES.ChainExpression;
309
238
  }
310
239
  function isFunctionDeclaration(node) {
311
- return node.type === AST_NODE_TYPES2.FunctionDeclaration;
240
+ return node.type === AST_NODE_TYPES.FunctionDeclaration;
312
241
  }
313
242
  function isFunctionExpression(node) {
314
- return node.type === AST_NODE_TYPES2.FunctionExpression;
243
+ return node.type === AST_NODE_TYPES.FunctionExpression;
315
244
  }
316
245
  function isIdentifier(node) {
317
- return node.type === AST_NODE_TYPES2.Identifier;
246
+ return node.type === AST_NODE_TYPES.Identifier;
318
247
  }
319
248
  function isImportDeclaration(node) {
320
- return node.type === AST_NODE_TYPES2.ImportDeclaration;
249
+ return node.type === AST_NODE_TYPES.ImportDeclaration;
321
250
  }
322
251
  function isImportNamespaceSpecifier(node) {
323
- return node.type === AST_NODE_TYPES2.ImportNamespaceSpecifier;
252
+ return node.type === AST_NODE_TYPES.ImportNamespaceSpecifier;
324
253
  }
325
254
  function isImportSpecifier(node) {
326
- return node.type === AST_NODE_TYPES2.ImportSpecifier;
255
+ return node.type === AST_NODE_TYPES.ImportSpecifier;
327
256
  }
328
257
  function isJSXExpressionContainer(node) {
329
- return node.type === AST_NODE_TYPES2.JSXExpressionContainer;
258
+ return node.type === AST_NODE_TYPES.JSXExpressionContainer;
330
259
  }
331
260
  function isLiteral(node) {
332
- return node.type === AST_NODE_TYPES2.Literal;
261
+ return node.type === AST_NODE_TYPES.Literal;
333
262
  }
334
263
  function isMemberExpression(node) {
335
- return node.type === AST_NODE_TYPES2.MemberExpression;
264
+ return node.type === AST_NODE_TYPES.MemberExpression;
336
265
  }
337
266
  function isMethodDefinition(node) {
338
- return node.type === AST_NODE_TYPES2.MethodDefinition;
267
+ return node.type === AST_NODE_TYPES.MethodDefinition;
339
268
  }
340
269
  function isObjectExpression(node) {
341
- return node.type === AST_NODE_TYPES2.ObjectExpression;
270
+ return node.type === AST_NODE_TYPES.ObjectExpression;
342
271
  }
343
272
  function isObjectPattern(node) {
344
- return node.type === AST_NODE_TYPES2.ObjectPattern;
273
+ return node.type === AST_NODE_TYPES.ObjectPattern;
345
274
  }
346
275
  function isProgram(node) {
347
- return node.type === AST_NODE_TYPES2.Program;
276
+ return node.type === AST_NODE_TYPES.Program;
348
277
  }
349
278
  function isProperty(node) {
350
- return node.type === AST_NODE_TYPES2.Property;
279
+ return node.type === AST_NODE_TYPES.Property;
351
280
  }
352
281
  function isPropertyDefinition(node) {
353
- return node.type === AST_NODE_TYPES2.PropertyDefinition;
282
+ return node.type === AST_NODE_TYPES.PropertyDefinition;
354
283
  }
355
284
  function isUnaryExpression(node) {
356
- return node.type === AST_NODE_TYPES2.UnaryExpression;
285
+ return node.type === AST_NODE_TYPES.UnaryExpression;
286
+ }
287
+ function isUnionType(node) {
288
+ return node.type === AST_NODE_TYPES.TSUnionType;
357
289
  }
358
290
 
359
291
  // src/etc/get-type-services.ts
360
292
  function getTypeServices(context) {
361
- const services = ESLintUtils2.getParserServices(context);
293
+ const services = ESLintUtils.getParserServices(context);
362
294
  const { esTreeNodeToTSNodeMap, program, getTypeAtLocation } = services;
363
295
  const typeChecker = program.getTypeChecker();
364
296
  const couldBeType2 = (node, name2, qualified) => {
@@ -415,18 +347,160 @@ function getTypeServices(context) {
415
347
 
416
348
  // src/etc/is-import.ts
417
349
  import { DefinitionType } from "@typescript-eslint/scope-manager";
418
- import { AST_NODE_TYPES as AST_NODE_TYPES3 } from "@typescript-eslint/utils";
350
+ import { AST_NODE_TYPES as AST_NODE_TYPES2 } from "@typescript-eslint/utils";
419
351
  function isImport(scope, name2, source) {
420
352
  const variable = scope.variables.find((variable2) => variable2.name === name2);
421
353
  if (variable) {
422
354
  return variable.defs.some(
423
- (def) => def.type === DefinitionType.ImportBinding && def.parent.type === AST_NODE_TYPES3.ImportDeclaration && (typeof source === "string" ? def.parent.source.value === source : source.test(def.parent.source.value))
355
+ (def) => def.type === DefinitionType.ImportBinding && def.parent.type === AST_NODE_TYPES2.ImportDeclaration && (typeof source === "string" ? def.parent.source.value === source : source.test(def.parent.source.value))
424
356
  );
425
357
  }
426
358
  return scope.upper ? isImport(scope.upper, name2, source) : false;
427
359
  }
428
360
 
361
+ // src/utils/find-is-last-operator-order-valid.ts
362
+ function findIsLastOperatorOrderValid(pipeCallExpression, operatorsRegExp, allow) {
363
+ let isOrderValid = true;
364
+ let operatorNode;
365
+ for (let i = pipeCallExpression.arguments.length - 1; i >= 0; i--) {
366
+ const arg = pipeCallExpression.arguments[i];
367
+ if (operatorNode) {
368
+ break;
369
+ }
370
+ if (!isCallExpression(arg)) {
371
+ isOrderValid = false;
372
+ continue;
373
+ }
374
+ let operatorName;
375
+ if (isIdentifier(arg.callee)) {
376
+ operatorName = arg.callee.name;
377
+ } else if (isMemberExpression(arg.callee) && isIdentifier(arg.callee.property)) {
378
+ operatorName = arg.callee.property.name;
379
+ } else {
380
+ isOrderValid = false;
381
+ continue;
382
+ }
383
+ if (operatorsRegExp.test(operatorName)) {
384
+ operatorNode = arg.callee;
385
+ break;
386
+ }
387
+ if (!allow.includes(operatorName)) {
388
+ isOrderValid = false;
389
+ continue;
390
+ }
391
+ }
392
+ return { isOrderValid, operatorNode };
393
+ }
394
+
395
+ // src/constants.ts
396
+ var defaultObservable = String.raw`[Aa]ction(s|s\$|\$)$`;
397
+ var SOURCES_OBJECT_ACCEPTING_STATIC_OBSERVABLE_CREATORS = [
398
+ "combineLatest",
399
+ "forkJoin"
400
+ ];
401
+ var DEFAULT_VALID_POST_COMPLETION_OPERATORS = [
402
+ "count",
403
+ "defaultIfEmpty",
404
+ "endWith",
405
+ "every",
406
+ "finalize",
407
+ "finally",
408
+ "isEmpty",
409
+ "last",
410
+ "max",
411
+ "min",
412
+ "publish",
413
+ "publishBehavior",
414
+ "publishLast",
415
+ "publishReplay",
416
+ "reduce",
417
+ "share",
418
+ "shareReplay",
419
+ "skipLast",
420
+ "takeLast",
421
+ "throwIfEmpty",
422
+ "toArray"
423
+ ];
424
+
425
+ // src/utils/is-sources-object-accepting-static-observable-creator.ts
426
+ function isSourcesObjectAcceptingStaticObservableCreator(expression) {
427
+ return isCallExpression(expression) && isIdentifier(expression.callee) && SOURCES_OBJECT_ACCEPTING_STATIC_OBSERVABLE_CREATORS.includes(expression.callee.name);
428
+ }
429
+
430
+ // src/utils/rule-creator.ts
431
+ import { ESLintUtils as ESLintUtils2 } from "@typescript-eslint/utils";
432
+ var REPO_URL = "https://github.com/JasonWeinzierl/eslint-plugin-rxjs-x";
433
+ var ruleCreator = ESLintUtils2.RuleCreator(
434
+ (name2) => `${REPO_URL}/blob/v${version}/docs/rules/${name2}.md`
435
+ );
436
+
437
+ // src/rules/ban-observables.ts
438
+ var defaultOptions = [];
439
+ var banObservablesRule = ruleCreator({
440
+ defaultOptions,
441
+ meta: {
442
+ docs: {
443
+ description: "Disallow banned observable creators."
444
+ },
445
+ messages: {
446
+ forbidden: "RxJS observable is banned: {{name}}{{explanation}}."
447
+ },
448
+ schema: [
449
+ {
450
+ type: "object",
451
+ description: stripIndent`
452
+ An object containing keys that are names of observable factory functions
453
+ and values that are either booleans or strings containing the explanation for the ban.`
454
+ }
455
+ ],
456
+ type: "problem"
457
+ },
458
+ name: "ban-observables",
459
+ create: (context) => {
460
+ const bans = [];
461
+ const [config] = context.options;
462
+ if (!config) {
463
+ return {};
464
+ }
465
+ Object.entries(config).forEach(([key, value]) => {
466
+ if (value !== false) {
467
+ bans.push({
468
+ explanation: typeof value === "string" ? value : "",
469
+ regExp: new RegExp(`^${key}$`)
470
+ });
471
+ }
472
+ });
473
+ function getFailure(name2) {
474
+ for (let b = 0, length = bans.length; b < length; ++b) {
475
+ const ban = bans[b];
476
+ if (ban.regExp.test(name2)) {
477
+ const explanation = ban.explanation ? `: ${ban.explanation}` : "";
478
+ return {
479
+ messageId: "forbidden",
480
+ data: { name: name2, explanation }
481
+ };
482
+ }
483
+ }
484
+ return void 0;
485
+ }
486
+ return {
487
+ "ImportDeclaration[source.value='rxjs'] > ImportSpecifier": (node) => {
488
+ const identifier = node.imported;
489
+ const name2 = identifier.type === AST_NODE_TYPES3.Identifier ? identifier.name : identifier.value;
490
+ const failure = getFailure(name2);
491
+ if (failure) {
492
+ context.report({
493
+ ...failure,
494
+ node: identifier
495
+ });
496
+ }
497
+ }
498
+ };
499
+ }
500
+ });
501
+
429
502
  // src/rules/ban-operators.ts
503
+ import { stripIndent as stripIndent2 } from "common-tags";
430
504
  var defaultOptions2 = [];
431
505
  var banOperatorsRule = ruleCreator({
432
506
  defaultOptions: defaultOptions2,
@@ -681,7 +755,7 @@ var finnishRule = ruleCreator({
681
755
  "ObjectExpression > Property[computed=false] > Identifier": (node) => {
682
756
  if (validate.properties) {
683
757
  const parent = node.parent;
684
- if (node === parent.key) {
758
+ if (node === parent.key && !isSourcesObjectAcceptingStaticObservableCreator(parent.parent.parent)) {
685
759
  checkNode(node);
686
760
  }
687
761
  }
@@ -992,11 +1066,6 @@ var noCreateRule = ruleCreator({
992
1066
  import { ESLintUtils as ESLintUtils4 } from "@typescript-eslint/utils";
993
1067
  import { stripIndent as stripIndent3 } from "common-tags";
994
1068
  import ts5 from "typescript";
995
-
996
- // src/constants.ts
997
- var defaultObservable = String.raw`[Aa]ction(s|s\$|\$)$`;
998
-
999
- // src/rules/no-cyclic-action.ts
1000
1069
  function isTypeReference2(type) {
1001
1070
  return Boolean(type.target);
1002
1071
  }
@@ -1121,21 +1190,25 @@ var noExplicitGenericsRule = ruleCreator({
1121
1190
  });
1122
1191
  }
1123
1192
  function checkBehaviorSubjects(node) {
1193
+ var _a;
1124
1194
  const parent = node.parent;
1125
1195
  const {
1126
1196
  arguments: [value]
1127
1197
  } = parent;
1128
- if (isArrayExpression(value) || isObjectExpression(value)) {
1198
+ const typeArgs = (_a = parent.typeArguments) == null ? void 0 : _a.params[0];
1199
+ if (isArrayExpression(value) || isObjectExpression(value) || typeArgs && isUnionType(typeArgs)) {
1129
1200
  return;
1130
1201
  }
1131
1202
  report(node);
1132
1203
  }
1133
1204
  function checkNotifications(node) {
1205
+ var _a;
1134
1206
  const parent = node.parent;
1135
1207
  const {
1136
1208
  arguments: [, value]
1137
1209
  } = parent;
1138
- if (isArrayExpression(value) || isObjectExpression(value)) {
1210
+ const typeArgs = (_a = parent.typeArguments) == null ? void 0 : _a.params[0];
1211
+ if (isArrayExpression(value) || isObjectExpression(value) || typeArgs && isUnionType(typeArgs)) {
1139
1212
  return;
1140
1213
  }
1141
1214
  report(node);
@@ -1765,8 +1838,10 @@ var noIgnoredSubscribeRule = ruleCreator({
1765
1838
  });
1766
1839
 
1767
1840
  // src/rules/no-ignored-subscription.ts
1841
+ import { stripIndent as stripIndent4 } from "common-tags";
1842
+ var defaultOptions7 = [];
1768
1843
  var noIgnoredSubscriptionRule = ruleCreator({
1769
- defaultOptions: [],
1844
+ defaultOptions: defaultOptions7,
1770
1845
  meta: {
1771
1846
  docs: {
1772
1847
  description: "Disallow ignoring the subscription returned by `subscribe`.",
@@ -1775,12 +1850,44 @@ var noIgnoredSubscriptionRule = ruleCreator({
1775
1850
  messages: {
1776
1851
  forbidden: "Ignoring returned subscriptions is forbidden."
1777
1852
  },
1778
- schema: [],
1853
+ schema: [
1854
+ {
1855
+ properties: {
1856
+ completers: { type: "array", items: { type: "string" }, description: "An array of operator names that will complete the observable and silence this rule.", default: ["takeUntil", "takeWhile", "take", "first", "last", "takeUntilDestroyed"] },
1857
+ postCompleters: { type: "array", items: { type: "string" }, description: "An array of operator names that are allowed to follow the completion operators.", default: DEFAULT_VALID_POST_COMPLETION_OPERATORS }
1858
+ },
1859
+ type: "object",
1860
+ description: stripIndent4`
1861
+ An object with optional \`completers\` and \`postCompleters\` properties.
1862
+ The \`completers\` property is an array containing the names of operators that will complete the observable and silence this rule.
1863
+ The \`postCompleters\` property is an array containing the names of the operators that are allowed to follow the completion operators.
1864
+ `
1865
+ }
1866
+ ],
1779
1867
  type: "problem"
1780
1868
  },
1781
1869
  name: "no-ignored-subscription",
1782
1870
  create: (context) => {
1871
+ const [config = {}] = context.options;
1872
+ const {
1873
+ completers = ["takeUntil", "takeWhile", "take", "first", "last", "takeUntilDestroyed"],
1874
+ postCompleters = DEFAULT_VALID_POST_COMPLETION_OPERATORS
1875
+ } = config;
1876
+ const checkedOperatorsRegExp = new RegExp(
1877
+ `^(${completers.join("|")})$`
1878
+ );
1783
1879
  const { couldBeObservable, couldBeType: couldBeType2 } = getTypeServices(context);
1880
+ function hasAllowedOperator(node) {
1881
+ if (isCallExpression(node) && isMemberExpression(node.callee) && isIdentifier(node.callee.property) && node.callee.property.name === "pipe") {
1882
+ const { isOrderValid, operatorNode } = findIsLastOperatorOrderValid(
1883
+ node,
1884
+ checkedOperatorsRegExp,
1885
+ postCompleters
1886
+ );
1887
+ return isOrderValid && !!operatorNode;
1888
+ }
1889
+ return false;
1890
+ }
1784
1891
  return {
1785
1892
  "ExpressionStatement > CallExpression > MemberExpression[property.name='subscribe']": (node) => {
1786
1893
  if (couldBeObservable(node.object)) {
@@ -1788,6 +1895,9 @@ var noIgnoredSubscriptionRule = ruleCreator({
1788
1895
  if (callExpression.arguments.length === 1 && couldBeType2(callExpression.arguments[0], "Subscriber")) {
1789
1896
  return;
1790
1897
  }
1898
+ if (hasAllowedOperator(node.object)) {
1899
+ return;
1900
+ }
1791
1901
  context.report({
1792
1902
  messageId: "forbidden",
1793
1903
  node: node.property
@@ -1862,9 +1972,9 @@ function isParenthesised(sourceCode, node) {
1862
1972
  const after = sourceCode.getTokenAfter(node);
1863
1973
  return before && after && before.value === "(" && before.range[1] <= node.range[0] && after.value === ")" && after.range[0] >= node.range[1];
1864
1974
  }
1865
- var defaultOptions7 = [];
1975
+ var defaultOptions8 = [];
1866
1976
  var noImplicitAnyCatchRule = ruleCreator({
1867
- defaultOptions: defaultOptions7,
1977
+ defaultOptions: defaultOptions8,
1868
1978
  meta: {
1869
1979
  docs: {
1870
1980
  description: "Disallow implicit `any` error parameters in `catchError` operators.",
@@ -2138,9 +2248,9 @@ function parseChecksVoidReturn(checksVoidReturn) {
2138
2248
  };
2139
2249
  }
2140
2250
  }
2141
- var defaultOptions8 = [];
2251
+ var defaultOptions9 = [];
2142
2252
  var noMisusedObservablesRule = ruleCreator({
2143
- defaultOptions: defaultOptions8,
2253
+ defaultOptions: defaultOptions9,
2144
2254
  meta: {
2145
2255
  docs: {
2146
2256
  description: "Disallow Observables in places not designed to handle them.",
@@ -2628,9 +2738,9 @@ function isExpressionObserver(expressionStatement, couldBeType2) {
2628
2738
 
2629
2739
  // src/rules/no-sharereplay.ts
2630
2740
  import { AST_NODE_TYPES as AST_NODE_TYPES7 } from "@typescript-eslint/utils";
2631
- var defaultOptions9 = [];
2741
+ var defaultOptions10 = [];
2632
2742
  var noSharereplayRule = ruleCreator({
2633
- defaultOptions: defaultOptions9,
2743
+ defaultOptions: defaultOptions10,
2634
2744
  meta: {
2635
2745
  docs: {
2636
2746
  description: "Disallow unsafe `shareReplay` usage.",
@@ -3069,10 +3179,10 @@ var noUnboundMethodsRule = ruleCreator({
3069
3179
  });
3070
3180
 
3071
3181
  // src/rules/no-unsafe-catch.ts
3072
- import { stripIndent as stripIndent4 } from "common-tags";
3073
- var defaultOptions10 = [];
3182
+ import { stripIndent as stripIndent5 } from "common-tags";
3183
+ var defaultOptions11 = [];
3074
3184
  var noUnsafeCatchRule = ruleCreator({
3075
- defaultOptions: defaultOptions10,
3185
+ defaultOptions: defaultOptions11,
3076
3186
  meta: {
3077
3187
  docs: {
3078
3188
  description: "Disallow unsafe `catchError` usage in effects and epics.",
@@ -3087,7 +3197,7 @@ var noUnsafeCatchRule = ruleCreator({
3087
3197
  observable: { type: "string", description: "A RegExp that matches an effect or epic's actions observable.", default: defaultObservable }
3088
3198
  },
3089
3199
  type: "object",
3090
- description: stripIndent4`
3200
+ description: stripIndent5`
3091
3201
  An optional object with an optional \`observable\` property.
3092
3202
  The property can be specified as a regular expression string and is used to identify the action observables from which effects and epics are composed.`
3093
3203
  }
@@ -3130,10 +3240,10 @@ var noUnsafeCatchRule = ruleCreator({
3130
3240
  });
3131
3241
 
3132
3242
  // src/rules/no-unsafe-first.ts
3133
- import { stripIndent as stripIndent5 } from "common-tags";
3134
- var defaultOptions11 = [];
3243
+ import { stripIndent as stripIndent6 } from "common-tags";
3244
+ var defaultOptions12 = [];
3135
3245
  var noUnsafeFirstRule = ruleCreator({
3136
- defaultOptions: defaultOptions11,
3246
+ defaultOptions: defaultOptions12,
3137
3247
  meta: {
3138
3248
  docs: {
3139
3249
  description: "Disallow unsafe `first`/`take` usage in effects and epics.",
@@ -3148,7 +3258,7 @@ var noUnsafeFirstRule = ruleCreator({
3148
3258
  observable: { type: "string", description: "A RegExp that matches an effect or epic's actions observable.", default: defaultObservable }
3149
3259
  },
3150
3260
  type: "object",
3151
- description: stripIndent5`
3261
+ description: stripIndent6`
3152
3262
  An optional object with an optional \`observable\` property.
3153
3263
  The property can be specified as a regular expression string and is used to identify the action observables from which effects and epics are composed.`
3154
3264
  }
@@ -3253,11 +3363,11 @@ var noUnsafeSubjectNext = ruleCreator({
3253
3363
  });
3254
3364
 
3255
3365
  // src/rules/no-unsafe-switchmap.ts
3256
- import { stripIndent as stripIndent6 } from "common-tags";
3366
+ import { stripIndent as stripIndent7 } from "common-tags";
3257
3367
  import decamelize from "decamelize";
3258
- var defaultOptions12 = [];
3368
+ var defaultOptions13 = [];
3259
3369
  var noUnsafeSwitchmapRule = ruleCreator({
3260
- defaultOptions: defaultOptions12,
3370
+ defaultOptions: defaultOptions13,
3261
3371
  meta: {
3262
3372
  docs: {
3263
3373
  description: "Disallow unsafe `switchMap` usage in effects and epics.",
@@ -3290,7 +3400,7 @@ var noUnsafeSwitchmapRule = ruleCreator({
3290
3400
  }
3291
3401
  },
3292
3402
  type: "object",
3293
- description: stripIndent6`
3403
+ description: stripIndent7`
3294
3404
  An optional object with optional \`allow\`, \`disallow\` and \`observable\` properties.
3295
3405
  The properties can be specified as regular expression strings or as arrays of words.
3296
3406
  The \`allow\` or \`disallow\` properties are mutually exclusive. Whether or not
@@ -3379,33 +3489,10 @@ var noUnsafeSwitchmapRule = ruleCreator({
3379
3489
  });
3380
3490
 
3381
3491
  // src/rules/no-unsafe-takeuntil.ts
3382
- import { stripIndent as stripIndent7 } from "common-tags";
3383
- var defaultOptions13 = [];
3384
- var allowedOperators = [
3385
- "count",
3386
- "defaultIfEmpty",
3387
- "endWith",
3388
- "every",
3389
- "finalize",
3390
- "finally",
3391
- "isEmpty",
3392
- "last",
3393
- "max",
3394
- "min",
3395
- "publish",
3396
- "publishBehavior",
3397
- "publishLast",
3398
- "publishReplay",
3399
- "reduce",
3400
- "share",
3401
- "shareReplay",
3402
- "skipLast",
3403
- "takeLast",
3404
- "throwIfEmpty",
3405
- "toArray"
3406
- ];
3492
+ import { stripIndent as stripIndent8 } from "common-tags";
3493
+ var defaultOptions14 = [];
3407
3494
  var noUnsafeTakeuntilRule = ruleCreator({
3408
- defaultOptions: defaultOptions13,
3495
+ defaultOptions: defaultOptions14,
3409
3496
  meta: {
3410
3497
  docs: {
3411
3498
  description: "Disallow applying operators after `takeUntil`.",
@@ -3419,10 +3506,10 @@ var noUnsafeTakeuntilRule = ruleCreator({
3419
3506
  {
3420
3507
  properties: {
3421
3508
  alias: { type: "array", items: { type: "string" }, description: "An array of operator names that should be treated similarly to `takeUntil`." },
3422
- allow: { type: "array", items: { type: "string" }, description: "An array of operator names that are allowed to follow `takeUntil`.", default: allowedOperators }
3509
+ allow: { type: "array", items: { type: "string" }, description: "An array of operator names that are allowed to follow `takeUntil`.", default: DEFAULT_VALID_POST_COMPLETION_OPERATORS }
3423
3510
  },
3424
3511
  type: "object",
3425
- description: stripIndent7`
3512
+ description: stripIndent8`
3426
3513
  An optional object with optional \`alias\` and \`allow\` properties.
3427
3514
  The \`alias\` property is an array containing the names of operators that aliases for \`takeUntil\`.
3428
3515
  The \`allow\` property is an array containing the names of the operators that are allowed to follow \`takeUntil\`.`
@@ -3434,7 +3521,7 @@ var noUnsafeTakeuntilRule = ruleCreator({
3434
3521
  create: (context) => {
3435
3522
  let checkedOperatorsRegExp = /^takeUntil$/;
3436
3523
  const [config = {}] = context.options;
3437
- const { alias, allow = allowedOperators } = config;
3524
+ const { alias, allow = DEFAULT_VALID_POST_COMPLETION_OPERATORS } = config;
3438
3525
  if (alias) {
3439
3526
  checkedOperatorsRegExp = new RegExp(
3440
3527
  `^(${alias.concat("takeUntil").join("|")})$`
@@ -3446,35 +3533,17 @@ var noUnsafeTakeuntilRule = ruleCreator({
3446
3533
  if (!pipeCallExpression.arguments || !couldBeObservable(pipeCallExpression)) {
3447
3534
  return;
3448
3535
  }
3449
- pipeCallExpression.arguments.reduceRight((state, arg) => {
3450
- if (state === "taken") {
3451
- return state;
3452
- }
3453
- if (!isCallExpression(arg)) {
3454
- return "disallowed";
3455
- }
3456
- let operatorName;
3457
- if (isIdentifier(arg.callee)) {
3458
- operatorName = arg.callee.name;
3459
- } else if (isMemberExpression(arg.callee) && isIdentifier(arg.callee.property)) {
3460
- operatorName = arg.callee.property.name;
3461
- } else {
3462
- return "disallowed";
3463
- }
3464
- if (checkedOperatorsRegExp.test(operatorName)) {
3465
- if (state === "disallowed") {
3466
- context.report({
3467
- messageId: "forbidden",
3468
- node: arg.callee
3469
- });
3470
- }
3471
- return "taken";
3472
- }
3473
- if (!allow.includes(operatorName)) {
3474
- return "disallowed";
3475
- }
3476
- return state;
3477
- }, "allowed");
3536
+ const { isOrderValid, operatorNode } = findIsLastOperatorOrderValid(
3537
+ pipeCallExpression,
3538
+ checkedOperatorsRegExp,
3539
+ allow
3540
+ );
3541
+ if (!isOrderValid && operatorNode) {
3542
+ context.report({
3543
+ messageId: "forbidden",
3544
+ node: operatorNode
3545
+ });
3546
+ }
3478
3547
  }
3479
3548
  return {
3480
3549
  [`CallExpression[callee.property.name='pipe'] > CallExpression[callee.name=${checkedOperatorsRegExp}]`]: checkNode,
@@ -3484,9 +3553,9 @@ var noUnsafeTakeuntilRule = ruleCreator({
3484
3553
  });
3485
3554
 
3486
3555
  // src/rules/prefer-observer.ts
3487
- var defaultOptions14 = [];
3556
+ var defaultOptions15 = [];
3488
3557
  var preferObserverRule = ruleCreator({
3489
- defaultOptions: defaultOptions14,
3558
+ defaultOptions: defaultOptions15,
3490
3559
  meta: {
3491
3560
  docs: {
3492
3561
  description: "Disallow passing separate handlers to `subscribe` and `tap`.",
@@ -3722,9 +3791,9 @@ var preferRootOperatorsRule = ruleCreator({
3722
3791
 
3723
3792
  // src/rules/suffix-subjects.ts
3724
3793
  import { AST_NODE_TYPES as AST_NODE_TYPES9, ESLintUtils as ESLintUtils11 } from "@typescript-eslint/utils";
3725
- var defaultOptions15 = [];
3794
+ var defaultOptions16 = [];
3726
3795
  var suffixSubjectsRule = ruleCreator({
3727
- defaultOptions: defaultOptions15,
3796
+ defaultOptions: defaultOptions16,
3728
3797
  meta: {
3729
3798
  docs: {
3730
3799
  description: "Enforce the use of a suffix in subject identifiers.",
@@ -3856,7 +3925,7 @@ var suffixSubjectsRule = ruleCreator({
3856
3925
  "ObjectExpression > Property[computed=false] > Identifier": (node) => {
3857
3926
  if (validate.properties) {
3858
3927
  const parent = node.parent;
3859
- if (node === parent.key) {
3928
+ if (node === parent.key && !isSourcesObjectAcceptingStaticObservableCreator(parent.parent.parent)) {
3860
3929
  checkNode(node);
3861
3930
  }
3862
3931
  }
@@ -3921,9 +3990,9 @@ var suffixSubjectsRule = ruleCreator({
3921
3990
  // src/rules/throw-error.ts
3922
3991
  import { ESLintUtils as ESLintUtils12 } from "@typescript-eslint/utils";
3923
3992
  import * as tsutils4 from "ts-api-utils";
3924
- var defaultOptions16 = [];
3993
+ var defaultOptions17 = [];
3925
3994
  var throwErrorRule = ruleCreator({
3926
- defaultOptions: defaultOptions16,
3995
+ defaultOptions: defaultOptions17,
3927
3996
  meta: {
3928
3997
  docs: {
3929
3998
  description: "Enforce passing only `Error` values to `throwError`.",