eslint-plugin-rxjs-x 0.9.4 → 1.0.0

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 DELETED
@@ -1,4576 +0,0 @@
1
- // package.json
2
- var name = "eslint-plugin-rxjs-x";
3
- var version = "0.9.4";
4
-
5
- // src/configs/recommended.ts
6
- var createRecommendedConfig = (plugin2) => ({
7
- ...baseConfig,
8
- name: "rxjs-x/recommended",
9
- plugins: {
10
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion -- "A type annotation is necessary."
11
- "rxjs-x": plugin2
12
- }
13
- });
14
- var createLegacyRecommendedConfig = () => ({
15
- ...baseConfig,
16
- plugins: ["rxjs-x"]
17
- });
18
- var baseConfig = {
19
- rules: {
20
- "rxjs-x/no-async-subscribe": "error",
21
- "rxjs-x/no-create": "error",
22
- "rxjs-x/no-ignored-notifier": "error",
23
- "rxjs-x/no-ignored-replay-buffer": "error",
24
- "rxjs-x/no-ignored-takewhile-value": "error",
25
- "rxjs-x/no-implicit-any-catch": "error",
26
- "rxjs-x/no-index": "error",
27
- "rxjs-x/no-internal": "error",
28
- "rxjs-x/no-nested-subscribe": "error",
29
- "rxjs-x/no-redundant-notify": "error",
30
- "rxjs-x/no-sharereplay": "error",
31
- "rxjs-x/no-subject-unsubscribe": "error",
32
- "rxjs-x/no-subscribe-in-pipe": "error",
33
- "rxjs-x/no-topromise": "error",
34
- "rxjs-x/no-unbound-methods": "error",
35
- "rxjs-x/no-unsafe-subject-next": "error",
36
- "rxjs-x/no-unsafe-takeuntil": "error",
37
- "rxjs-x/prefer-observer": "error",
38
- "rxjs-x/prefer-root-operators": "error",
39
- "rxjs-x/throw-error": "error"
40
- }
41
- };
42
-
43
- // src/configs/strict.ts
44
- var createStrictConfig = (plugin2) => ({
45
- name: "rxjs-x/strict",
46
- plugins: {
47
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion -- "A type annotation is necessary."
48
- "rxjs-x": plugin2
49
- },
50
- rules: {
51
- "rxjs-x/no-async-subscribe": "error",
52
- "rxjs-x/no-create": "error",
53
- "rxjs-x/no-exposed-subjects": "error",
54
- "rxjs-x/no-floating-observables": "error",
55
- "rxjs-x/no-ignored-default-value": "error",
56
- "rxjs-x/no-ignored-error": "error",
57
- "rxjs-x/no-ignored-notifier": "error",
58
- "rxjs-x/no-ignored-replay-buffer": "error",
59
- "rxjs-x/no-ignored-takewhile-value": "error",
60
- "rxjs-x/no-implicit-any-catch": ["error", {
61
- allowExplicitAny: false
62
- }],
63
- "rxjs-x/no-index": "error",
64
- "rxjs-x/no-internal": "error",
65
- "rxjs-x/no-misused-observables": "error",
66
- "rxjs-x/no-nested-subscribe": "error",
67
- "rxjs-x/no-redundant-notify": "error",
68
- "rxjs-x/no-sharereplay-before-takeuntil": "error",
69
- "rxjs-x/no-sharereplay": "error",
70
- "rxjs-x/no-subclass": "error",
71
- "rxjs-x/no-subject-unsubscribe": "error",
72
- "rxjs-x/no-subscribe-in-pipe": "error",
73
- "rxjs-x/no-topromise": "error",
74
- "rxjs-x/no-unbound-methods": "error",
75
- "rxjs-x/no-unnecessary-collection": "error",
76
- "rxjs-x/no-unsafe-subject-next": "error",
77
- "rxjs-x/no-unsafe-takeuntil": "error",
78
- "rxjs-x/prefer-observer": "error",
79
- "rxjs-x/prefer-root-operators": "error",
80
- "rxjs-x/throw-error": ["error", {
81
- allowThrowingAny: false,
82
- allowThrowingUnknown: false
83
- }]
84
- }
85
- });
86
-
87
- // src/rules/ban-observables.ts
88
- import { AST_NODE_TYPES as AST_NODE_TYPES3 } from "@typescript-eslint/utils";
89
- import { stripIndent } from "common-tags";
90
-
91
- // src/utils/create-regexp-for-words.ts
92
- function createRegExpForWords(config) {
93
- if (!(config == null ? void 0 : config.length)) {
94
- return void 0;
95
- }
96
- const flags = "i";
97
- if (typeof config === "string") {
98
- return new RegExp(config, flags);
99
- }
100
- const words = config;
101
- const joined = words.map((word) => String.raw`(\b|_)${word}(\b|_)`).join("|");
102
- return new RegExp(`(${joined})`, flags);
103
- }
104
-
105
- // src/utils/escape-regexp.ts
106
- function escapeRegExp(text) {
107
- return text.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
108
- }
109
-
110
- // src/etc/could-be-function.ts
111
- import ts2 from "typescript";
112
-
113
- // src/etc/could-be-type.ts
114
- import * as tsutils from "ts-api-utils";
115
- import ts from "typescript";
116
- function couldBeType(type, name2, qualified) {
117
- if (tsutils.isTypeReference(type)) {
118
- type = type.target;
119
- }
120
- if (isType(type.symbol, name2, qualified)) {
121
- return true;
122
- }
123
- if (type.aliasSymbol && isType(type.aliasSymbol, name2, qualified)) {
124
- return true;
125
- }
126
- if (tsutils.isUnionOrIntersectionType(type)) {
127
- return type.types.some((t) => couldBeType(t, name2, qualified));
128
- }
129
- const baseTypes = type.getBaseTypes();
130
- if (baseTypes == null ? void 0 : baseTypes.some((t) => couldBeType(t, name2, qualified))) {
131
- return true;
132
- }
133
- if (couldImplement(type, name2, qualified)) {
134
- return true;
135
- }
136
- return false;
137
- }
138
- function isType(symbol, name2, qualified) {
139
- if (!symbol) {
140
- return false;
141
- }
142
- if (qualified && !qualified.name.test(
143
- qualified.typeChecker.getFullyQualifiedName(symbol)
144
- )) {
145
- return false;
146
- }
147
- return typeof name2 === "string" ? symbol.name === name2 : Boolean(symbol.name.match(name2));
148
- }
149
- function couldImplement(type, name2, qualified) {
150
- const { symbol } = type;
151
- if (symbol) {
152
- const { valueDeclaration } = symbol;
153
- if (valueDeclaration && ts.isClassDeclaration(valueDeclaration)) {
154
- const { heritageClauses } = valueDeclaration;
155
- if (heritageClauses) {
156
- const implemented = heritageClauses.some(
157
- ({ token, types }) => token === ts.SyntaxKind.ImplementsKeyword && types.some((node) => isMatchingNode(node, name2, qualified))
158
- );
159
- if (implemented) {
160
- return true;
161
- }
162
- }
163
- }
164
- }
165
- return false;
166
- }
167
- function isMatchingNode(node, name2, qualified) {
168
- const { expression } = node;
169
- if (qualified) {
170
- const type = qualified.typeChecker.getTypeAtLocation(expression);
171
- if (type) {
172
- const qualifiedName = qualified.typeChecker.getFullyQualifiedName(
173
- type.symbol
174
- );
175
- if (!qualified.name.test(qualifiedName)) {
176
- return false;
177
- }
178
- }
179
- }
180
- const text = expression.getText();
181
- return typeof name2 === "string" ? text === name2 : Boolean(text.match(name2));
182
- }
183
-
184
- // src/etc/could-be-function.ts
185
- function couldBeFunction(type) {
186
- return type.getCallSignatures().length > 0 || couldBeType(type, "Function") || couldBeType(type, "ArrowFunction") || couldBeType(type, ts2.InternalSymbolName.Function);
187
- }
188
-
189
- // src/etc/find-parent.ts
190
- function findParent(node, ...args) {
191
- const [arg] = args;
192
- const predicate = typeof arg === "function" ? arg : (type) => !args.includes(type) ? "continue" : "return";
193
- let parent = node.parent;
194
- while (parent) {
195
- switch (predicate(parent.type)) {
196
- case "break":
197
- return void 0;
198
- case "return":
199
- return parent;
200
- default:
201
- break;
202
- }
203
- parent = parent.parent;
204
- }
205
- return void 0;
206
- }
207
-
208
- // src/etc/get-loc.ts
209
- import ts3 from "typescript";
210
- function getLoc(node) {
211
- const sourceFile = node.getSourceFile();
212
- const start = ts3.getLineAndCharacterOfPosition(sourceFile, node.getStart());
213
- const end = ts3.getLineAndCharacterOfPosition(sourceFile, node.getEnd());
214
- return {
215
- start: {
216
- line: start.line + 1,
217
- column: start.character
218
- },
219
- end: {
220
- line: end.line + 1,
221
- column: end.character
222
- }
223
- };
224
- }
225
-
226
- // src/etc/get-type-services.ts
227
- import { ESLintUtils } from "@typescript-eslint/utils";
228
- import * as tsutils2 from "ts-api-utils";
229
-
230
- // src/etc/is.ts
231
- import { AST_NODE_TYPES } from "@typescript-eslint/utils";
232
- function hasTypeAnnotation(node) {
233
- return "typeAnnotation" in node && !!node.typeAnnotation;
234
- }
235
- function isAccessorProperty(node) {
236
- return node.type === AST_NODE_TYPES.AccessorProperty;
237
- }
238
- function isArrayExpression(node) {
239
- return node.type === AST_NODE_TYPES.ArrayExpression;
240
- }
241
- function isArrayPattern(node) {
242
- return node.type === AST_NODE_TYPES.ArrayPattern;
243
- }
244
- function isArrowFunctionExpression(node) {
245
- return node.type === AST_NODE_TYPES.ArrowFunctionExpression;
246
- }
247
- function isBlockStatement(node) {
248
- return node.type === AST_NODE_TYPES.BlockStatement;
249
- }
250
- function isCallExpression(node) {
251
- return node.type === AST_NODE_TYPES.CallExpression;
252
- }
253
- function isChainExpression(node) {
254
- return node.type === AST_NODE_TYPES.ChainExpression;
255
- }
256
- function isFunctionDeclaration(node) {
257
- return node.type === AST_NODE_TYPES.FunctionDeclaration;
258
- }
259
- function isFunctionExpression(node) {
260
- return node.type === AST_NODE_TYPES.FunctionExpression;
261
- }
262
- function isIdentifier(node) {
263
- return node.type === AST_NODE_TYPES.Identifier;
264
- }
265
- function isImportDeclaration(node) {
266
- return node.type === AST_NODE_TYPES.ImportDeclaration;
267
- }
268
- function isImportNamespaceSpecifier(node) {
269
- return node.type === AST_NODE_TYPES.ImportNamespaceSpecifier;
270
- }
271
- function isImportSpecifier(node) {
272
- return node.type === AST_NODE_TYPES.ImportSpecifier;
273
- }
274
- function isJSXExpressionContainer(node) {
275
- return node.type === AST_NODE_TYPES.JSXExpressionContainer;
276
- }
277
- function isLiteral(node) {
278
- return node.type === AST_NODE_TYPES.Literal;
279
- }
280
- function isTemplateLiteral(node) {
281
- return node.type === AST_NODE_TYPES.TemplateLiteral;
282
- }
283
- function isMemberExpression(node) {
284
- return node.type === AST_NODE_TYPES.MemberExpression;
285
- }
286
- function isMethodDefinition(node) {
287
- return node.type === AST_NODE_TYPES.MethodDefinition;
288
- }
289
- function isObjectExpression(node) {
290
- return node.type === AST_NODE_TYPES.ObjectExpression;
291
- }
292
- function isObjectPattern(node) {
293
- return node.type === AST_NODE_TYPES.ObjectPattern;
294
- }
295
- function isProgram(node) {
296
- return node.type === AST_NODE_TYPES.Program;
297
- }
298
- function isProperty(node) {
299
- return node.type === AST_NODE_TYPES.Property;
300
- }
301
- function isPropertyDefinition(node) {
302
- return node.type === AST_NODE_TYPES.PropertyDefinition;
303
- }
304
- function isSpreadElement(node) {
305
- return node.type === AST_NODE_TYPES.SpreadElement;
306
- }
307
- function isTSAsExpression(node) {
308
- return node.type === AST_NODE_TYPES.TSAsExpression;
309
- }
310
- function isTSSatisfiesExpression(node) {
311
- return node.type === AST_NODE_TYPES.TSSatisfiesExpression;
312
- }
313
- function isUnaryExpression(node) {
314
- return node.type === AST_NODE_TYPES.UnaryExpression;
315
- }
316
- function isUnionType(node) {
317
- return node.type === AST_NODE_TYPES.TSUnionType;
318
- }
319
- function isVariableDeclarator(node) {
320
- return node.type === AST_NODE_TYPES.VariableDeclarator;
321
- }
322
-
323
- // src/etc/get-type-services.ts
324
- function getTypeServices(context) {
325
- const services = ESLintUtils.getParserServices(context);
326
- const { program, getTypeAtLocation } = services;
327
- const typeChecker = program.getTypeChecker();
328
- const couldBeType2 = (node, name2, qualified) => {
329
- const type = getTypeAtLocation(node);
330
- return couldBeType(
331
- type,
332
- name2,
333
- qualified ? { ...qualified, typeChecker } : void 0
334
- );
335
- };
336
- const couldReturnType = (node, name2, qualified) => {
337
- const type = getTypeAtLocation(node);
338
- for (const signature of tsutils2.getCallSignaturesOfType(type)) {
339
- const returnType = signature.getReturnType();
340
- if (couldBeType(
341
- returnType,
342
- name2,
343
- qualified ? { ...qualified, typeChecker } : void 0
344
- )) {
345
- return true;
346
- }
347
- }
348
- return false;
349
- };
350
- return {
351
- couldBeBehaviorSubject: (node) => couldBeType2(node, "BehaviorSubject"),
352
- couldBeFunction: (node) => {
353
- if (isArrowFunctionExpression(node) || isFunctionDeclaration(node)) {
354
- return true;
355
- }
356
- return couldBeFunction(getTypeAtLocation(node));
357
- },
358
- couldBeMonoTypeOperatorFunction: (node) => couldBeType2(node, "MonoTypeOperatorFunction"),
359
- couldBeObservable: (node) => couldBeType2(node, "Observable"),
360
- couldBeSubject: (node) => couldBeType2(node, "Subject"),
361
- couldBeSubscription: (node) => couldBeType2(node, "Subscription"),
362
- couldBeType: couldBeType2,
363
- couldReturnObservable: (node) => couldReturnType(node, "Observable"),
364
- couldReturnType
365
- };
366
- }
367
-
368
- // src/etc/is-import.ts
369
- import { DefinitionType } from "@typescript-eslint/scope-manager";
370
- import { AST_NODE_TYPES as AST_NODE_TYPES2 } from "@typescript-eslint/utils";
371
- function isImport(scope, name2, source) {
372
- const variable = scope.variables.find((variable2) => variable2.name === name2);
373
- if (variable) {
374
- return variable.defs.some(
375
- (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))
376
- );
377
- }
378
- return scope.upper ? isImport(scope.upper, name2, source) : false;
379
- }
380
-
381
- // src/utils/find-is-last-operator-order-valid.ts
382
- function findIsLastOperatorOrderValid(pipeCallExpression, operatorsRegExp, allow) {
383
- let isOrderValid = true;
384
- let operatorNode;
385
- for (let i = pipeCallExpression.arguments.length - 1; i >= 0; i--) {
386
- const arg = pipeCallExpression.arguments[i];
387
- if (operatorNode) {
388
- break;
389
- }
390
- if (!isCallExpression(arg)) {
391
- isOrderValid = false;
392
- continue;
393
- }
394
- let operatorName;
395
- if (isIdentifier(arg.callee)) {
396
- operatorName = arg.callee.name;
397
- } else if (isMemberExpression(arg.callee) && isIdentifier(arg.callee.property)) {
398
- operatorName = arg.callee.property.name;
399
- } else {
400
- isOrderValid = false;
401
- continue;
402
- }
403
- if (operatorsRegExp.test(operatorName)) {
404
- operatorNode = arg.callee;
405
- break;
406
- }
407
- if (!allow.includes(operatorName)) {
408
- isOrderValid = false;
409
- continue;
410
- }
411
- }
412
- return { isOrderValid, operatorNode };
413
- }
414
-
415
- // src/utils/rule-creator.ts
416
- import { ESLintUtils as ESLintUtils2 } from "@typescript-eslint/utils";
417
- var REPO_URL = "https://github.com/JasonWeinzierl/eslint-plugin-rxjs-x";
418
- var ruleCreator = ESLintUtils2.RuleCreator(
419
- (name2) => `${REPO_URL}/blob/v${version}/docs/rules/${name2}.md`
420
- // Ensure the resulting types are narrowed to exactly what each rule declares.
421
- );
422
-
423
- // src/rules/ban-observables.ts
424
- var defaultOptions = [];
425
- var banObservablesRule = ruleCreator({
426
- defaultOptions,
427
- meta: {
428
- docs: {
429
- description: "Disallow banned observable creators."
430
- },
431
- messages: {
432
- forbidden: "RxJS observable is banned: {{name}}{{explanation}}."
433
- },
434
- schema: [
435
- {
436
- type: "object",
437
- description: stripIndent`
438
- An object containing keys that are names of observable factory functions
439
- and values that are either booleans or strings containing the explanation for the ban.`
440
- }
441
- ],
442
- type: "problem"
443
- },
444
- name: "ban-observables",
445
- create: (context) => {
446
- const bans = [];
447
- const [config] = context.options;
448
- if (!config) {
449
- return {};
450
- }
451
- Object.entries(config).forEach(([key, value]) => {
452
- if (value !== false) {
453
- bans.push({
454
- explanation: typeof value === "string" ? value : "",
455
- regExp: new RegExp(`^${key}$`)
456
- });
457
- }
458
- });
459
- function getFailure(name2) {
460
- for (let b = 0, length = bans.length; b < length; ++b) {
461
- const ban = bans[b];
462
- if (ban.regExp.test(name2)) {
463
- const explanation = ban.explanation ? `: ${ban.explanation}` : "";
464
- return {
465
- messageId: "forbidden",
466
- data: { name: name2, explanation }
467
- };
468
- }
469
- }
470
- return void 0;
471
- }
472
- return {
473
- "ImportDeclaration[source.value='rxjs'] > ImportSpecifier": (node) => {
474
- const identifier = node.imported;
475
- const name2 = identifier.type === AST_NODE_TYPES3.Identifier ? identifier.name : identifier.value;
476
- const failure = getFailure(name2);
477
- if (failure) {
478
- context.report({
479
- ...failure,
480
- node: identifier
481
- });
482
- }
483
- }
484
- };
485
- }
486
- });
487
-
488
- // src/rules/ban-operators.ts
489
- import { stripIndent as stripIndent2 } from "common-tags";
490
- var defaultOptions2 = [];
491
- var banOperatorsRule = ruleCreator({
492
- defaultOptions: defaultOptions2,
493
- meta: {
494
- docs: {
495
- description: "Disallow banned operators.",
496
- requiresTypeChecking: true
497
- },
498
- messages: {
499
- forbidden: "RxJS operator is banned: {{name}}{{explanation}}."
500
- },
501
- schema: [
502
- {
503
- type: "object",
504
- description: stripIndent2`
505
- An object containing keys that are names of operators
506
- and values that are either booleans or strings containing the explanation for the ban.`
507
- }
508
- ],
509
- type: "problem"
510
- },
511
- name: "ban-operators",
512
- create: (context) => {
513
- const { couldBeType: couldBeType2 } = getTypeServices(context);
514
- const bans = [];
515
- const [config] = context.options;
516
- if (!config) {
517
- return {};
518
- }
519
- Object.entries(config).forEach(([key, value]) => {
520
- if (value !== false) {
521
- bans.push({
522
- name: key,
523
- explanation: typeof value === "string" ? value : ""
524
- });
525
- }
526
- });
527
- function checkNode(node) {
528
- for (const ban of bans) {
529
- if (couldBeType2(node, ban.name, { name: /[/\\]rxjs[/\\]/ })) {
530
- const explanation = ban.explanation ? `: ${ban.explanation}` : "";
531
- context.report({
532
- messageId: "forbidden",
533
- data: { name: ban.name, explanation },
534
- node
535
- });
536
- return;
537
- }
538
- }
539
- }
540
- return {
541
- "CallExpression[callee.property.name='pipe'] > CallExpression[callee.name]": (node) => {
542
- checkNode(node.callee);
543
- },
544
- "CallExpression[callee.property.name='pipe'] > CallExpression[callee.type=\"MemberExpression\"]": (node) => {
545
- const callee = node.callee;
546
- checkNode(callee.property);
547
- }
548
- };
549
- }
550
- });
551
-
552
- // src/rules/finnish.ts
553
- import { ESLintUtils as ESLintUtils3 } from "@typescript-eslint/utils";
554
- var defaultOptions3 = [];
555
- var baseShouldBeFinnish = "Finnish notation should be used here.";
556
- var finnishRule = ruleCreator({
557
- defaultOptions: defaultOptions3,
558
- meta: {
559
- docs: {
560
- description: "Enforce Finnish notation.",
561
- requiresTypeChecking: true
562
- },
563
- messages: {
564
- shouldBeFinnish: baseShouldBeFinnish,
565
- shouldBeFinnishProperty: `${baseShouldBeFinnish} Add a type annotation, assertion, or 'satisfies' to silence this rule.`,
566
- shouldNotBeFinnish: "Finnish notation should not be used here."
567
- },
568
- schema: [
569
- {
570
- properties: {
571
- functions: { type: "boolean", description: "Require for functions." },
572
- methods: { type: "boolean", description: "Require for methods." },
573
- names: { type: "object", description: "Enforce for specific names. Keys are a RegExp, values are a boolean." },
574
- parameters: { type: "boolean", description: "Require for parameters." },
575
- properties: { type: "boolean", description: 'Require for properties, except object literal keys (see "objects" option).' },
576
- objects: { type: "boolean", description: "Require for object literal keys." },
577
- strict: { type: "boolean", description: "Disallow Finnish notation for non-Observables." },
578
- types: { type: "object", description: "Enforce for specific types. Keys are a RegExp, values are a boolean." },
579
- variables: { type: "boolean", description: "Require for variables." }
580
- },
581
- type: "object"
582
- }
583
- ],
584
- type: "problem"
585
- },
586
- name: "finnish",
587
- create: (context) => {
588
- const { esTreeNodeToTSNodeMap } = ESLintUtils3.getParserServices(context);
589
- const {
590
- couldBeObservable,
591
- couldBeType: couldBeType2,
592
- couldReturnObservable,
593
- couldReturnType
594
- } = getTypeServices(context);
595
- const [config = {}] = context.options;
596
- const { strict = false } = config;
597
- const validate = {
598
- functions: true,
599
- methods: true,
600
- parameters: true,
601
- properties: true,
602
- objects: true,
603
- variables: true,
604
- ...config
605
- };
606
- const names = [];
607
- if (config.names) {
608
- Object.entries(config.names).forEach(
609
- ([key, validate2]) => {
610
- names.push({ regExp: new RegExp(key), validate: validate2 });
611
- }
612
- );
613
- } else {
614
- names.push({
615
- regExp: /^(canActivate|canActivateChild|canDeactivate|canLoad|intercept|resolve|validate)$/,
616
- validate: false
617
- });
618
- }
619
- const types = [];
620
- if (config.types) {
621
- Object.entries(config.types).forEach(
622
- ([key, validate2]) => {
623
- types.push({ regExp: new RegExp(key), validate: validate2 });
624
- }
625
- );
626
- } else {
627
- types.push({
628
- regExp: /^EventEmitter$/,
629
- validate: false
630
- });
631
- }
632
- function checkNode(nameNode, typeNode, shouldMessage = "shouldBeFinnish") {
633
- const tsNode = esTreeNodeToTSNodeMap.get(nameNode);
634
- const text = tsNode.getText();
635
- const hasFinnish = text.endsWith("$");
636
- if (hasFinnish && !strict) {
637
- return;
638
- }
639
- const shouldBeFinnish = hasFinnish ? () => {
640
- } : () => {
641
- context.report({
642
- loc: getLoc(tsNode),
643
- messageId: shouldMessage
644
- });
645
- };
646
- const shouldNotBeFinnish = hasFinnish ? () => {
647
- context.report({
648
- loc: getLoc(tsNode),
649
- messageId: "shouldNotBeFinnish"
650
- });
651
- } : () => {
652
- };
653
- const nameWithoutDollar = text.endsWith("$") ? text.slice(0, -1) : text;
654
- for (const name2 of names) {
655
- const { regExp, validate: validate2 } = name2;
656
- if (regExp.test(text) || regExp.test(nameWithoutDollar)) {
657
- if (validate2) {
658
- shouldBeFinnish();
659
- } else {
660
- shouldNotBeFinnish();
661
- }
662
- return;
663
- }
664
- }
665
- for (const type of types) {
666
- const { regExp, validate: validate2 } = type;
667
- if (couldBeType2(typeNode != null ? typeNode : nameNode, regExp) || couldReturnType(typeNode != null ? typeNode : nameNode, regExp)) {
668
- if (validate2) {
669
- shouldBeFinnish();
670
- } else {
671
- shouldNotBeFinnish();
672
- }
673
- return;
674
- }
675
- }
676
- if (couldBeObservable(typeNode != null ? typeNode : nameNode) || couldReturnObservable(typeNode != null ? typeNode : nameNode)) {
677
- shouldBeFinnish();
678
- } else {
679
- shouldNotBeFinnish();
680
- }
681
- }
682
- return {
683
- "ArrayPattern > Identifier": (node) => {
684
- const found = findParent(
685
- node,
686
- "ArrowFunctionExpression",
687
- "FunctionDeclaration",
688
- "FunctionExpression",
689
- "VariableDeclarator"
690
- );
691
- if (!found) {
692
- return;
693
- }
694
- if (!validate.variables && isVariableDeclarator(found)) {
695
- return;
696
- }
697
- if (!validate.parameters) {
698
- return;
699
- }
700
- checkNode(node);
701
- },
702
- "ArrowFunctionExpression > Identifier": (node) => {
703
- if (validate.parameters) {
704
- const parent = node.parent;
705
- if (node !== parent.body) {
706
- checkNode(node);
707
- }
708
- }
709
- },
710
- "PropertyDefinition[computed=false]": (node) => {
711
- if (validate.properties) {
712
- if (node.override) {
713
- return;
714
- }
715
- checkNode(node.key);
716
- }
717
- },
718
- "FunctionDeclaration > Identifier": (node) => {
719
- const parent = node.parent;
720
- if (node === parent.id) {
721
- if (validate.functions) {
722
- checkNode(node, parent);
723
- }
724
- } else {
725
- if (validate.parameters) {
726
- checkNode(node);
727
- }
728
- }
729
- },
730
- "FunctionExpression > Identifier": (node) => {
731
- const parent = node.parent;
732
- if (node === parent.id) {
733
- if (validate.functions) {
734
- checkNode(node, parent);
735
- }
736
- } else {
737
- if (validate.parameters) {
738
- checkNode(node);
739
- }
740
- }
741
- },
742
- "MethodDefinition[kind='get'][computed=false]": (node) => {
743
- if (validate.properties) {
744
- if (node.override) {
745
- return;
746
- }
747
- checkNode(node.key, node);
748
- }
749
- },
750
- "MethodDefinition[kind='method'][computed=false]": (node) => {
751
- if (validate.methods) {
752
- if (node.override) {
753
- return;
754
- }
755
- checkNode(node.key, node);
756
- }
757
- },
758
- "MethodDefinition[kind='set'][computed=false]": (node) => {
759
- if (validate.properties) {
760
- if (node.override) {
761
- return;
762
- }
763
- checkNode(node.key, node);
764
- }
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
- },
782
- "ObjectExpression > Property[computed=false] > Identifier": (node) => {
783
- if (!validate.objects) {
784
- return;
785
- }
786
- const found = findParent(
787
- node,
788
- "CallExpression",
789
- "VariableDeclarator",
790
- "TSSatisfiesExpression",
791
- "TSAsExpression"
792
- );
793
- if (found) {
794
- if (isCallExpression(found)) {
795
- return;
796
- } else if (isVariableDeclarator(found) && !!found.id.typeAnnotation) {
797
- return;
798
- } else if (isTSAsExpression(found) || isTSSatisfiesExpression(found)) {
799
- return;
800
- }
801
- }
802
- const parent = node.parent;
803
- if (node === parent.key) {
804
- checkNode(node, void 0, "shouldBeFinnishProperty");
805
- }
806
- },
807
- "ObjectPattern > Property > Identifier": (node) => {
808
- const found = findParent(
809
- node,
810
- "ArrowFunctionExpression",
811
- "FunctionDeclaration",
812
- "FunctionExpression",
813
- "VariableDeclarator"
814
- );
815
- if (!found) {
816
- return;
817
- }
818
- if (!validate.variables && isVariableDeclarator(found)) {
819
- return;
820
- }
821
- if (!validate.parameters) {
822
- return;
823
- }
824
- const parent = node.parent;
825
- if (node === parent.value) {
826
- checkNode(node);
827
- }
828
- },
829
- "TSCallSignatureDeclaration > Identifier": (node) => {
830
- if (validate.parameters) {
831
- checkNode(node);
832
- }
833
- },
834
- "TSConstructSignatureDeclaration > Identifier": (node) => {
835
- if (validate.parameters) {
836
- checkNode(node);
837
- }
838
- },
839
- "TSMethodSignature[computed=false]": (node) => {
840
- if (validate.methods) {
841
- checkNode(node.key, node);
842
- }
843
- if (validate.parameters) {
844
- node.params.forEach((param) => {
845
- checkNode(param);
846
- });
847
- }
848
- },
849
- "TSParameterProperty > Identifier": (node) => {
850
- if (validate.parameters || validate.properties) {
851
- checkNode(node);
852
- }
853
- },
854
- "TSPropertySignature[computed=false]": (node) => {
855
- if (validate.properties) {
856
- checkNode(node.key);
857
- }
858
- },
859
- "VariableDeclarator > Identifier": (node) => {
860
- const parent = node.parent;
861
- if (validate.variables && node === parent.id) {
862
- checkNode(node);
863
- }
864
- }
865
- };
866
- }
867
- });
868
-
869
- // src/rules/just.ts
870
- var justRule = ruleCreator({
871
- defaultOptions: [],
872
- meta: {
873
- docs: {
874
- description: "Require the use of `just` instead of `of`."
875
- },
876
- fixable: "code",
877
- messages: {
878
- forbidden: "Use just alias."
879
- },
880
- schema: [],
881
- type: "problem"
882
- },
883
- name: "just",
884
- create: (context) => {
885
- return {
886
- "ImportDeclaration[source.value='rxjs'] > ImportSpecifier[imported.name='of']": (node) => {
887
- if (node.local.range[0] !== node.imported.range[0] && node.local.range[1] !== node.imported.range[1]) {
888
- return;
889
- }
890
- context.report({
891
- messageId: "forbidden",
892
- node,
893
- fix: (fixer) => fixer.replaceTextRange(node.range, "of as just")
894
- });
895
- const [ofImport] = context.sourceCode.getDeclaredVariables(node);
896
- ofImport.references.forEach((ref) => {
897
- context.report({
898
- messageId: "forbidden",
899
- node: ref.identifier,
900
- fix: (fixer) => fixer.replaceTextRange(ref.identifier.range, "just")
901
- });
902
- });
903
- }
904
- };
905
- }
906
- });
907
-
908
- // src/rules/macro.ts
909
- var macroRule = ruleCreator({
910
- defaultOptions: [],
911
- meta: {
912
- deprecated: true,
913
- docs: {
914
- description: "Require the use of the RxJS Tools Babel macro."
915
- },
916
- fixable: "code",
917
- messages: {
918
- macro: "Use the RxJS Tools Babel macro."
919
- },
920
- schema: [],
921
- type: "problem"
922
- },
923
- name: "macro",
924
- create: (context) => {
925
- let hasFailure = false;
926
- let hasMacroImport = false;
927
- let program = void 0;
928
- function fix(fixer) {
929
- return fixer.insertTextBefore(
930
- /* eslint-disable-next-line @typescript-eslint/no-non-null-assertion */
931
- program,
932
- `import "babel-plugin-rxjs-tools/macro";
933
- `
934
- );
935
- }
936
- return {
937
- "CallExpression[callee.property.name=/^(pipe|subscribe)$/]": (node) => {
938
- if (hasFailure || hasMacroImport) {
939
- return;
940
- }
941
- hasFailure = true;
942
- context.report({
943
- fix,
944
- messageId: "macro",
945
- node: node.callee
946
- });
947
- },
948
- "ImportDeclaration[source.value='babel-plugin-rxjs-tools/macro']": (_node) => {
949
- hasMacroImport = true;
950
- },
951
- [String.raw`ImportDeclaration[source.value=/^rxjs(\u002f|$)/]`]: (node) => {
952
- if (hasFailure || hasMacroImport) {
953
- return;
954
- }
955
- hasFailure = true;
956
- context.report({
957
- fix,
958
- messageId: "macro",
959
- node
960
- });
961
- },
962
- "Program": (node) => {
963
- program = node;
964
- }
965
- };
966
- }
967
- });
968
-
969
- // src/rules/no-async-subscribe.ts
970
- var noAsyncSubscribeRule = ruleCreator({
971
- defaultOptions: [],
972
- meta: {
973
- docs: {
974
- description: "Disallow passing `async` functions to `subscribe`.",
975
- recommended: "recommended",
976
- requiresTypeChecking: true
977
- },
978
- messages: {
979
- forbidden: "Passing async functions to subscribe is forbidden. Use operators like `concatMap` or `switchMap` to avoid race conditions."
980
- },
981
- schema: [],
982
- type: "problem"
983
- },
984
- name: "no-async-subscribe",
985
- create: (context) => {
986
- const { couldBeObservable } = getTypeServices(context);
987
- function report(node) {
988
- const { loc } = node;
989
- const asyncLoc = {
990
- ...loc,
991
- end: {
992
- ...loc.start,
993
- column: loc.start.column + 5
994
- }
995
- };
996
- context.report({
997
- messageId: "forbidden",
998
- loc: asyncLoc
999
- });
1000
- }
1001
- function checkSingleNext(funcNode) {
1002
- const parentNode = funcNode.parent;
1003
- const callee = parentNode.callee;
1004
- if (couldBeObservable(callee.object)) {
1005
- report(funcNode);
1006
- }
1007
- }
1008
- function checkObserverObjectProp(propNode) {
1009
- const parentNode = propNode.parent.parent;
1010
- const callee = parentNode.callee;
1011
- if (couldBeObservable(callee.object) && (isArrowFunctionExpression(propNode.value) || isFunctionExpression(propNode.value))) {
1012
- report(propNode.value);
1013
- }
1014
- }
1015
- return {
1016
- "CallExpression[callee.property.name='subscribe'] > FunctionExpression[async=true]": checkSingleNext,
1017
- "CallExpression[callee.property.name='subscribe'] > ArrowFunctionExpression[async=true]": checkSingleNext,
1018
- "CallExpression[callee.property.name='subscribe'] > ObjectExpression > Property[key.name='next'][value.type=\"ArrowFunctionExpression\"][value.async=true]": checkObserverObjectProp,
1019
- "CallExpression[callee.property.name='subscribe'] > ObjectExpression > Property[key.name='next'][value.type=\"FunctionExpression\"][value.async=true]": checkObserverObjectProp
1020
- };
1021
- }
1022
- });
1023
-
1024
- // src/rules/no-compat.ts
1025
- var noCompatRule = ruleCreator({
1026
- defaultOptions: [],
1027
- meta: {
1028
- deprecated: true,
1029
- docs: {
1030
- description: "Disallow the `rxjs-compat` package."
1031
- },
1032
- messages: {
1033
- forbidden: "'rxjs-compat'-dependent import locations are forbidden."
1034
- },
1035
- schema: [],
1036
- type: "problem"
1037
- },
1038
- name: "no-compat",
1039
- create: (context) => {
1040
- return {
1041
- [String.raw`ImportDeclaration Literal[value=/^rxjs\u002f/]:not(Literal[value=/^rxjs\u002f(ajax|fetch|operators|testing|webSocket)/])`]: (node) => {
1042
- context.report({
1043
- messageId: "forbidden",
1044
- node
1045
- });
1046
- }
1047
- };
1048
- }
1049
- });
1050
-
1051
- // src/rules/no-connectable.ts
1052
- var noConnectableRule = ruleCreator({
1053
- defaultOptions: [],
1054
- meta: {
1055
- docs: {
1056
- description: "Disallow operators that return connectable observables.",
1057
- requiresTypeChecking: true
1058
- },
1059
- messages: {
1060
- forbidden: "Connectable observables are forbidden."
1061
- },
1062
- schema: [],
1063
- type: "problem"
1064
- },
1065
- name: "no-connectable",
1066
- create: (context) => {
1067
- const { couldBeFunction: couldBeFunction2 } = getTypeServices(context);
1068
- return {
1069
- "CallExpression[callee.name='multicast']": (node) => {
1070
- if (node.arguments.length === 1) {
1071
- context.report({
1072
- messageId: "forbidden",
1073
- node: node.callee
1074
- });
1075
- }
1076
- },
1077
- "CallExpression[callee.name=/^(publish|publishBehavior|publishLast|publishReplay)$/]": (node) => {
1078
- if (!node.arguments.some((arg) => couldBeFunction2(arg))) {
1079
- context.report({
1080
- messageId: "forbidden",
1081
- node: node.callee
1082
- });
1083
- }
1084
- }
1085
- };
1086
- }
1087
- });
1088
-
1089
- // src/rules/no-create.ts
1090
- var noCreateRule = ruleCreator({
1091
- defaultOptions: [],
1092
- meta: {
1093
- docs: {
1094
- description: "Disallow the static `Observable.create` and `Subject.create` functions.",
1095
- recommended: "recommended",
1096
- requiresTypeChecking: true
1097
- },
1098
- messages: {
1099
- forbidden: "Observable.create is forbidden; use new Observable.",
1100
- forbiddenSubject: "Subject.create is forbidden."
1101
- },
1102
- schema: [],
1103
- type: "problem"
1104
- },
1105
- name: "no-create",
1106
- create: (context) => {
1107
- const { couldBeObservable, couldBeType: couldBeType2 } = getTypeServices(context);
1108
- return {
1109
- "CallExpression > MemberExpression[object.name='Observable'] > Identifier[name='create']": (node) => {
1110
- const memberExpression = node.parent;
1111
- if (couldBeObservable(memberExpression.object)) {
1112
- context.report({
1113
- messageId: "forbidden",
1114
- node
1115
- });
1116
- }
1117
- },
1118
- "CallExpression > MemberExpression[object.name=/^(Subject|BehaviorSubject|AsyncSubject|ReplaySubject)$/] > Identifier[name='create']": (node) => {
1119
- const memberExpression = node.parent;
1120
- if (couldBeType2(memberExpression.object, /^(Subject|BehaviorSubject|AsyncSubject|ReplaySubject)$/)) {
1121
- context.report({
1122
- messageId: "forbiddenSubject",
1123
- node
1124
- });
1125
- }
1126
- }
1127
- };
1128
- }
1129
- });
1130
-
1131
- // src/rules/no-cyclic-action.ts
1132
- import { ESLintUtils as ESLintUtils4 } from "@typescript-eslint/utils";
1133
- import { stripIndent as stripIndent3 } from "common-tags";
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
1178
- function isTypeReference2(type) {
1179
- return Boolean(type.target);
1180
- }
1181
- var defaultOptions4 = [];
1182
- var noCyclicActionRule = ruleCreator({
1183
- defaultOptions: defaultOptions4,
1184
- meta: {
1185
- docs: {
1186
- description: "Disallow cyclic actions in effects and epics.",
1187
- requiresTypeChecking: true
1188
- },
1189
- messages: {
1190
- forbidden: "Effects and epics that re-emit filtered actions are forbidden."
1191
- },
1192
- schema: [
1193
- {
1194
- properties: {
1195
- observable: { type: "string", description: "A RegExp that matches an effect or epic's actions observable.", default: defaultObservable }
1196
- },
1197
- type: "object",
1198
- description: stripIndent3`
1199
- An optional object with an optional \`observable\` property.
1200
- 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.`
1201
- }
1202
- ],
1203
- type: "problem"
1204
- },
1205
- name: "no-cyclic-action",
1206
- create: (context) => {
1207
- const [config = {}] = context.options;
1208
- const { observable = defaultObservable } = config;
1209
- const observableRegExp = new RegExp(observable);
1210
- const { getTypeAtLocation, program } = ESLintUtils4.getParserServices(context);
1211
- const typeChecker = program.getTypeChecker();
1212
- function checkNode(pipeCallExpression) {
1213
- const operatorCallExpression = pipeCallExpression.arguments.find(
1214
- (arg) => isCallExpression(arg) && isIdentifier(arg.callee) && arg.callee.name === "ofType"
1215
- );
1216
- if (!operatorCallExpression) {
1217
- return;
1218
- }
1219
- const operatorType = getTypeAtLocation(operatorCallExpression);
1220
- const [signature] = typeChecker.getSignaturesOfType(
1221
- operatorType,
1222
- ts4.SignatureKind.Call
1223
- );
1224
- if (!signature) {
1225
- return;
1226
- }
1227
- const operatorReturnType = typeChecker.getReturnTypeOfSignature(signature);
1228
- if (!isTypeReference2(operatorReturnType)) {
1229
- return;
1230
- }
1231
- const [operatorElementType] = typeChecker.getTypeArguments(operatorReturnType);
1232
- if (!operatorElementType) {
1233
- return;
1234
- }
1235
- const pipeType = getTypeAtLocation(pipeCallExpression);
1236
- if (!isTypeReference2(pipeType)) {
1237
- return;
1238
- }
1239
- const [pipeElementType] = typeChecker.getTypeArguments(pipeType);
1240
- if (!pipeElementType) {
1241
- return;
1242
- }
1243
- const operatorActionTypes = getActionTypes(operatorElementType);
1244
- const pipeActionTypes = getActionTypes(pipeElementType);
1245
- for (const actionType of operatorActionTypes) {
1246
- if (pipeActionTypes.includes(actionType)) {
1247
- context.report({
1248
- messageId: "forbidden",
1249
- node: pipeCallExpression.callee
1250
- });
1251
- return;
1252
- }
1253
- }
1254
- }
1255
- function getActionTypes(type) {
1256
- if (type.isUnion()) {
1257
- const memberActionTypes = [];
1258
- for (const memberType of type.types) {
1259
- memberActionTypes.push(...getActionTypes(memberType));
1260
- }
1261
- return memberActionTypes;
1262
- }
1263
- const symbol = typeChecker.getPropertyOfType(type, "type");
1264
- if (!(symbol == null ? void 0 : symbol.valueDeclaration)) {
1265
- return [];
1266
- }
1267
- const actionType = typeChecker.getTypeOfSymbolAtLocation(
1268
- symbol,
1269
- symbol.valueDeclaration
1270
- );
1271
- return [typeChecker.typeToString(actionType)];
1272
- }
1273
- return {
1274
- [`CallExpression[callee.property.name='pipe'][callee.object.name=${observableRegExp}]`]: checkNode,
1275
- [`CallExpression[callee.property.name='pipe'][callee.object.property.name=${observableRegExp}]`]: checkNode
1276
- };
1277
- }
1278
- });
1279
-
1280
- // src/rules/no-explicit-generics.ts
1281
- import { ESLintUtils as ESLintUtils5 } from "@typescript-eslint/utils";
1282
- import * as tsutils3 from "ts-api-utils";
1283
- var noExplicitGenericsRule = ruleCreator({
1284
- defaultOptions: [],
1285
- meta: {
1286
- docs: {
1287
- description: "Disallow unnecessary explicit generic type arguments.",
1288
- requiresTypeChecking: true
1289
- },
1290
- messages: {
1291
- forbidden: "Explicit generic type arguments are forbidden."
1292
- },
1293
- schema: [],
1294
- type: "problem"
1295
- },
1296
- name: "no-explicit-generics",
1297
- create: (context) => {
1298
- function report(node) {
1299
- context.report({
1300
- messageId: "forbidden",
1301
- node
1302
- });
1303
- }
1304
- function isUnion(node) {
1305
- if (!node) {
1306
- return false;
1307
- }
1308
- if (isUnionType(node)) {
1309
- return true;
1310
- }
1311
- const { getTypeAtLocation } = ESLintUtils5.getParserServices(context);
1312
- const type = getTypeAtLocation(node);
1313
- return tsutils3.isUnionOrIntersectionType(type);
1314
- }
1315
- function checkBehaviorSubjects(node) {
1316
- var _a;
1317
- const parent = node.parent;
1318
- const {
1319
- arguments: [value]
1320
- } = parent;
1321
- const typeArgs = (_a = parent.typeArguments) == null ? void 0 : _a.params[0];
1322
- if (isArrayExpression(value) || isObjectExpression(value) || isUnion(typeArgs)) {
1323
- return;
1324
- }
1325
- report(node);
1326
- }
1327
- function checkNotifications(node) {
1328
- var _a;
1329
- const parent = node.parent;
1330
- const {
1331
- arguments: [, value]
1332
- } = parent;
1333
- const typeArgs = (_a = parent.typeArguments) == null ? void 0 : _a.params[0];
1334
- if (isArrayExpression(value) || isObjectExpression(value) || isUnion(typeArgs)) {
1335
- return;
1336
- }
1337
- report(node);
1338
- }
1339
- return {
1340
- "CallExpression[callee.property.name='pipe'] > CallExpression[typeArguments.params.length > 0] > Identifier": report,
1341
- "NewExpression[typeArguments.params.length > 0] > Identifier[name='BehaviorSubject']": checkBehaviorSubjects,
1342
- "CallExpression[typeArguments.params.length > 0] > Identifier[name=/^(from|of)$/]": report,
1343
- "NewExpression[typeArguments.params.length > 0][arguments.0.value='N'] > Identifier[name='Notification']": checkNotifications
1344
- };
1345
- }
1346
- });
1347
-
1348
- // src/rules/no-exposed-subjects.ts
1349
- var defaultAllowedTypesRegExp = /^EventEmitter$/;
1350
- var defaultOptions5 = [];
1351
- var noExposedSubjectsRule = ruleCreator({
1352
- defaultOptions: defaultOptions5,
1353
- meta: {
1354
- docs: {
1355
- description: "Disallow public and protected subjects.",
1356
- recommended: "strict",
1357
- requiresTypeChecking: true
1358
- },
1359
- messages: {
1360
- forbidden: "Subject '{{subject}}' must be private.",
1361
- forbiddenAllowProtected: "Subject '{{subject}}' must be private or protected."
1362
- },
1363
- schema: [
1364
- {
1365
- properties: {
1366
- allowProtected: { type: "boolean", description: "Allow protected subjects.", default: false }
1367
- },
1368
- type: "object"
1369
- }
1370
- ],
1371
- type: "problem"
1372
- },
1373
- name: "no-exposed-subjects",
1374
- create: (context) => {
1375
- const [config = {}] = context.options;
1376
- const { allowProtected = false } = config;
1377
- const { couldBeSubject, couldBeType: couldBeType2 } = getTypeServices(context);
1378
- const messageId = allowProtected ? "forbiddenAllowProtected" : "forbidden";
1379
- const accessibilityRexExp = allowProtected ? /^(private|protected)$/ : /^private$/;
1380
- function isSubject(node) {
1381
- return couldBeSubject(node) && !couldBeType2(node, defaultAllowedTypesRegExp);
1382
- }
1383
- return {
1384
- [`PropertyDefinition[accessibility!=${accessibilityRexExp}]`]: (node) => {
1385
- if (isSubject(node)) {
1386
- const { key } = node;
1387
- if (isIdentifier(key)) {
1388
- context.report({
1389
- messageId,
1390
- node: key,
1391
- data: {
1392
- subject: key.name
1393
- }
1394
- });
1395
- }
1396
- }
1397
- },
1398
- [`MethodDefinition[kind='constructor'] > FunctionExpression > TSParameterProperty[accessibility!=${accessibilityRexExp}] > Identifier`]: (node) => {
1399
- if (isSubject(node)) {
1400
- const { loc } = node;
1401
- context.report({
1402
- messageId,
1403
- loc: {
1404
- ...loc,
1405
- end: {
1406
- ...loc.start,
1407
- column: loc.start.column + node.name.length
1408
- }
1409
- },
1410
- data: {
1411
- subject: node.name
1412
- }
1413
- });
1414
- }
1415
- },
1416
- [`MethodDefinition[accessibility!=${accessibilityRexExp}][kind=/^(get|set)$/]`]: (node) => {
1417
- if (isSubject(node)) {
1418
- const key = node.key;
1419
- context.report({
1420
- messageId,
1421
- node: key,
1422
- data: {
1423
- subject: key.name
1424
- }
1425
- });
1426
- }
1427
- },
1428
- [`MethodDefinition[accessibility!=${accessibilityRexExp}][kind='method']`]: (node) => {
1429
- const functionExpression = node.value;
1430
- const returnType = functionExpression.returnType;
1431
- if (!returnType) {
1432
- return;
1433
- }
1434
- const typeAnnotation = returnType.typeAnnotation;
1435
- if (!typeAnnotation) {
1436
- return;
1437
- }
1438
- if (isSubject(typeAnnotation)) {
1439
- const key = node.key;
1440
- context.report({
1441
- messageId,
1442
- node: key,
1443
- data: {
1444
- subject: key.name
1445
- }
1446
- });
1447
- }
1448
- }
1449
- };
1450
- }
1451
- });
1452
-
1453
- // src/rules/no-finnish.ts
1454
- import { ESLintUtils as ESLintUtils6 } from "@typescript-eslint/utils";
1455
- var noFinnishRule = ruleCreator({
1456
- defaultOptions: [],
1457
- meta: {
1458
- docs: {
1459
- description: "Disallow Finnish notation.",
1460
- requiresTypeChecking: true
1461
- },
1462
- messages: {
1463
- forbidden: "Finnish notation is forbidden."
1464
- },
1465
- schema: [],
1466
- type: "problem"
1467
- },
1468
- name: "no-finnish",
1469
- create: (context) => {
1470
- const { esTreeNodeToTSNodeMap } = ESLintUtils6.getParserServices(context);
1471
- const { couldBeObservable, couldReturnObservable } = getTypeServices(context);
1472
- function checkNode(nameNode, typeNode) {
1473
- if (couldBeObservable(typeNode != null ? typeNode : nameNode) || couldReturnObservable(typeNode != null ? typeNode : nameNode)) {
1474
- const tsNode = esTreeNodeToTSNodeMap.get(nameNode);
1475
- if (/[$]+$/.test(tsNode.getText())) {
1476
- context.report({
1477
- loc: getLoc(tsNode),
1478
- messageId: "forbidden"
1479
- });
1480
- }
1481
- }
1482
- }
1483
- return {
1484
- "ArrayPattern > Identifier[name=/[$]+$/]": (node) => {
1485
- checkNode(node);
1486
- },
1487
- "ArrowFunctionExpression > Identifier[name=/[$]+$/]": (node) => {
1488
- const parent = node.parent;
1489
- if (node !== parent.body) {
1490
- checkNode(node);
1491
- }
1492
- },
1493
- "PropertyDefinition[key.name=/[$]+$/] > Identifier": (node) => {
1494
- checkNode(node, node.parent);
1495
- },
1496
- "FunctionDeclaration > Identifier[name=/[$]+$/]": (node) => {
1497
- const parent = node.parent;
1498
- if (node === parent.id) {
1499
- checkNode(node, parent);
1500
- } else {
1501
- checkNode(node);
1502
- }
1503
- },
1504
- "FunctionExpression > Identifier[name=/[$]+$/]": (node) => {
1505
- const parent = node.parent;
1506
- if (node === parent.id) {
1507
- checkNode(node, parent);
1508
- } else {
1509
- checkNode(node);
1510
- }
1511
- },
1512
- "MethodDefinition[key.name=/[$]+$/]": (node) => {
1513
- checkNode(node.key, node);
1514
- },
1515
- "ObjectExpression > Property[computed=false][key.name=/[$]+$/]": (node) => {
1516
- checkNode(node.key);
1517
- },
1518
- "ObjectPattern > Property[value.name=/[$]+$/]": (node) => {
1519
- checkNode(node.value);
1520
- },
1521
- "TSCallSignatureDeclaration > Identifier[name=/[$]+$/]": (node) => {
1522
- checkNode(node);
1523
- },
1524
- "TSConstructSignatureDeclaration > Identifier[name=/[$]+$/]": (node) => {
1525
- checkNode(node);
1526
- },
1527
- "TSParameterProperty > Identifier[name=/[$]+$/]": (node) => {
1528
- checkNode(node);
1529
- },
1530
- "TSPropertySignature > Identifier[name=/[$]+$/]": (node) => {
1531
- checkNode(node, node.parent);
1532
- },
1533
- "TSMethodSignature > Identifier[name=/[$]+$/]": (node) => {
1534
- const parent = node.parent;
1535
- if (node === parent.key) {
1536
- checkNode(node, parent);
1537
- } else {
1538
- checkNode(node);
1539
- }
1540
- },
1541
- "VariableDeclarator[id.name=/[$]+$/]": (node) => {
1542
- var _a;
1543
- checkNode(node.id, (_a = node.init) != null ? _a : node);
1544
- }
1545
- };
1546
- }
1547
- });
1548
-
1549
- // src/rules/no-floating-observables.ts
1550
- var defaultOptions6 = [];
1551
- var messageBase = "Observables must be subscribed to, returned, converted to a promise and awaited, or be explicitly marked as ignored with the `void` operator.";
1552
- var messageBaseNoVoid = "Observables must be subscribed to, returned, or converted to a promise and awaited.";
1553
- var noFloatingObservablesRule = ruleCreator({
1554
- defaultOptions: defaultOptions6,
1555
- meta: {
1556
- docs: {
1557
- description: "Require Observables to be handled appropriately.",
1558
- recommended: "strict",
1559
- requiresTypeChecking: true
1560
- },
1561
- messages: {
1562
- forbidden: messageBase,
1563
- forbiddenNoVoid: messageBaseNoVoid
1564
- },
1565
- schema: [
1566
- {
1567
- properties: {
1568
- ignoreVoid: { type: "boolean", default: true, description: "Whether to ignore `void` expressions." }
1569
- },
1570
- type: "object"
1571
- }
1572
- ],
1573
- type: "problem"
1574
- },
1575
- name: "no-floating-observables",
1576
- create: (context) => {
1577
- const { couldBeObservable } = getTypeServices(context);
1578
- const [config = {}] = context.options;
1579
- const { ignoreVoid = true } = config;
1580
- function checkNode(node) {
1581
- if (couldBeObservable(node)) {
1582
- context.report({
1583
- messageId: ignoreVoid ? "forbidden" : "forbiddenNoVoid",
1584
- node
1585
- });
1586
- }
1587
- }
1588
- function checkVoid(node) {
1589
- if (ignoreVoid) return;
1590
- if (node.operator !== "void") return;
1591
- let expression = node.argument;
1592
- if (isChainExpression(expression)) {
1593
- expression = expression.expression;
1594
- }
1595
- if (!isCallExpression(expression)) return;
1596
- checkNode(expression);
1597
- }
1598
- return {
1599
- "ExpressionStatement > CallExpression": (node) => {
1600
- checkNode(node);
1601
- },
1602
- "ExpressionStatement > UnaryExpression": (node) => {
1603
- checkVoid(node);
1604
- },
1605
- "ExpressionStatement > ChainExpression": (node) => {
1606
- if (!isCallExpression(node.expression)) return;
1607
- checkNode(node.expression);
1608
- },
1609
- "ExpressionStatement > SequenceExpression": (node) => {
1610
- node.expressions.forEach((expression) => {
1611
- if (isCallExpression(expression)) {
1612
- checkNode(expression);
1613
- }
1614
- });
1615
- },
1616
- "ExpressionStatement > ArrayExpression": (node) => {
1617
- node.elements.forEach((expression) => {
1618
- if (!expression) return;
1619
- if (isCallExpression(expression)) {
1620
- checkNode(expression);
1621
- } else if (isUnaryExpression(expression)) {
1622
- checkVoid(expression);
1623
- }
1624
- });
1625
- }
1626
- };
1627
- }
1628
- });
1629
-
1630
- // src/rules/no-ignored-default-value.ts
1631
- import { ESLintUtils as ESLintUtils7 } from "@typescript-eslint/utils";
1632
- var noIgnoredDefaultValueRule = ruleCreator({
1633
- defaultOptions: [],
1634
- meta: {
1635
- docs: {
1636
- description: "Disallow using `firstValueFrom`, `lastValueFrom`, `first`, and `last` without specifying a default value.",
1637
- recommended: "strict",
1638
- requiresTypeChecking: true
1639
- },
1640
- messages: {
1641
- forbidden: "Not specifying a default value is forbidden."
1642
- },
1643
- schema: [],
1644
- type: "problem"
1645
- },
1646
- name: "no-ignored-default-value",
1647
- create: (context) => {
1648
- const { getTypeAtLocation } = ESLintUtils7.getParserServices(context);
1649
- const { couldBeObservable, couldBeType: couldBeType2 } = getTypeServices(context);
1650
- function checkConfigObj(configArg) {
1651
- if (!configArg.properties.some((p) => isProperty(p) && isIdentifier(p.key) && p.key.name === "defaultValue")) {
1652
- context.report({
1653
- messageId: "forbidden",
1654
- node: configArg
1655
- });
1656
- }
1657
- }
1658
- function checkConfigType(configArg) {
1659
- const configArgType = getTypeAtLocation(configArg);
1660
- if (!(configArgType == null ? void 0 : configArgType.getProperties().some((p) => p.name === "defaultValue"))) {
1661
- context.report({
1662
- messageId: "forbidden",
1663
- node: configArg
1664
- });
1665
- }
1666
- }
1667
- function checkArg(arg) {
1668
- if (isIdentifier(arg)) {
1669
- checkConfigType(arg);
1670
- return;
1671
- } else if (isMemberExpression(arg) && isIdentifier(arg.property)) {
1672
- checkConfigType(arg.property);
1673
- return;
1674
- }
1675
- if (!isObjectExpression(arg)) {
1676
- return;
1677
- }
1678
- checkConfigObj(arg);
1679
- }
1680
- function checkFunctionArgs(node, args) {
1681
- if (!couldBeType2(node, "firstValueFrom", { name: /[/\\]rxjs[/\\]/ }) && !couldBeType2(node, "lastValueFrom", { name: /[/\\]rxjs[/\\]/ })) {
1682
- return;
1683
- }
1684
- if (!args || args.length <= 0) {
1685
- return;
1686
- }
1687
- const [observableArg, configArg] = args;
1688
- if (!couldBeObservable(observableArg)) {
1689
- return;
1690
- }
1691
- if (!configArg) {
1692
- context.report({
1693
- messageId: "forbidden",
1694
- node
1695
- });
1696
- return;
1697
- }
1698
- checkArg(configArg);
1699
- }
1700
- function checkOperatorArgs(node, args) {
1701
- if (!couldBeType2(node, "first", { name: /[/\\]rxjs[/\\]/ }) && !couldBeType2(node, "last", { name: /[/\\]rxjs[/\\]/ })) {
1702
- return;
1703
- }
1704
- if (!args || args.length <= 0) {
1705
- context.report({
1706
- messageId: "forbidden",
1707
- node
1708
- });
1709
- return;
1710
- }
1711
- const [arg] = args;
1712
- checkArg(arg);
1713
- }
1714
- return {
1715
- "CallExpression[callee.name=/^(firstValueFrom|lastValueFrom)$/]": (node) => {
1716
- checkFunctionArgs(node.callee, node.arguments);
1717
- },
1718
- "CallExpression[callee.property.name=/^(firstValueFrom|lastValueFrom)$/]": (node) => {
1719
- const memberExpression = node.callee;
1720
- checkFunctionArgs(memberExpression.property, node.arguments);
1721
- },
1722
- "CallExpression[callee.property.name='pipe'] > CallExpression[callee.name=/^(first|last)$/]": (node) => {
1723
- checkOperatorArgs(node.callee, node.arguments);
1724
- },
1725
- "CallExpression[callee.property.name='pipe'] > CallExpression[callee.property.name=/^(first|last)$/]": (node) => {
1726
- const memberExpression = node.callee;
1727
- checkOperatorArgs(memberExpression.property, node.arguments);
1728
- }
1729
- };
1730
- }
1731
- });
1732
-
1733
- // src/rules/no-ignored-error.ts
1734
- import { ESLintUtils as ESLintUtils8 } from "@typescript-eslint/utils";
1735
- var noIgnoredErrorRule = ruleCreator({
1736
- defaultOptions: [],
1737
- meta: {
1738
- docs: {
1739
- description: "Disallow calling `subscribe` without specifying an error handler.",
1740
- recommended: "strict",
1741
- requiresTypeChecking: true
1742
- },
1743
- messages: {
1744
- forbidden: "Calling subscribe without an error handler is forbidden."
1745
- },
1746
- schema: [],
1747
- type: "problem"
1748
- },
1749
- name: "no-ignored-error",
1750
- create: (context) => {
1751
- const { getTypeAtLocation } = ESLintUtils8.getParserServices(context);
1752
- const { couldBeObservable, couldBeFunction: couldBeFunction2 } = getTypeServices(context);
1753
- function isMissingErrorCallback(callExpression) {
1754
- if (callExpression.arguments.length >= 2) {
1755
- return false;
1756
- }
1757
- return couldBeFunction2(callExpression.arguments[0]);
1758
- }
1759
- function isObjMissingError(arg) {
1760
- return !arg.properties.some(
1761
- (property) => isProperty(property) && isIdentifier(property.key) && property.key.name === "error"
1762
- );
1763
- }
1764
- function isTypeMissingError(arg) {
1765
- const argType = getTypeAtLocation(arg);
1766
- return !(argType == null ? void 0 : argType.getProperties().some((p) => p.name === "error"));
1767
- }
1768
- function isMissingErrorProperty(callExpression) {
1769
- if (callExpression.arguments.length !== 1) {
1770
- return false;
1771
- }
1772
- const [arg] = callExpression.arguments;
1773
- if (isObjectExpression(arg)) {
1774
- return isObjMissingError(arg);
1775
- }
1776
- if (isIdentifier(arg)) {
1777
- return isTypeMissingError(arg);
1778
- }
1779
- if (isMemberExpression(arg) && isIdentifier(arg.property)) {
1780
- return isTypeMissingError(arg.property);
1781
- }
1782
- return false;
1783
- }
1784
- return {
1785
- "CallExpression[arguments.length > 0] > MemberExpression > Identifier[name='subscribe']": (node) => {
1786
- const memberExpression = node.parent;
1787
- const callExpression = memberExpression.parent;
1788
- if ((isMissingErrorCallback(callExpression) || isMissingErrorProperty(callExpression)) && couldBeObservable(memberExpression.object)) {
1789
- context.report({
1790
- messageId: "forbidden",
1791
- node
1792
- });
1793
- }
1794
- }
1795
- };
1796
- }
1797
- });
1798
-
1799
- // src/rules/no-ignored-notifier.ts
1800
- var noIgnoredNotifierRule = ruleCreator({
1801
- defaultOptions: [],
1802
- meta: {
1803
- docs: {
1804
- description: "Disallow observables not composed from the `repeatWhen` or `retryWhen` notifier.",
1805
- recommended: "recommended",
1806
- requiresTypeChecking: true
1807
- },
1808
- messages: {
1809
- forbidden: "Ignoring the notifier is forbidden."
1810
- },
1811
- schema: [],
1812
- type: "problem"
1813
- },
1814
- name: "no-ignored-notifier",
1815
- create: (context) => {
1816
- const { couldBeMonoTypeOperatorFunction } = getTypeServices(context);
1817
- const entries = [];
1818
- function getEntry() {
1819
- const { length, [length - 1]: entry } = entries;
1820
- return entry;
1821
- }
1822
- return {
1823
- "CallExpression[callee.name=/^(repeatWhen|retryWhen)$/]": (node) => {
1824
- if (couldBeMonoTypeOperatorFunction(node)) {
1825
- const [arg] = node.arguments;
1826
- if (isArrowFunctionExpression(arg) || isFunctionExpression(arg)) {
1827
- const [param] = arg.params;
1828
- if (param) {
1829
- entries.push({
1830
- node,
1831
- param,
1832
- sightings: 0
1833
- });
1834
- } else {
1835
- context.report({
1836
- messageId: "forbidden",
1837
- node: node.callee
1838
- });
1839
- }
1840
- }
1841
- }
1842
- },
1843
- "CallExpression[callee.name=/^(repeatWhen|retryWhen)$/]:exit": (node) => {
1844
- const entry = getEntry();
1845
- if (!entry) {
1846
- return;
1847
- }
1848
- if (entry.node === node) {
1849
- if (entry.sightings < 2) {
1850
- context.report({
1851
- messageId: "forbidden",
1852
- node: node.callee
1853
- });
1854
- }
1855
- entries.pop();
1856
- }
1857
- },
1858
- "Identifier": (node) => {
1859
- const entry = getEntry();
1860
- if (!entry) {
1861
- return;
1862
- }
1863
- if (node.name === entry.param.name) {
1864
- ++entry.sightings;
1865
- }
1866
- }
1867
- };
1868
- }
1869
- });
1870
-
1871
- // src/rules/no-ignored-observable.ts
1872
- var noIgnoredObservableRule = ruleCreator({
1873
- defaultOptions: [],
1874
- meta: {
1875
- deprecated: true,
1876
- docs: {
1877
- description: "Disallow ignoring of observables returned by functions."
1878
- },
1879
- messages: {
1880
- forbidden: "Ignoring a returned Observable is forbidden."
1881
- },
1882
- replacedBy: ["no-floating-observables"],
1883
- schema: [],
1884
- type: "problem"
1885
- },
1886
- name: "no-ignored-observable",
1887
- create: (context) => {
1888
- const { couldBeObservable } = getTypeServices(context);
1889
- return {
1890
- "ExpressionStatement > CallExpression": (node) => {
1891
- if (couldBeObservable(node)) {
1892
- context.report({
1893
- messageId: "forbidden",
1894
- node
1895
- });
1896
- }
1897
- }
1898
- };
1899
- }
1900
- });
1901
-
1902
- // src/rules/no-ignored-replay-buffer.ts
1903
- var noIgnoredReplayBufferRule = ruleCreator({
1904
- defaultOptions: [],
1905
- meta: {
1906
- docs: {
1907
- description: "Disallow using `ReplaySubject`, `publishReplay` or `shareReplay` without specifying the buffer size.",
1908
- recommended: "recommended"
1909
- },
1910
- messages: {
1911
- forbidden: "Ignoring the buffer size is forbidden."
1912
- },
1913
- schema: [],
1914
- type: "problem"
1915
- },
1916
- name: "no-ignored-replay-buffer",
1917
- create: (context) => {
1918
- function checkShareReplayConfig(node, shareReplayConfigArg) {
1919
- if (!shareReplayConfigArg.properties.some((p) => isProperty(p) && isIdentifier(p.key) && p.key.name === "bufferSize")) {
1920
- context.report({
1921
- messageId: "forbidden",
1922
- node
1923
- });
1924
- }
1925
- }
1926
- function checkNode(node, { arguments: args }) {
1927
- if (!args || args.length === 0) {
1928
- context.report({
1929
- messageId: "forbidden",
1930
- node
1931
- });
1932
- }
1933
- if (node.name === "shareReplay" && (args == null ? void 0 : args.length) === 1) {
1934
- const [arg] = args;
1935
- if (isObjectExpression(arg)) {
1936
- checkShareReplayConfig(node, arg);
1937
- }
1938
- }
1939
- }
1940
- return {
1941
- "NewExpression > Identifier[name='ReplaySubject']": (node) => {
1942
- const newExpression = node.parent;
1943
- checkNode(node, newExpression);
1944
- },
1945
- "NewExpression > MemberExpression > Identifier[name='ReplaySubject']": (node) => {
1946
- const memberExpression = node.parent;
1947
- const newExpression = memberExpression.parent;
1948
- checkNode(node, newExpression);
1949
- },
1950
- "CallExpression > Identifier[name=/^(publishReplay|shareReplay)$/]": (node) => {
1951
- const callExpression = node.parent;
1952
- checkNode(node, callExpression);
1953
- },
1954
- "CallExpression > MemberExpression > Identifier[name=/^(publishReplay|shareReplay)$/]": (node) => {
1955
- const memberExpression = node.parent;
1956
- const callExpression = memberExpression.parent;
1957
- checkNode(node, callExpression);
1958
- }
1959
- };
1960
- }
1961
- });
1962
-
1963
- // src/rules/no-ignored-subscribe.ts
1964
- var noIgnoredSubscribeRule = ruleCreator({
1965
- defaultOptions: [],
1966
- meta: {
1967
- docs: {
1968
- description: "Disallow calling `subscribe` without specifying arguments.",
1969
- requiresTypeChecking: true
1970
- },
1971
- messages: {
1972
- forbidden: "Calling subscribe without arguments is forbidden."
1973
- },
1974
- schema: [],
1975
- type: "problem"
1976
- },
1977
- name: "no-ignored-subscribe",
1978
- create: (context) => {
1979
- const { couldBeObservable, couldBeType: couldBeType2 } = getTypeServices(context);
1980
- return {
1981
- "CallExpression[arguments.length = 0][callee.property.name='subscribe']": (node) => {
1982
- const callee = node.callee;
1983
- if (couldBeObservable(callee.object) || couldBeType2(callee.object, "Subscribable")) {
1984
- context.report({
1985
- messageId: "forbidden",
1986
- node: callee.property
1987
- });
1988
- }
1989
- }
1990
- };
1991
- }
1992
- });
1993
-
1994
- // src/rules/no-ignored-subscription.ts
1995
- import { stripIndent as stripIndent4 } from "common-tags";
1996
- var defaultOptions7 = [];
1997
- var noIgnoredSubscriptionRule = ruleCreator({
1998
- defaultOptions: defaultOptions7,
1999
- meta: {
2000
- docs: {
2001
- description: "Disallow ignoring the subscription returned by `subscribe`.",
2002
- requiresTypeChecking: true
2003
- },
2004
- messages: {
2005
- forbidden: "Ignoring returned subscriptions is forbidden."
2006
- },
2007
- schema: [
2008
- {
2009
- properties: {
2010
- 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"] },
2011
- 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 }
2012
- },
2013
- type: "object",
2014
- description: stripIndent4`
2015
- An object with optional \`completers\` and \`postCompleters\` properties.
2016
- The \`completers\` property is an array containing the names of operators that will complete the observable and silence this rule.
2017
- The \`postCompleters\` property is an array containing the names of the operators that are allowed to follow the completion operators.
2018
- `
2019
- }
2020
- ],
2021
- type: "problem"
2022
- },
2023
- name: "no-ignored-subscription",
2024
- create: (context) => {
2025
- const [config = {}] = context.options;
2026
- const {
2027
- completers = ["takeUntil", "takeWhile", "take", "first", "last", "takeUntilDestroyed"],
2028
- postCompleters = DEFAULT_VALID_POST_COMPLETION_OPERATORS
2029
- } = config;
2030
- const checkedOperatorsRegExp = new RegExp(
2031
- `^(${completers.join("|")})$`
2032
- );
2033
- const { couldBeObservable, couldBeType: couldBeType2 } = getTypeServices(context);
2034
- function hasAllowedOperator(node) {
2035
- if (isCallExpression(node) && isMemberExpression(node.callee) && isIdentifier(node.callee.property) && node.callee.property.name === "pipe") {
2036
- const { isOrderValid, operatorNode } = findIsLastOperatorOrderValid(
2037
- node,
2038
- checkedOperatorsRegExp,
2039
- postCompleters
2040
- );
2041
- return isOrderValid && !!operatorNode;
2042
- }
2043
- return false;
2044
- }
2045
- return {
2046
- "ExpressionStatement > CallExpression > MemberExpression[property.name='subscribe']": (node) => {
2047
- if (couldBeObservable(node.object)) {
2048
- const callExpression = node.parent;
2049
- if (callExpression.arguments.length === 1 && couldBeType2(callExpression.arguments[0], "Subscriber")) {
2050
- return;
2051
- }
2052
- if (hasAllowedOperator(node.object)) {
2053
- return;
2054
- }
2055
- context.report({
2056
- messageId: "forbidden",
2057
- node: node.property
2058
- });
2059
- }
2060
- }
2061
- };
2062
- }
2063
- });
2064
-
2065
- // src/rules/no-ignored-takewhile-value.ts
2066
- var noIgnoredTakewhileValueRule = ruleCreator({
2067
- defaultOptions: [],
2068
- meta: {
2069
- docs: {
2070
- description: "Disallow ignoring the value within `takeWhile`.",
2071
- recommended: "recommended"
2072
- },
2073
- messages: {
2074
- forbidden: "Ignoring the value within takeWhile is forbidden."
2075
- },
2076
- schema: [],
2077
- type: "problem"
2078
- },
2079
- name: "no-ignored-takewhile-value",
2080
- create: (context) => {
2081
- function checkNode(expression) {
2082
- const scope = context.sourceCode.getScope(expression);
2083
- if (!isImport(scope, "takeWhile", /^rxjs\/?/)) {
2084
- return;
2085
- }
2086
- let ignored = true;
2087
- const [param] = expression.params;
2088
- if (param) {
2089
- if (isIdentifier(param)) {
2090
- const variable = scope.variables.find(
2091
- ({ name: name2 }) => name2 === param.name
2092
- );
2093
- if (variable && variable.references.length > 0) {
2094
- ignored = false;
2095
- }
2096
- } else if (isArrayPattern(param)) {
2097
- ignored = false;
2098
- } else if (isObjectPattern(param)) {
2099
- ignored = false;
2100
- }
2101
- }
2102
- if (ignored) {
2103
- context.report({
2104
- messageId: "forbidden",
2105
- node: expression
2106
- });
2107
- }
2108
- }
2109
- return {
2110
- "CallExpression[callee.name='takeWhile'] > ArrowFunctionExpression": (node) => {
2111
- checkNode(node);
2112
- },
2113
- "CallExpression[callee.name='takeWhile'] > FunctionExpression": (node) => {
2114
- checkNode(node);
2115
- }
2116
- };
2117
- }
2118
- });
2119
-
2120
- // src/rules/no-implicit-any-catch.ts
2121
- import {
2122
- AST_NODE_TYPES as AST_NODE_TYPES4
2123
- } from "@typescript-eslint/utils";
2124
- function isParenthesised(sourceCode, node) {
2125
- const before = sourceCode.getTokenBefore(node);
2126
- const after = sourceCode.getTokenAfter(node);
2127
- return before && after && before.value === "(" && before.range[1] <= node.range[0] && after.value === ")" && after.range[0] >= node.range[1];
2128
- }
2129
- var defaultOptions8 = [];
2130
- var noImplicitAnyCatchRule = ruleCreator({
2131
- defaultOptions: defaultOptions8,
2132
- meta: {
2133
- docs: {
2134
- description: "Disallow implicit `any` error parameters in `catchError`, `subscribe`, and `tap`.",
2135
- recommended: {
2136
- recommended: true,
2137
- strict: [{
2138
- allowExplicitAny: false
2139
- }]
2140
- },
2141
- requiresTypeChecking: true
2142
- },
2143
- fixable: "code",
2144
- hasSuggestions: true,
2145
- messages: {
2146
- explicitAny: "Explicit `any` in error callback.",
2147
- implicitAny: "Implicit `any` in error callback.",
2148
- narrowed: "Error type must be `unknown` or `any`.",
2149
- narrowedAllowError: "Error type must be `unknown`, `any`, or `Error`.",
2150
- suggestExplicitUnknown: "Use `unknown` instead to explicitly and safely assert the type is correct.",
2151
- suggestExplicitAny: "Use `any` instead to explicitly opt out of type safety.",
2152
- suggestExplicitError: "Use `Error` instead."
2153
- },
2154
- schema: [
2155
- {
2156
- additionalProperties: false,
2157
- properties: {
2158
- allowExplicitAny: {
2159
- type: "boolean",
2160
- description: "Allow error variable to be explicitly typed as `any`.",
2161
- default: true
2162
- },
2163
- allowExplicitError: {
2164
- type: "boolean",
2165
- description: "Allow narrowing error type to `Error`.",
2166
- default: false
2167
- }
2168
- },
2169
- type: "object"
2170
- }
2171
- ],
2172
- type: "suggestion"
2173
- },
2174
- name: "no-implicit-any-catch",
2175
- create: (context) => {
2176
- const [config = {}] = context.options;
2177
- const { allowExplicitAny = true, allowExplicitError = false } = config;
2178
- const { couldBeObservable } = getTypeServices(context);
2179
- const sourceCode = context.sourceCode;
2180
- function createReplacerFix(typeAnnotation, replaceWith) {
2181
- return function fix(fixer) {
2182
- return fixer.replaceText(typeAnnotation, `: ${replaceWith}`);
2183
- };
2184
- }
2185
- function createInserterFix(param, annotateWith, { hasRestParams = false } = {}) {
2186
- return function fix(fixer) {
2187
- if (hasRestParams || isParenthesised(sourceCode, param)) {
2188
- return fixer.insertTextAfter(param, `: ${annotateWith}`);
2189
- }
2190
- return [
2191
- fixer.insertTextBefore(param, "("),
2192
- fixer.insertTextAfter(param, `: ${annotateWith})`)
2193
- ];
2194
- };
2195
- }
2196
- function checkCallback(callback) {
2197
- if (isArrowFunctionExpression(callback) || isFunctionExpression(callback)) {
2198
- const [param, ...restParams] = callback.params;
2199
- if (!param) {
2200
- return;
2201
- }
2202
- if (hasTypeAnnotation(param)) {
2203
- const { typeAnnotation } = param;
2204
- const {
2205
- typeAnnotation: { type }
2206
- } = typeAnnotation;
2207
- if (type === AST_NODE_TYPES4.TSAnyKeyword) {
2208
- if (allowExplicitAny) {
2209
- return;
2210
- }
2211
- context.report({
2212
- messageId: "explicitAny",
2213
- node: param,
2214
- suggest: [
2215
- {
2216
- messageId: "suggestExplicitUnknown",
2217
- fix: createReplacerFix(typeAnnotation, "unknown")
2218
- }
2219
- ]
2220
- });
2221
- } else if (type !== AST_NODE_TYPES4.TSUnknownKeyword) {
2222
- let isAllowedError = false;
2223
- if (allowExplicitError && type === AST_NODE_TYPES4.TSTypeReference) {
2224
- const typeRef = typeAnnotation.typeAnnotation;
2225
- if (isIdentifier(typeRef.typeName)) {
2226
- isAllowedError = typeRef.typeName.name === "Error";
2227
- }
2228
- }
2229
- if (!isAllowedError) {
2230
- context.report({
2231
- messageId: allowExplicitError ? "narrowedAllowError" : "narrowed",
2232
- node: param,
2233
- suggest: [
2234
- {
2235
- messageId: "suggestExplicitUnknown",
2236
- fix: createReplacerFix(typeAnnotation, "unknown")
2237
- },
2238
- allowExplicitAny ? {
2239
- messageId: "suggestExplicitAny",
2240
- fix: createReplacerFix(typeAnnotation, "any")
2241
- } : null,
2242
- allowExplicitError && !isAllowedError ? {
2243
- messageId: "suggestExplicitError",
2244
- fix: createReplacerFix(typeAnnotation, "Error")
2245
- } : null
2246
- ].filter((x) => !!x)
2247
- });
2248
- }
2249
- }
2250
- } else {
2251
- const hasRestParams = restParams.length > 0;
2252
- context.report({
2253
- fix: allowExplicitAny ? createInserterFix(param, "any", { hasRestParams }) : void 0,
2254
- messageId: "implicitAny",
2255
- node: param,
2256
- suggest: [
2257
- {
2258
- messageId: "suggestExplicitUnknown",
2259
- fix: createInserterFix(param, "unknown", { hasRestParams })
2260
- },
2261
- allowExplicitAny ? {
2262
- messageId: "suggestExplicitAny",
2263
- fix: createInserterFix(param, "any", { hasRestParams })
2264
- } : null
2265
- ].filter((x) => !!x)
2266
- });
2267
- }
2268
- }
2269
- }
2270
- return {
2271
- "CallExpression[callee.name='catchError']": (node) => {
2272
- const [callback] = node.arguments;
2273
- if (!callback) {
2274
- return;
2275
- }
2276
- checkCallback(callback);
2277
- },
2278
- "CallExpression[callee.property.name='subscribe'],CallExpression[callee.name='tap']": (node) => {
2279
- const { callee } = node;
2280
- if (isMemberExpression(callee) && !couldBeObservable(callee.object)) {
2281
- return;
2282
- }
2283
- const [observer, callback] = node.arguments;
2284
- if (callback) {
2285
- checkCallback(callback);
2286
- } else if (observer && isObjectExpression(observer)) {
2287
- const errorProperty = observer.properties.find(
2288
- (property) => isProperty(property) && isIdentifier(property.key) && property.key.name === "error"
2289
- );
2290
- if (errorProperty) {
2291
- checkCallback(errorProperty.value);
2292
- }
2293
- }
2294
- }
2295
- };
2296
- }
2297
- });
2298
-
2299
- // src/rules/no-index.ts
2300
- var noIndexRule = ruleCreator({
2301
- defaultOptions: [],
2302
- meta: {
2303
- docs: {
2304
- description: "Disallow importing index modules.",
2305
- recommended: "recommended"
2306
- },
2307
- messages: {
2308
- forbidden: "RxJS imports from index modules are forbidden."
2309
- },
2310
- schema: [],
2311
- type: "problem"
2312
- },
2313
- name: "no-index",
2314
- create: (context) => {
2315
- return {
2316
- [String.raw`ImportDeclaration Literal[value=/^rxjs(?:\u002f\w+)?\u002findex/]`]: (node) => {
2317
- context.report({
2318
- messageId: "forbidden",
2319
- node
2320
- });
2321
- }
2322
- };
2323
- }
2324
- });
2325
-
2326
- // src/rules/no-internal.ts
2327
- var noInternalRule = ruleCreator({
2328
- defaultOptions: [],
2329
- meta: {
2330
- docs: {
2331
- description: "Disallow importing internal modules.",
2332
- recommended: "recommended"
2333
- },
2334
- fixable: "code",
2335
- hasSuggestions: true,
2336
- messages: {
2337
- forbidden: "RxJS imports from internal are forbidden.",
2338
- suggest: "Import from a non-internal location."
2339
- },
2340
- schema: [],
2341
- type: "problem"
2342
- },
2343
- name: "no-internal",
2344
- create: (context) => {
2345
- function getReplacement(location) {
2346
- const match = /^\s*('|")/.exec(location);
2347
- if (!match) {
2348
- return void 0;
2349
- }
2350
- const [, quote] = match;
2351
- if (/^['"]rxjs\/internal\/ajax/.test(location)) {
2352
- return `${quote}rxjs/ajax${quote}`;
2353
- }
2354
- if (/^['"]rxjs\/internal\/observable\/dom\/fetch/.test(location)) {
2355
- return `${quote}rxjs/fetch${quote}`;
2356
- }
2357
- if (/^['"]rxjs\/internal\/observable\/dom\/webSocket/i.test(location)) {
2358
- return `${quote}rxjs/webSocket${quote}`;
2359
- }
2360
- if (/^['"]rxjs\/internal\/observable/.test(location)) {
2361
- return `${quote}rxjs${quote}`;
2362
- }
2363
- if (/^['"]rxjs\/internal\/operators/.test(location)) {
2364
- return `${quote}rxjs/operators${quote}`;
2365
- }
2366
- if (/^['"]rxjs\/internal\/scheduled/.test(location)) {
2367
- return `${quote}rxjs${quote}`;
2368
- }
2369
- if (/^['"]rxjs\/internal\/scheduler/.test(location)) {
2370
- return `${quote}rxjs${quote}`;
2371
- }
2372
- if (/^['"]rxjs\/internal\/testing/.test(location)) {
2373
- return `${quote}rxjs/testing${quote}`;
2374
- }
2375
- return void 0;
2376
- }
2377
- return {
2378
- [String.raw`ImportDeclaration Literal[value=/^rxjs\u002finternal/]`]: (node) => {
2379
- const replacement = getReplacement(node.raw);
2380
- if (replacement) {
2381
- let fix2 = function(fixer) {
2382
- return fixer.replaceText(node, replacement);
2383
- };
2384
- var fix = fix2;
2385
- context.report({
2386
- fix: fix2,
2387
- messageId: "forbidden",
2388
- node,
2389
- suggest: [{ fix: fix2, messageId: "suggest" }]
2390
- });
2391
- } else {
2392
- context.report({
2393
- messageId: "forbidden",
2394
- node
2395
- });
2396
- }
2397
- }
2398
- };
2399
- }
2400
- });
2401
-
2402
- // src/rules/no-misused-observables.ts
2403
- import { AST_NODE_TYPES as AST_NODE_TYPES5, ESLintUtils as ESLintUtils9 } from "@typescript-eslint/utils";
2404
- import { getFunctionHeadLocation, isFunction } from "@typescript-eslint/utils/ast-utils";
2405
- import * as tsutils4 from "ts-api-utils";
2406
- import ts5 from "typescript";
2407
- function parseChecksVoidReturn(checksVoidReturn) {
2408
- var _a, _b, _c, _d, _e, _f;
2409
- switch (checksVoidReturn) {
2410
- case false:
2411
- return false;
2412
- case true:
2413
- case void 0:
2414
- return {
2415
- arguments: true,
2416
- attributes: true,
2417
- inheritedMethods: true,
2418
- properties: true,
2419
- returns: true,
2420
- variables: true
2421
- };
2422
- default:
2423
- return {
2424
- arguments: (_a = checksVoidReturn.arguments) != null ? _a : true,
2425
- attributes: (_b = checksVoidReturn.attributes) != null ? _b : true,
2426
- inheritedMethods: (_c = checksVoidReturn.inheritedMethods) != null ? _c : true,
2427
- properties: (_d = checksVoidReturn.properties) != null ? _d : true,
2428
- returns: (_e = checksVoidReturn.returns) != null ? _e : true,
2429
- variables: (_f = checksVoidReturn.variables) != null ? _f : true
2430
- };
2431
- }
2432
- }
2433
- var defaultOptions9 = [];
2434
- var noMisusedObservablesRule = ruleCreator({
2435
- defaultOptions: defaultOptions9,
2436
- meta: {
2437
- docs: {
2438
- description: "Disallow Observables in places not designed to handle them.",
2439
- recommended: "strict",
2440
- requiresTypeChecking: true
2441
- },
2442
- messages: {
2443
- forbiddenVoidReturnArgument: "Observable returned in function argument where a void return was expected.",
2444
- forbiddenVoidReturnAttribute: "Observable-returning function provided to attribute where a void return was expected.",
2445
- forbiddenVoidReturnInheritedMethod: "Observable-returning method provided where a void return was expected by extended/implemented type '{{heritageTypeName}}'.",
2446
- forbiddenVoidReturnProperty: "Observable-returning function provided to property where a void return was expected.",
2447
- forbiddenVoidReturnReturnValue: "Observable-returning function provided to return value where a void return was expected.",
2448
- forbiddenVoidReturnVariable: "Observable-returning function provided to variable where a void return was expected.",
2449
- forbiddenSpread: "Expected a non-Observable value to be spread into an object."
2450
- },
2451
- schema: [
2452
- {
2453
- properties: {
2454
- checksVoidReturn: {
2455
- default: true,
2456
- description: "Disallow returning an Observable from a function typed as returning `void`.",
2457
- oneOf: [
2458
- {
2459
- default: true,
2460
- type: "boolean",
2461
- description: "Disallow returning an Observable from all types of functions typed as returning `void`."
2462
- },
2463
- {
2464
- type: "object",
2465
- additionalProperties: false,
2466
- description: "Which forms of functions may have checking disabled.",
2467
- properties: {
2468
- arguments: { type: "boolean", description: "Disallow passing an Observable-returning function as an argument where the parameter type expects a function that returns `void`." },
2469
- attributes: { type: "boolean", description: "Disallow passing an Observable-returning function as a JSX attribute expected to be a function that returns `void`." },
2470
- inheritedMethods: { type: "boolean", description: "Disallow providing an Observable-returning function where a function that returns `void` is expected by an extended or implemented type." },
2471
- properties: { type: "boolean", description: "Disallow providing an Observable-returning function where a function that returns `void` is expected by a property." },
2472
- returns: { type: "boolean", description: "Disallow returning an Observable-returning function where a function that returns `void` is expected." },
2473
- variables: { type: "boolean", description: "Disallow assigning or declaring an Observable-returning function where a function that returns `void` is expected." }
2474
- }
2475
- }
2476
- ]
2477
- },
2478
- checksSpreads: { type: "boolean", default: true, description: "Disallow `...` spreading an Observable." }
2479
- },
2480
- type: "object"
2481
- }
2482
- ],
2483
- type: "problem"
2484
- },
2485
- name: "no-misused-observables",
2486
- create: (context) => {
2487
- const { program, esTreeNodeToTSNodeMap, getTypeAtLocation } = ESLintUtils9.getParserServices(context);
2488
- const checker = program.getTypeChecker();
2489
- const { couldBeObservable, couldReturnObservable } = getTypeServices(context);
2490
- const [config = {}] = context.options;
2491
- const { checksVoidReturn = true, checksSpreads = true } = config;
2492
- const parsedChecksVoidReturn = parseChecksVoidReturn(checksVoidReturn);
2493
- const voidReturnChecks = parsedChecksVoidReturn ? {
2494
- ...parsedChecksVoidReturn.arguments && {
2495
- CallExpression: checkArguments,
2496
- NewExpression: checkArguments
2497
- },
2498
- ...parsedChecksVoidReturn.attributes && {
2499
- JSXAttribute: checkJSXAttribute
2500
- },
2501
- ...parsedChecksVoidReturn.inheritedMethods && {
2502
- ClassDeclaration: checkClassLikeOrInterfaceNode,
2503
- ClassExpression: checkClassLikeOrInterfaceNode,
2504
- TSInterfaceDeclaration: checkClassLikeOrInterfaceNode
2505
- },
2506
- ...parsedChecksVoidReturn.properties && {
2507
- Property: checkProperty
2508
- },
2509
- ...parsedChecksVoidReturn.returns && {
2510
- ReturnStatement: checkReturnStatement
2511
- },
2512
- ...parsedChecksVoidReturn.variables && {
2513
- AssignmentExpression: checkAssignment,
2514
- VariableDeclarator: checkVariableDeclaration
2515
- }
2516
- } : {};
2517
- const spreadChecks = {
2518
- SpreadElement: (node) => {
2519
- if (couldBeObservable(node.argument)) {
2520
- context.report({
2521
- messageId: "forbiddenSpread",
2522
- node: node.argument
2523
- });
2524
- }
2525
- }
2526
- };
2527
- function checkArguments(node) {
2528
- const tsNode = esTreeNodeToTSNodeMap.get(node);
2529
- const voidArgs = voidFunctionArguments(checker, tsNode);
2530
- if (!voidArgs.size) {
2531
- return;
2532
- }
2533
- for (const [index, argument] of node.arguments.entries()) {
2534
- if (!voidArgs.has(index)) {
2535
- continue;
2536
- }
2537
- if (couldReturnObservable(argument)) {
2538
- context.report({
2539
- messageId: "forbiddenVoidReturnArgument",
2540
- node: argument
2541
- });
2542
- }
2543
- }
2544
- }
2545
- function checkJSXAttribute(node) {
2546
- if (node.value == null || !isJSXExpressionContainer(node.value)) {
2547
- return;
2548
- }
2549
- const expressionContainer = esTreeNodeToTSNodeMap.get(
2550
- node.value
2551
- );
2552
- const contextualType = checker.getContextualType(expressionContainer);
2553
- if (contextualType != null && isVoidReturningFunctionType(contextualType) && couldReturnObservable(node.value.expression)) {
2554
- context.report({
2555
- messageId: "forbiddenVoidReturnAttribute",
2556
- node: node.value
2557
- });
2558
- }
2559
- }
2560
- function checkClassLikeOrInterfaceNode(node) {
2561
- var _a;
2562
- const tsNode = esTreeNodeToTSNodeMap.get(node);
2563
- const heritageTypes = getHeritageTypes(checker, tsNode);
2564
- if (!(heritageTypes == null ? void 0 : heritageTypes.length)) {
2565
- return;
2566
- }
2567
- for (const element of node.body.body) {
2568
- const tsElement = esTreeNodeToTSNodeMap.get(element);
2569
- const memberName = (_a = tsElement == null ? void 0 : tsElement.name) == null ? void 0 : _a.getText();
2570
- if (memberName == null) {
2571
- continue;
2572
- }
2573
- if (!couldReturnObservable(element)) {
2574
- continue;
2575
- }
2576
- if (isStaticMember(element)) {
2577
- continue;
2578
- }
2579
- for (const heritageType of heritageTypes) {
2580
- const heritageMember = getMemberIfExists(heritageType, memberName);
2581
- if (heritageMember == null) {
2582
- continue;
2583
- }
2584
- const memberType = checker.getTypeOfSymbolAtLocation(heritageMember, tsElement);
2585
- if (!isVoidReturningFunctionType(memberType)) {
2586
- continue;
2587
- }
2588
- context.report({
2589
- messageId: "forbiddenVoidReturnInheritedMethod",
2590
- node: element,
2591
- data: { heritageTypeName: checker.typeToString(heritageType) }
2592
- });
2593
- }
2594
- }
2595
- }
2596
- function checkProperty(node) {
2597
- const tsNode = esTreeNodeToTSNodeMap.get(node);
2598
- const contextualType = getPropertyContextualType(checker, tsNode);
2599
- if (contextualType == null) {
2600
- return;
2601
- }
2602
- if (!isVoidReturningFunctionType(contextualType)) {
2603
- return;
2604
- }
2605
- if (!couldReturnObservable(node.value)) {
2606
- return;
2607
- }
2608
- if (isFunction(node.value)) {
2609
- const functionNode = node.value;
2610
- if (functionNode.returnType) {
2611
- context.report({
2612
- messageId: "forbiddenVoidReturnProperty",
2613
- node: functionNode.returnType.typeAnnotation
2614
- });
2615
- } else {
2616
- context.report({
2617
- messageId: "forbiddenVoidReturnProperty",
2618
- loc: getFunctionHeadLocation(functionNode, context.sourceCode)
2619
- });
2620
- }
2621
- } else {
2622
- context.report({
2623
- messageId: "forbiddenVoidReturnProperty",
2624
- node: node.value
2625
- });
2626
- }
2627
- }
2628
- function checkReturnStatement(node) {
2629
- const tsNode = esTreeNodeToTSNodeMap.get(node);
2630
- if (tsNode.expression == null || !node.argument) {
2631
- return;
2632
- }
2633
- function getFunctionNode() {
2634
- let current = node.parent;
2635
- while (current && !isArrowFunctionExpression(current) && !isFunctionExpression(current) && !isFunctionDeclaration(current)) {
2636
- current = current.parent;
2637
- }
2638
- return current;
2639
- }
2640
- const functionNode = getFunctionNode();
2641
- if ((functionNode == null ? void 0 : functionNode.returnType) && !isPossiblyFunctionType(functionNode.returnType)) {
2642
- return;
2643
- }
2644
- const contextualType = checker.getContextualType(tsNode.expression);
2645
- if (contextualType == null) {
2646
- return;
2647
- }
2648
- if (!isVoidReturningFunctionType(contextualType)) {
2649
- return;
2650
- }
2651
- if (!couldReturnObservable(node.argument)) {
2652
- return;
2653
- }
2654
- context.report({
2655
- node: node.argument,
2656
- messageId: "forbiddenVoidReturnReturnValue"
2657
- });
2658
- }
2659
- function checkAssignment(node) {
2660
- const varType = getTypeAtLocation(node.left);
2661
- if (!isVoidReturningFunctionType(varType)) {
2662
- return;
2663
- }
2664
- if (couldReturnObservable(node.right)) {
2665
- context.report({
2666
- messageId: "forbiddenVoidReturnVariable",
2667
- node: node.right
2668
- });
2669
- }
2670
- }
2671
- function checkVariableDeclaration(node) {
2672
- const tsNode = esTreeNodeToTSNodeMap.get(node);
2673
- if (tsNode.initializer == null || node.init == null || node.id.typeAnnotation == null) {
2674
- return;
2675
- }
2676
- if (!isPossiblyFunctionType(node.id.typeAnnotation)) {
2677
- return;
2678
- }
2679
- const varType = getTypeAtLocation(node.id);
2680
- if (!isVoidReturningFunctionType(varType)) {
2681
- return;
2682
- }
2683
- if (couldReturnObservable(node.init)) {
2684
- context.report({
2685
- messageId: "forbiddenVoidReturnVariable",
2686
- node: node.init
2687
- });
2688
- }
2689
- }
2690
- return {
2691
- ...checksVoidReturn ? voidReturnChecks : {},
2692
- ...checksSpreads ? spreadChecks : {}
2693
- };
2694
- }
2695
- });
2696
- function voidFunctionArguments(checker, tsNode) {
2697
- if (!tsNode.arguments) {
2698
- return /* @__PURE__ */ new Set();
2699
- }
2700
- const voidReturnIndices = /* @__PURE__ */ new Set();
2701
- const type = checker.getTypeAtLocation(tsNode.expression);
2702
- for (const subType of tsutils4.unionConstituents(type)) {
2703
- const signatures = ts5.isCallExpression(tsNode) ? subType.getCallSignatures() : subType.getConstructSignatures();
2704
- for (const signature of signatures) {
2705
- for (const [index, parameter] of signature.parameters.entries()) {
2706
- const type2 = checker.getTypeOfSymbolAtLocation(parameter, tsNode.expression);
2707
- if (isVoidReturningFunctionType(type2)) {
2708
- voidReturnIndices.add(index);
2709
- }
2710
- }
2711
- }
2712
- }
2713
- return voidReturnIndices;
2714
- }
2715
- function isVoidReturningFunctionType(type) {
2716
- let hasVoidReturn = false;
2717
- for (const subType of tsutils4.unionConstituents(type)) {
2718
- for (const signature of subType.getCallSignatures()) {
2719
- const returnType = signature.getReturnType();
2720
- if (couldBeType(returnType, "Observable")) {
2721
- return false;
2722
- }
2723
- hasVoidReturn || (hasVoidReturn = tsutils4.isTypeFlagSet(returnType, ts5.TypeFlags.Void));
2724
- }
2725
- }
2726
- return hasVoidReturn;
2727
- }
2728
- function getHeritageTypes(checker, tsNode) {
2729
- var _a;
2730
- return (_a = tsNode.heritageClauses) == null ? void 0 : _a.flatMap((clause) => clause.types).map((typeExpressions) => checker.getTypeAtLocation(typeExpressions));
2731
- }
2732
- function getMemberIfExists(type, memberName) {
2733
- var _a, _b;
2734
- const escapedMemberName = ts5.escapeLeadingUnderscores(memberName);
2735
- const symbolMemberMatch = (_b = (_a = type.getSymbol()) == null ? void 0 : _a.members) == null ? void 0 : _b.get(escapedMemberName);
2736
- return symbolMemberMatch != null ? symbolMemberMatch : tsutils4.getPropertyOfType(type, escapedMemberName);
2737
- }
2738
- function isStaticMember(node) {
2739
- return (isMethodDefinition(node) || isPropertyDefinition(node) || isAccessorProperty(node)) && node.static;
2740
- }
2741
- function getPropertyContextualType(checker, tsNode) {
2742
- if (ts5.isPropertyAssignment(tsNode)) {
2743
- return checker.getContextualType(tsNode.initializer);
2744
- } else if (ts5.isShorthandPropertyAssignment(tsNode)) {
2745
- return checker.getContextualType(tsNode.name);
2746
- } else if (ts5.isMethodDeclaration(tsNode)) {
2747
- if (ts5.isComputedPropertyName(tsNode.name)) {
2748
- return;
2749
- }
2750
- const obj = tsNode.parent;
2751
- if (!ts5.isObjectLiteralExpression(obj)) {
2752
- return;
2753
- }
2754
- const objType = checker.getContextualType(obj);
2755
- if (objType == null) {
2756
- return;
2757
- }
2758
- const propertySymbol = tsutils4.unionConstituents(objType).map((t) => checker.getPropertyOfType(t, tsNode.name.getText())).find((p) => p);
2759
- if (propertySymbol == null) {
2760
- return;
2761
- }
2762
- return checker.getTypeOfSymbolAtLocation(propertySymbol, tsNode.name);
2763
- } else {
2764
- return void 0;
2765
- }
2766
- }
2767
- function isPossiblyFunctionType(node) {
2768
- switch (node.typeAnnotation.type) {
2769
- case AST_NODE_TYPES5.TSConditionalType:
2770
- case AST_NODE_TYPES5.TSConstructorType:
2771
- case AST_NODE_TYPES5.TSFunctionType:
2772
- case AST_NODE_TYPES5.TSImportType:
2773
- case AST_NODE_TYPES5.TSIndexedAccessType:
2774
- case AST_NODE_TYPES5.TSInferType:
2775
- case AST_NODE_TYPES5.TSIntersectionType:
2776
- case AST_NODE_TYPES5.TSQualifiedName:
2777
- case AST_NODE_TYPES5.TSThisType:
2778
- case AST_NODE_TYPES5.TSTypeOperator:
2779
- case AST_NODE_TYPES5.TSTypeQuery:
2780
- case AST_NODE_TYPES5.TSTypeReference:
2781
- case AST_NODE_TYPES5.TSUnionType:
2782
- return true;
2783
- case AST_NODE_TYPES5.TSTypeLiteral:
2784
- return node.typeAnnotation.members.some(
2785
- (member) => member.type === AST_NODE_TYPES5.TSCallSignatureDeclaration || member.type === AST_NODE_TYPES5.TSConstructSignatureDeclaration
2786
- );
2787
- case AST_NODE_TYPES5.TSAbstractKeyword:
2788
- case AST_NODE_TYPES5.TSAnyKeyword:
2789
- case AST_NODE_TYPES5.TSArrayType:
2790
- case AST_NODE_TYPES5.TSAsyncKeyword:
2791
- case AST_NODE_TYPES5.TSBigIntKeyword:
2792
- case AST_NODE_TYPES5.TSBooleanKeyword:
2793
- case AST_NODE_TYPES5.TSDeclareKeyword:
2794
- case AST_NODE_TYPES5.TSExportKeyword:
2795
- case AST_NODE_TYPES5.TSIntrinsicKeyword:
2796
- case AST_NODE_TYPES5.TSLiteralType:
2797
- case AST_NODE_TYPES5.TSMappedType:
2798
- case AST_NODE_TYPES5.TSNamedTupleMember:
2799
- case AST_NODE_TYPES5.TSNeverKeyword:
2800
- case AST_NODE_TYPES5.TSNullKeyword:
2801
- case AST_NODE_TYPES5.TSNumberKeyword:
2802
- case AST_NODE_TYPES5.TSObjectKeyword:
2803
- case AST_NODE_TYPES5.TSOptionalType:
2804
- case AST_NODE_TYPES5.TSPrivateKeyword:
2805
- case AST_NODE_TYPES5.TSProtectedKeyword:
2806
- case AST_NODE_TYPES5.TSPublicKeyword:
2807
- case AST_NODE_TYPES5.TSReadonlyKeyword:
2808
- case AST_NODE_TYPES5.TSRestType:
2809
- case AST_NODE_TYPES5.TSStaticKeyword:
2810
- case AST_NODE_TYPES5.TSStringKeyword:
2811
- case AST_NODE_TYPES5.TSSymbolKeyword:
2812
- case AST_NODE_TYPES5.TSTemplateLiteralType:
2813
- case AST_NODE_TYPES5.TSTupleType:
2814
- case AST_NODE_TYPES5.TSTypePredicate:
2815
- case AST_NODE_TYPES5.TSUndefinedKeyword:
2816
- case AST_NODE_TYPES5.TSUnknownKeyword:
2817
- case AST_NODE_TYPES5.TSVoidKeyword:
2818
- return false;
2819
- }
2820
- }
2821
-
2822
- // src/rules/no-nested-subscribe.ts
2823
- var noNestedSubscribeRule = ruleCreator({
2824
- defaultOptions: [],
2825
- meta: {
2826
- docs: {
2827
- description: "Disallow calling `subscribe` within a `subscribe` callback.",
2828
- recommended: "recommended",
2829
- requiresTypeChecking: true
2830
- },
2831
- messages: {
2832
- forbidden: "Nested subscribe calls are forbidden."
2833
- },
2834
- schema: [],
2835
- type: "problem"
2836
- },
2837
- name: "no-nested-subscribe",
2838
- create: (context) => {
2839
- const { couldBeObservable, couldBeType: couldBeType2 } = getTypeServices(context);
2840
- const argumentsMap = /* @__PURE__ */ new WeakMap();
2841
- return {
2842
- [`CallExpression > MemberExpression[property.name='subscribe']`]: (node) => {
2843
- if (!couldBeObservable(node.object) && !couldBeType2(node.object, "Subscribable")) {
2844
- return;
2845
- }
2846
- const callExpression = node.parent;
2847
- let parent = callExpression.parent;
2848
- while (parent) {
2849
- if (argumentsMap.has(parent)) {
2850
- context.report({
2851
- messageId: "forbidden",
2852
- node: node.property
2853
- });
2854
- return;
2855
- }
2856
- parent = parent.parent;
2857
- }
2858
- for (const arg of callExpression.arguments) {
2859
- argumentsMap.set(arg);
2860
- }
2861
- }
2862
- };
2863
- }
2864
- });
2865
-
2866
- // src/rules/no-redundant-notify.ts
2867
- var noRedundantNotifyRule = ruleCreator({
2868
- defaultOptions: [],
2869
- meta: {
2870
- docs: {
2871
- description: "Disallow sending redundant notifications from completed or errored observables.",
2872
- recommended: "recommended",
2873
- requiresTypeChecking: true
2874
- },
2875
- messages: {
2876
- forbidden: "Redundant notifications are forbidden."
2877
- },
2878
- schema: [],
2879
- type: "problem"
2880
- },
2881
- name: "no-redundant-notify",
2882
- create: (context) => {
2883
- const sourceCode = context.sourceCode;
2884
- const { couldBeType: couldBeType2 } = getTypeServices(context);
2885
- return {
2886
- "ExpressionStatement[expression.callee.property.name=/^(complete|error|unsubscribe)$/] + ExpressionStatement[expression.callee.property.name=/^(next|complete|error|unsubscribe)$/]": (node) => {
2887
- const parent = node.parent;
2888
- if (!parent) {
2889
- return;
2890
- }
2891
- if (!isBlockStatement(parent) && !isProgram(parent)) {
2892
- return;
2893
- }
2894
- const { body } = parent;
2895
- const index = body.indexOf(node);
2896
- const sibling = body[index - 1];
2897
- if (getExpressionText(sibling, sourceCode) !== getExpressionText(node, sourceCode)) {
2898
- return;
2899
- }
2900
- if (!isExpressionObserver(sibling, couldBeType2) || !isExpressionObserver(node, couldBeType2)) {
2901
- return;
2902
- }
2903
- const { expression } = node;
2904
- if (isCallExpression(expression)) {
2905
- const { callee } = expression;
2906
- if (isMemberExpression(callee)) {
2907
- const { property } = callee;
2908
- if (isIdentifier(property)) {
2909
- context.report({
2910
- messageId: "forbidden",
2911
- node: property
2912
- });
2913
- }
2914
- }
2915
- }
2916
- }
2917
- };
2918
- }
2919
- });
2920
- function getExpressionText(expressionStatement, sourceCode) {
2921
- if (!isCallExpression(expressionStatement.expression)) {
2922
- return void 0;
2923
- }
2924
- const callExpression = expressionStatement.expression;
2925
- if (!isMemberExpression(callExpression.callee)) {
2926
- return void 0;
2927
- }
2928
- const { object } = callExpression.callee;
2929
- return sourceCode.getText(object);
2930
- }
2931
- function isExpressionObserver(expressionStatement, couldBeType2) {
2932
- if (!isCallExpression(expressionStatement.expression)) {
2933
- return false;
2934
- }
2935
- const callExpression = expressionStatement.expression;
2936
- if (!isMemberExpression(callExpression.callee)) {
2937
- return false;
2938
- }
2939
- const { object } = callExpression.callee;
2940
- return couldBeType2(object, /^(Subject|Subscriber)$/);
2941
- }
2942
-
2943
- // src/rules/no-sharereplay.ts
2944
- import { AST_NODE_TYPES as AST_NODE_TYPES6 } from "@typescript-eslint/utils";
2945
- var defaultOptions10 = [];
2946
- var noSharereplayRule = ruleCreator({
2947
- defaultOptions: defaultOptions10,
2948
- meta: {
2949
- docs: {
2950
- description: "Disallow unsafe `shareReplay` usage.",
2951
- recommended: "recommended"
2952
- },
2953
- messages: {
2954
- forbidden: "shareReplay is forbidden.",
2955
- forbiddenWithoutConfig: "shareReplay is forbidden unless a config argument is passed."
2956
- },
2957
- schema: [
2958
- {
2959
- properties: {
2960
- allowConfig: { type: "boolean", description: "Allow shareReplay if a config argument is specified.", default: true }
2961
- },
2962
- type: "object"
2963
- }
2964
- ],
2965
- type: "problem"
2966
- },
2967
- name: "no-sharereplay",
2968
- create: (context) => {
2969
- const [config = {}] = context.options;
2970
- const { allowConfig = true } = config;
2971
- return {
2972
- "CallExpression[callee.name='shareReplay']": (node) => {
2973
- let report = true;
2974
- if (allowConfig) {
2975
- report = node.arguments.length !== 1 || node.arguments[0].type !== AST_NODE_TYPES6.ObjectExpression;
2976
- }
2977
- if (report) {
2978
- context.report({
2979
- messageId: allowConfig ? "forbiddenWithoutConfig" : "forbidden",
2980
- node: node.callee
2981
- });
2982
- }
2983
- }
2984
- };
2985
- }
2986
- });
2987
-
2988
- // src/rules/no-sharereplay-before-takeuntil.ts
2989
- var defaultOptions11 = [];
2990
- var noSharereplayBeforeTakeuntilRule = ruleCreator({
2991
- defaultOptions: defaultOptions11,
2992
- meta: {
2993
- docs: {
2994
- description: "Disallow using `shareReplay({ refCount: false })` before `takeUntil`.",
2995
- recommended: "strict"
2996
- },
2997
- messages: {
2998
- forbidden: "shareReplay before '{{takeUntilAlias}}' is forbidden unless 'refCount: true' is specified."
2999
- },
3000
- schema: [{
3001
- properties: {
3002
- takeUntilAlias: { type: "array", description: "List of operators to treat as takeUntil.", default: ["takeUntilDestroyed"] }
3003
- },
3004
- type: "object"
3005
- }],
3006
- type: "problem"
3007
- },
3008
- name: "no-sharereplay-before-takeuntil",
3009
- create: (context) => {
3010
- const [config = {}] = context.options;
3011
- const { takeUntilAlias = ["takeUntilDestroyed"] } = config;
3012
- function checkCallExpression(node) {
3013
- const pipeCallExpression = node.parent;
3014
- if (!pipeCallExpression.arguments || !isMemberExpression(pipeCallExpression.callee) || !isIdentifier(pipeCallExpression.callee.property) || pipeCallExpression.callee.property.name !== "pipe") {
3015
- return;
3016
- }
3017
- const allTakeUntilAlias = ["takeUntil", ...takeUntilAlias];
3018
- const takeUntilRegex = new RegExp(`^(${allTakeUntilAlias.join("|")})$`);
3019
- const { isOrderValid, operatorNode: takeUntilNode } = findIsLastOperatorOrderValid(
3020
- pipeCallExpression,
3021
- takeUntilRegex,
3022
- DEFAULT_VALID_POST_COMPLETION_OPERATORS
3023
- );
3024
- if (!isOrderValid || !takeUntilNode) {
3025
- return;
3026
- }
3027
- if (takeUntilNode.range[0] < node.range[0]) {
3028
- return;
3029
- }
3030
- const shareReplayConfig = node.arguments[0];
3031
- if (!shareReplayConfig || !isObjectExpression(shareReplayConfig)) {
3032
- context.report({
3033
- messageId: "forbidden",
3034
- data: { takeUntilAlias: isIdentifier(takeUntilNode) ? takeUntilNode.name : "takeUntil" },
3035
- node: node.callee
3036
- });
3037
- return;
3038
- }
3039
- const refCountElement = shareReplayConfig.properties.filter(isProperty).find((prop) => isIdentifier(prop.key) && prop.key.name === "refCount");
3040
- if (!refCountElement || isLiteral(refCountElement.value) && refCountElement.value.value === false) {
3041
- context.report({
3042
- messageId: "forbidden",
3043
- data: { takeUntilAlias: isIdentifier(takeUntilNode) ? takeUntilNode.name : "takeUntil" },
3044
- node: node.callee
3045
- });
3046
- }
3047
- }
3048
- return {
3049
- 'CallExpression[callee.name="shareReplay"]': (node) => {
3050
- checkCallExpression(node);
3051
- },
3052
- 'CallExpression[callee.property.name="shareReplay"]': (node) => {
3053
- checkCallExpression(node);
3054
- }
3055
- };
3056
- }
3057
- });
3058
-
3059
- // src/rules/no-subclass.ts
3060
- var noSubclassRule = ruleCreator({
3061
- defaultOptions: [],
3062
- meta: {
3063
- docs: {
3064
- description: "Disallow subclassing RxJS classes.",
3065
- recommended: "strict",
3066
- requiresTypeChecking: true
3067
- },
3068
- messages: {
3069
- forbidden: "Subclassing RxJS classes is forbidden."
3070
- },
3071
- schema: [],
3072
- type: "problem"
3073
- },
3074
- name: "no-subclass",
3075
- create: (context) => {
3076
- const { couldBeType: couldBeType2 } = getTypeServices(context);
3077
- const queryNames = [
3078
- "AsyncSubject",
3079
- "BehaviorSubject",
3080
- "Observable",
3081
- "ReplaySubject",
3082
- "Scheduler",
3083
- "Subject",
3084
- "Subscriber"
3085
- ];
3086
- return {
3087
- [`ClassDeclaration[superClass.name=/^(${queryNames.join(
3088
- "|"
3089
- )})$/] > Identifier.superClass`]: (node) => {
3090
- if (queryNames.some(
3091
- (name2) => couldBeType2(node, name2, { name: /[/\\]rxjs[/\\]/ })
3092
- )) {
3093
- context.report({
3094
- messageId: "forbidden",
3095
- node
3096
- });
3097
- }
3098
- }
3099
- };
3100
- }
3101
- });
3102
-
3103
- // src/rules/no-subject-unsubscribe.ts
3104
- var noSubjectUnsubscribeRule = ruleCreator({
3105
- defaultOptions: [],
3106
- meta: {
3107
- docs: {
3108
- description: "Disallow calling the `unsubscribe` method of subjects.",
3109
- recommended: "recommended",
3110
- requiresTypeChecking: true
3111
- },
3112
- messages: {
3113
- forbidden: "Calling unsubscribe on a subject is forbidden."
3114
- },
3115
- schema: [],
3116
- type: "problem"
3117
- },
3118
- name: "no-subject-unsubscribe",
3119
- create: (context) => {
3120
- const { couldBeSubject, couldBeSubscription } = getTypeServices(context);
3121
- return {
3122
- "MemberExpression[property.name='unsubscribe']": (node) => {
3123
- if (couldBeSubject(node.object)) {
3124
- context.report({
3125
- messageId: "forbidden",
3126
- node: node.property
3127
- });
3128
- }
3129
- },
3130
- "CallExpression[callee.property.name='add'][arguments.length > 0]": (node) => {
3131
- const memberExpression = node.callee;
3132
- if (couldBeSubscription(memberExpression.object)) {
3133
- const [arg] = node.arguments;
3134
- if (couldBeSubject(arg)) {
3135
- context.report({
3136
- messageId: "forbidden",
3137
- node: arg
3138
- });
3139
- }
3140
- }
3141
- }
3142
- };
3143
- }
3144
- });
3145
-
3146
- // src/rules/no-subject-value.ts
3147
- var noSubjectValueRule = ruleCreator({
3148
- defaultOptions: [],
3149
- meta: {
3150
- docs: {
3151
- description: "Disallow accessing the `value` property of a `BehaviorSubject` instance.",
3152
- requiresTypeChecking: true
3153
- },
3154
- messages: {
3155
- forbidden: "Accessing the value property of a BehaviorSubject is forbidden."
3156
- },
3157
- schema: [],
3158
- type: "problem"
3159
- },
3160
- name: "no-subject-value",
3161
- create: (context) => {
3162
- const { couldBeBehaviorSubject } = getTypeServices(context);
3163
- return {
3164
- "Identifier[name=/^(value|getValue)$/]": (node) => {
3165
- const parent = node.parent;
3166
- if (!parent || !("object" in parent)) {
3167
- return;
3168
- }
3169
- if (couldBeBehaviorSubject(parent.object)) {
3170
- context.report({
3171
- messageId: "forbidden",
3172
- node
3173
- });
3174
- }
3175
- }
3176
- };
3177
- }
3178
- });
3179
-
3180
- // src/rules/no-subscribe-handlers.ts
3181
- var noSubscribeHandlersRule = ruleCreator({
3182
- defaultOptions: [],
3183
- meta: {
3184
- docs: {
3185
- description: "Disallow passing handlers to `subscribe`.",
3186
- requiresTypeChecking: true
3187
- },
3188
- messages: {
3189
- forbidden: "Passing handlers to subscribe is forbidden."
3190
- },
3191
- schema: [],
3192
- type: "problem"
3193
- },
3194
- name: "no-subscribe-handlers",
3195
- create: (context) => {
3196
- const { couldBeObservable, couldBeType: couldBeType2 } = getTypeServices(context);
3197
- return {
3198
- "CallExpression[arguments.length > 0][callee.property.name='subscribe']": (node) => {
3199
- const callee = node.callee;
3200
- if (couldBeObservable(callee.object) || couldBeType2(callee.object, "Subscribable")) {
3201
- context.report({
3202
- messageId: "forbidden",
3203
- node: callee.property
3204
- });
3205
- }
3206
- }
3207
- };
3208
- }
3209
- });
3210
-
3211
- // src/rules/no-subscribe-in-pipe.ts
3212
- import { AST_NODE_TYPES as AST_NODE_TYPES7 } from "@typescript-eslint/utils";
3213
- var noSubscribeInPipeRule = ruleCreator({
3214
- defaultOptions: [],
3215
- meta: {
3216
- docs: {
3217
- description: "Disallow calling of `subscribe` within any RxJS operator inside a `pipe`.",
3218
- recommended: "recommended",
3219
- requiresTypeChecking: true
3220
- },
3221
- messages: {
3222
- forbidden: "Subscribe calls within pipe operators are forbidden."
3223
- },
3224
- schema: [],
3225
- type: "problem"
3226
- },
3227
- name: "no-subscribe-in-pipe",
3228
- create: (context) => {
3229
- const { couldBeObservable, couldBeType: couldBeType2 } = getTypeServices(context);
3230
- function isWithinPipe(node) {
3231
- let parent = node.parent;
3232
- while (parent) {
3233
- 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") {
3234
- return true;
3235
- }
3236
- parent = parent.parent;
3237
- }
3238
- return false;
3239
- }
3240
- return {
3241
- "CallExpression > MemberExpression[property.name='subscribe']": (node) => {
3242
- if (!couldBeObservable(node.object) && !couldBeType2(node.object, "Subscribable")) {
3243
- return;
3244
- }
3245
- if (isWithinPipe(node)) {
3246
- context.report({
3247
- messageId: "forbidden",
3248
- node: node.property
3249
- });
3250
- }
3251
- }
3252
- };
3253
- }
3254
- });
3255
-
3256
- // src/rules/no-tap.ts
3257
- var noTapRule = ruleCreator({
3258
- defaultOptions: [],
3259
- meta: {
3260
- deprecated: true,
3261
- docs: {
3262
- description: "Disallow the `tap` operator."
3263
- },
3264
- messages: {
3265
- forbidden: "The tap operator is forbidden."
3266
- },
3267
- replacedBy: ["ban-operators"],
3268
- schema: [],
3269
- type: "problem"
3270
- },
3271
- name: "no-tap",
3272
- create: (context) => {
3273
- return {
3274
- [String.raw`ImportDeclaration[source.value=/^rxjs(\u002foperators)?$/] > ImportSpecifier[imported.name='tap']`]: (node) => {
3275
- const { loc } = node;
3276
- context.report({
3277
- messageId: "forbidden",
3278
- loc: {
3279
- ...loc,
3280
- end: {
3281
- ...loc.start,
3282
- column: loc.start.column + 3
3283
- }
3284
- }
3285
- });
3286
- }
3287
- };
3288
- }
3289
- });
3290
-
3291
- // src/rules/no-topromise.ts
3292
- var noTopromiseRule = ruleCreator({
3293
- defaultOptions: [],
3294
- meta: {
3295
- docs: {
3296
- description: "Disallow use of the `toPromise` method.",
3297
- recommended: "recommended",
3298
- requiresTypeChecking: true
3299
- },
3300
- hasSuggestions: true,
3301
- messages: {
3302
- forbidden: "The toPromise method is forbidden.",
3303
- suggestLastValueFromWithDefault: "Use lastValueFrom(..., { defaultValue: undefined }) instead.",
3304
- suggestLastValueFrom: "Use lastValueFrom instead.",
3305
- suggestFirstValueFrom: "Use firstValueFrom instead."
3306
- },
3307
- schema: [],
3308
- type: "problem"
3309
- },
3310
- name: "no-topromise",
3311
- create: (context) => {
3312
- const { couldBeObservable } = getTypeServices(context);
3313
- function getQuote(raw) {
3314
- const match = /^\s*('|")/.exec(raw);
3315
- if (!match) {
3316
- return void 0;
3317
- }
3318
- const [, quote] = match;
3319
- return quote;
3320
- }
3321
- function createFix(conversion, callExpression, observableNode, importDeclarations, { withDefault } = {}) {
3322
- return function* fix(fixer) {
3323
- var _a, _b, _c;
3324
- let namespace = "";
3325
- let functionName = conversion;
3326
- const rxjsImportDeclaration = importDeclarations.find((node) => node.source.value === "rxjs");
3327
- if ((_a = rxjsImportDeclaration == null ? void 0 : rxjsImportDeclaration.specifiers) == null ? void 0 : _a.every(isImportNamespaceSpecifier)) {
3328
- namespace = rxjsImportDeclaration.specifiers[0].local.name + ".";
3329
- } else if ((_b = rxjsImportDeclaration == null ? void 0 : rxjsImportDeclaration.specifiers) == null ? void 0 : _b.every(isImportSpecifier)) {
3330
- const { specifiers } = rxjsImportDeclaration;
3331
- const existingSpecifier = specifiers.find((node) => (isIdentifier(node.imported) ? node.imported.name : node.imported.value) === functionName);
3332
- if (existingSpecifier) {
3333
- functionName = existingSpecifier.local.name;
3334
- } else {
3335
- const lastSpecifier = specifiers[specifiers.length - 1];
3336
- yield fixer.insertTextAfter(lastSpecifier, `, ${functionName}`);
3337
- }
3338
- } else if (importDeclarations.length) {
3339
- const lastImport = importDeclarations[importDeclarations.length - 1];
3340
- const quote = (_c = getQuote(lastImport.source.raw)) != null ? _c : '"';
3341
- yield fixer.insertTextAfter(
3342
- importDeclarations[importDeclarations.length - 1],
3343
- `
3344
- import { ${functionName} } from ${quote}rxjs${quote};`
3345
- );
3346
- } else {
3347
- console.warn("No import declarations found. Unable to suggest a fix.");
3348
- return;
3349
- }
3350
- yield fixer.replaceText(
3351
- callExpression,
3352
- `${namespace}${functionName}(${context.sourceCode.getText(observableNode)}${withDefault ? ", { defaultValue: undefined }" : ""})`
3353
- );
3354
- };
3355
- }
3356
- return {
3357
- [`CallExpression[callee.property.name="toPromise"]`]: (node) => {
3358
- const memberExpression = node.callee;
3359
- if (!couldBeObservable(memberExpression.object)) {
3360
- return;
3361
- }
3362
- const { body } = context.sourceCode.ast;
3363
- const importDeclarations = body.filter(isImportDeclaration);
3364
- if (!importDeclarations.length) {
3365
- return;
3366
- }
3367
- context.report({
3368
- messageId: "forbidden",
3369
- node: memberExpression.property,
3370
- suggest: [
3371
- {
3372
- messageId: "suggestLastValueFromWithDefault",
3373
- fix: createFix("lastValueFrom", node, memberExpression.object, importDeclarations, { withDefault: true })
3374
- },
3375
- {
3376
- messageId: "suggestLastValueFrom",
3377
- fix: createFix("lastValueFrom", node, memberExpression.object, importDeclarations)
3378
- },
3379
- {
3380
- messageId: "suggestFirstValueFrom",
3381
- fix: createFix("firstValueFrom", node, memberExpression.object, importDeclarations)
3382
- }
3383
- ]
3384
- });
3385
- }
3386
- };
3387
- }
3388
- });
3389
-
3390
- // src/rules/no-unbound-methods.ts
3391
- import { ESLintUtils as ESLintUtils10 } from "@typescript-eslint/utils";
3392
- var defaultOptions12 = [];
3393
- var noUnboundMethodsRule = ruleCreator({
3394
- defaultOptions: defaultOptions12,
3395
- meta: {
3396
- docs: {
3397
- description: "Disallow passing unbound methods.",
3398
- recommended: "recommended",
3399
- requiresTypeChecking: true
3400
- },
3401
- messages: {
3402
- forbidden: "Unbound methods are forbidden."
3403
- },
3404
- schema: [
3405
- {
3406
- properties: {
3407
- allowTypes: { type: "array", items: { type: "string" }, description: "An array of function types that are allowed to be passed unbound.", default: DEFAULT_UNBOUND_ALLOWED_TYPES }
3408
- },
3409
- type: "object"
3410
- }
3411
- ],
3412
- type: "problem"
3413
- },
3414
- name: "no-unbound-methods",
3415
- create: (context) => {
3416
- const { getTypeAtLocation } = ESLintUtils10.getParserServices(context);
3417
- const { couldBeObservable, couldBeSubscription } = getTypeServices(context);
3418
- const nodeMap = /* @__PURE__ */ new WeakMap();
3419
- const [config = {}] = context.options;
3420
- const { allowTypes = DEFAULT_UNBOUND_ALLOWED_TYPES } = config;
3421
- function mapArguments(node) {
3422
- node.arguments.filter(isMemberExpression).forEach((arg) => {
3423
- const argType = getTypeAtLocation(arg);
3424
- if (allowTypes.some((t) => couldBeType(argType, t))) {
3425
- return;
3426
- }
3427
- if (argType.getCallSignatures().length > 0) {
3428
- nodeMap.set(arg);
3429
- }
3430
- });
3431
- }
3432
- function isObservableOrSubscription(node, action) {
3433
- if (!isMemberExpression(node.callee)) {
3434
- return;
3435
- }
3436
- if (couldBeObservable(node.callee.object) || couldBeSubscription(node.callee.object)) {
3437
- action(node);
3438
- }
3439
- }
3440
- return {
3441
- "CallExpression[callee.property.name='pipe']": (node) => {
3442
- isObservableOrSubscription(node, ({ arguments: args }) => {
3443
- args.filter(isCallExpression).forEach(mapArguments);
3444
- });
3445
- },
3446
- "CallExpression[callee.property.name=/^(add|subscribe)$/]": (node) => {
3447
- isObservableOrSubscription(node, mapArguments);
3448
- },
3449
- "NewExpression[callee.name='Subscription']": mapArguments,
3450
- "ThisExpression": (node) => {
3451
- let parent = node.parent;
3452
- while (parent) {
3453
- if (nodeMap.has(parent)) {
3454
- context.report({
3455
- messageId: "forbidden",
3456
- node: parent
3457
- });
3458
- return;
3459
- }
3460
- parent = parent.parent;
3461
- }
3462
- }
3463
- };
3464
- }
3465
- });
3466
-
3467
- // src/rules/no-unnecessary-collection.ts
3468
- var noUnnecessaryCollectionRule = ruleCreator({
3469
- defaultOptions: [],
3470
- meta: {
3471
- docs: {
3472
- description: "Disallow unnecessary usage of collection arguments with single values.",
3473
- recommended: "strict",
3474
- requiresTypeChecking: false
3475
- },
3476
- messages: {
3477
- forbidden: "Unnecessary {{operator}} with {{inputType}}. Use the observable directly instead."
3478
- },
3479
- schema: [],
3480
- type: "suggestion"
3481
- },
3482
- name: "no-unnecessary-collection",
3483
- create: (context) => {
3484
- const { couldBeType: couldBeType2, couldBeObservable } = getTypeServices(context);
3485
- function couldBeFromRxjs(node, operatorName) {
3486
- return couldBeType2(node, operatorName, { name: /[/\\]rxjs[/\\]/ });
3487
- }
3488
- function checkCallExpression(node, operatorName) {
3489
- const args = node.arguments;
3490
- if (args.length === 0) {
3491
- return;
3492
- }
3493
- const firstArg = args[0];
3494
- if (isArrayExpression(firstArg)) {
3495
- const nonNullElements = firstArg.elements.filter((element) => element !== null);
3496
- if (nonNullElements.length === 1 && couldBeObservable(nonNullElements[0])) {
3497
- context.report({
3498
- messageId: "forbidden",
3499
- node: node.callee,
3500
- data: {
3501
- operator: operatorName,
3502
- inputType: "single-valued array"
3503
- }
3504
- });
3505
- }
3506
- return;
3507
- }
3508
- if (isObjectExpression(firstArg) && SOURCES_OBJECT_ACCEPTING_STATIC_OBSERVABLE_CREATORS.includes(operatorName)) {
3509
- if (firstArg.properties.length === 1 && isProperty(firstArg.properties[0])) {
3510
- const property = firstArg.properties[0];
3511
- if (property.value && couldBeObservable(property.value)) {
3512
- context.report({
3513
- messageId: "forbidden",
3514
- node: node.callee,
3515
- data: {
3516
- operator: operatorName,
3517
- inputType: "single-property object"
3518
- }
3519
- });
3520
- }
3521
- }
3522
- return;
3523
- }
3524
- if (args.length === 1 && !isSpreadElement(firstArg) && couldBeObservable(firstArg)) {
3525
- context.report({
3526
- messageId: "forbidden",
3527
- node: node.callee,
3528
- data: {
3529
- operator: operatorName,
3530
- inputType: "single argument"
3531
- }
3532
- });
3533
- }
3534
- }
3535
- const callExpressionVisitors = {};
3536
- for (const operator of MULTIPLE_OBSERVABLE_ACCEPTING_STATIC_OBSERVABLE_CREATORS) {
3537
- callExpressionVisitors[`CallExpression[callee.name="${operator}"]`] = (node) => {
3538
- if (couldBeFromRxjs(node.callee, operator)) {
3539
- checkCallExpression(node, operator);
3540
- }
3541
- };
3542
- }
3543
- for (const operator of MULTIPLE_OBSERVABLE_ACCEPTING_STATIC_OBSERVABLE_CREATORS) {
3544
- callExpressionVisitors[`CallExpression[callee.type="MemberExpression"][callee.property.name="${operator}"]`] = (node) => {
3545
- const memberExpr = node.callee;
3546
- if (couldBeFromRxjs(memberExpr.property, operator)) {
3547
- checkCallExpression(node, operator);
3548
- }
3549
- };
3550
- }
3551
- return callExpressionVisitors;
3552
- }
3553
- });
3554
-
3555
- // src/rules/no-unsafe-catch.ts
3556
- import { stripIndent as stripIndent5 } from "common-tags";
3557
- var defaultOptions13 = [];
3558
- var noUnsafeCatchRule = ruleCreator({
3559
- defaultOptions: defaultOptions13,
3560
- meta: {
3561
- docs: {
3562
- description: "Disallow unsafe `catchError` usage in effects and epics.",
3563
- requiresTypeChecking: true
3564
- },
3565
- messages: {
3566
- forbidden: "Unsafe catchError usage in effects and epics are forbidden."
3567
- },
3568
- schema: [
3569
- {
3570
- properties: {
3571
- observable: { type: "string", description: "A RegExp that matches an effect or epic's actions observable.", default: defaultObservable }
3572
- },
3573
- type: "object",
3574
- description: stripIndent5`
3575
- An optional object with an optional \`observable\` property.
3576
- 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.`
3577
- }
3578
- ],
3579
- type: "problem"
3580
- },
3581
- name: "no-unsafe-catch",
3582
- create: (context) => {
3583
- const invalidOperatorsRegExp = /^(catchError)$/;
3584
- const [config = {}] = context.options;
3585
- const { observable = defaultObservable } = config;
3586
- const observableRegExp = new RegExp(observable);
3587
- const { couldBeObservable } = getTypeServices(context);
3588
- function isUnsafe([arg]) {
3589
- if (arg && (isFunctionDeclaration(arg) || isArrowFunctionExpression(arg))) {
3590
- return arg.params.length < 2;
3591
- }
3592
- return false;
3593
- }
3594
- function checkNode(node) {
3595
- if (!node.arguments || !couldBeObservable(node)) {
3596
- return;
3597
- }
3598
- node.arguments.forEach((arg) => {
3599
- if (isCallExpression(arg) && isIdentifier(arg.callee)) {
3600
- if (invalidOperatorsRegExp.test(arg.callee.name) && isUnsafe(arg.arguments)) {
3601
- context.report({
3602
- messageId: "forbidden",
3603
- node: arg.callee
3604
- });
3605
- }
3606
- }
3607
- });
3608
- }
3609
- return {
3610
- [`CallExpression[callee.property.name='pipe'][callee.object.name=${observableRegExp}]`]: checkNode,
3611
- [`CallExpression[callee.property.name='pipe'][callee.object.property.name=${observableRegExp}]`]: checkNode
3612
- };
3613
- }
3614
- });
3615
-
3616
- // src/rules/no-unsafe-first.ts
3617
- import { stripIndent as stripIndent6 } from "common-tags";
3618
- var defaultOptions14 = [];
3619
- var noUnsafeFirstRule = ruleCreator({
3620
- defaultOptions: defaultOptions14,
3621
- meta: {
3622
- docs: {
3623
- description: "Disallow unsafe `first`/`take` usage in effects and epics.",
3624
- requiresTypeChecking: true
3625
- },
3626
- messages: {
3627
- forbidden: "Unsafe first and take usage in effects and epics are forbidden."
3628
- },
3629
- schema: [
3630
- {
3631
- properties: {
3632
- observable: { type: "string", description: "A RegExp that matches an effect or epic's actions observable.", default: defaultObservable }
3633
- },
3634
- type: "object",
3635
- description: stripIndent6`
3636
- An optional object with an optional \`observable\` property.
3637
- 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.`
3638
- }
3639
- ],
3640
- type: "problem"
3641
- },
3642
- name: "no-unsafe-first",
3643
- create: (context) => {
3644
- const invalidOperatorsRegExp = /^(take|first)$/;
3645
- const [config = {}] = context.options;
3646
- const { observable = defaultObservable } = config;
3647
- const observableRegExp = new RegExp(observable);
3648
- const { couldBeObservable } = getTypeServices(context);
3649
- const nodes = [];
3650
- function checkNode(node) {
3651
- if (!node.arguments || !couldBeObservable(node)) {
3652
- return;
3653
- }
3654
- node.arguments.forEach((arg) => {
3655
- if (isCallExpression(arg) && isIdentifier(arg.callee)) {
3656
- if (invalidOperatorsRegExp.test(arg.callee.name)) {
3657
- context.report({
3658
- messageId: "forbidden",
3659
- node: arg.callee
3660
- });
3661
- }
3662
- }
3663
- });
3664
- }
3665
- return {
3666
- [`CallExpression[callee.property.name='pipe'][callee.object.name=${observableRegExp}]`]: (node) => {
3667
- if (nodes.push(node) === 1) {
3668
- checkNode(node);
3669
- }
3670
- },
3671
- [`CallExpression[callee.property.name='pipe'][callee.object.name=${observableRegExp}]:exit`]: () => {
3672
- nodes.pop();
3673
- },
3674
- [`CallExpression[callee.property.name='pipe'][callee.object.property.name=${observableRegExp}]`]: (node) => {
3675
- if (nodes.push(node) === 1) {
3676
- checkNode(node);
3677
- }
3678
- },
3679
- [`CallExpression[callee.property.name='pipe'][callee.object.property.name=${observableRegExp}]:exit`]: () => {
3680
- nodes.pop();
3681
- }
3682
- };
3683
- }
3684
- });
3685
-
3686
- // src/rules/no-unsafe-subject-next.ts
3687
- import { ESLintUtils as ESLintUtils11 } from "@typescript-eslint/utils";
3688
- import * as tsutils5 from "ts-api-utils";
3689
- import ts6 from "typescript";
3690
- var noUnsafeSubjectNext = ruleCreator({
3691
- defaultOptions: [],
3692
- meta: {
3693
- docs: {
3694
- description: "Disallow unsafe optional `next` calls.",
3695
- recommended: "recommended",
3696
- requiresTypeChecking: true
3697
- },
3698
- messages: {
3699
- forbidden: "Unsafe optional next calls are forbidden."
3700
- },
3701
- schema: [],
3702
- type: "problem"
3703
- },
3704
- name: "no-unsafe-subject-next",
3705
- create: (context) => {
3706
- const { getTypeAtLocation, program } = ESLintUtils11.getParserServices(context);
3707
- const typeChecker = program.getTypeChecker();
3708
- return {
3709
- [`CallExpression[callee.property.name='next']`]: (node) => {
3710
- if (node.arguments.length === 0 && isMemberExpression(node.callee)) {
3711
- const type = getTypeAtLocation(node.callee.object);
3712
- if (tsutils5.isTypeReference(type) && couldBeType(type, "Subject")) {
3713
- const [typeArg] = typeChecker.getTypeArguments(type);
3714
- if (tsutils5.isTypeFlagSet(typeArg, ts6.TypeFlags.Any)) {
3715
- return;
3716
- }
3717
- if (tsutils5.isTypeFlagSet(typeArg, ts6.TypeFlags.Unknown)) {
3718
- return;
3719
- }
3720
- if (tsutils5.isTypeFlagSet(typeArg, ts6.TypeFlags.Void)) {
3721
- return;
3722
- }
3723
- if (tsutils5.isUnionType(typeArg) && typeArg.types.some(
3724
- (t) => tsutils5.isTypeFlagSet(t, ts6.TypeFlags.Void)
3725
- )) {
3726
- return;
3727
- }
3728
- context.report({
3729
- messageId: "forbidden",
3730
- node: node.callee.property
3731
- });
3732
- }
3733
- }
3734
- }
3735
- };
3736
- }
3737
- });
3738
-
3739
- // src/rules/no-unsafe-switchmap.ts
3740
- import { stripIndent as stripIndent7 } from "common-tags";
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
- ];
3752
- var defaultOptions15 = [];
3753
- var noUnsafeSwitchmapRule = ruleCreator({
3754
- defaultOptions: defaultOptions15,
3755
- meta: {
3756
- docs: {
3757
- description: "Disallow unsafe `switchMap` usage in effects and epics.",
3758
- requiresTypeChecking: true
3759
- },
3760
- messages: {
3761
- forbidden: "Unsafe switchMap usage in effects and epics is forbidden."
3762
- },
3763
- schema: [
3764
- {
3765
- properties: {
3766
- allow: {
3767
- description: "Action types that are allowed to be used with switchMap. Mutually exclusive with `disallow`.",
3768
- oneOf: [
3769
- { type: "string", description: "A regular expression string." },
3770
- { type: "array", items: { type: "string" }, description: "An array of words." }
3771
- ]
3772
- },
3773
- disallow: {
3774
- description: "Action types that are disallowed to be used with switchMap. Mutually exclusive with `allow`.",
3775
- oneOf: [
3776
- { type: "string", description: "A regular expression string." },
3777
- { type: "array", items: { type: "string" }, description: "An array of words." }
3778
- ],
3779
- default: DEFAULT_DISALLOW
3780
- },
3781
- observable: {
3782
- type: "string",
3783
- description: "A RegExp that matches an effect or epic's actions observable.",
3784
- default: defaultObservable
3785
- }
3786
- },
3787
- type: "object",
3788
- description: stripIndent7`
3789
- An optional object with optional \`allow\`, \`disallow\` and \`observable\` properties.
3790
- The properties can be specified as regular expression strings or as arrays of words.
3791
- The \`allow\` or \`disallow\` properties are mutually exclusive. Whether or not
3792
- \`switchMap\` is allowed will depend upon the matching of action types with \`allow\` or \`disallow\`.
3793
- The \`observable\` property is used to identify the action observables from which effects and epics are composed.
3794
- `
3795
- }
3796
- ],
3797
- type: "problem"
3798
- },
3799
- name: "no-unsafe-switchmap",
3800
- create: (context) => {
3801
- var _a, _b, _c;
3802
- let allowRegExp = void 0;
3803
- let disallowRegExp = void 0;
3804
- const [config = {}] = context.options;
3805
- if (config.allow) {
3806
- allowRegExp = createRegExpForWords((_a = config.allow) != null ? _a : []);
3807
- } else {
3808
- disallowRegExp = createRegExpForWords((_b = config.disallow) != null ? _b : DEFAULT_DISALLOW);
3809
- }
3810
- const observableRegExp = new RegExp((_c = config.observable) != null ? _c : defaultObservable);
3811
- const { couldBeObservable } = getTypeServices(context);
3812
- function shouldDisallow(args) {
3813
- const names = args.map((arg) => {
3814
- if (isLiteral(arg) && typeof arg.value === "string") {
3815
- return arg.value;
3816
- }
3817
- if (isIdentifier(arg)) {
3818
- return arg.name;
3819
- }
3820
- if (isMemberExpression(arg) && isIdentifier(arg.property)) {
3821
- return arg.property.name;
3822
- }
3823
- return "";
3824
- }).map((name2) => decamelize(name2));
3825
- if (allowRegExp) {
3826
- return !names.every((name2) => allowRegExp == null ? void 0 : allowRegExp.test(name2));
3827
- }
3828
- if (disallowRegExp) {
3829
- return names.some((name2) => disallowRegExp == null ? void 0 : disallowRegExp.test(name2));
3830
- }
3831
- return false;
3832
- }
3833
- function checkNode(node) {
3834
- if (!node.arguments || !couldBeObservable(node)) {
3835
- return;
3836
- }
3837
- const hasUnsafeOfType = node.arguments.some((arg) => {
3838
- if (isCallExpression(arg) && isIdentifier(arg.callee) && arg.callee.name === "ofType") {
3839
- return shouldDisallow(arg.arguments);
3840
- }
3841
- return false;
3842
- });
3843
- if (!hasUnsafeOfType) {
3844
- return;
3845
- }
3846
- node.arguments.forEach((arg) => {
3847
- if (isCallExpression(arg) && isIdentifier(arg.callee) && arg.callee.name === "switchMap") {
3848
- context.report({
3849
- messageId: "forbidden",
3850
- node: arg.callee
3851
- });
3852
- }
3853
- });
3854
- }
3855
- return {
3856
- [`CallExpression[callee.property.name='pipe'][callee.object.name=${observableRegExp}]`]: checkNode,
3857
- [`CallExpression[callee.property.name='pipe'][callee.object.property.name=${observableRegExp}]`]: checkNode
3858
- };
3859
- }
3860
- });
3861
-
3862
- // src/rules/no-unsafe-takeuntil.ts
3863
- import { stripIndent as stripIndent8 } from "common-tags";
3864
- var defaultOptions16 = [];
3865
- var noUnsafeTakeuntilRule = ruleCreator({
3866
- defaultOptions: defaultOptions16,
3867
- meta: {
3868
- docs: {
3869
- description: "Disallow applying operators after `takeUntil`.",
3870
- recommended: "recommended",
3871
- requiresTypeChecking: true
3872
- },
3873
- messages: {
3874
- forbidden: "Applying operators after takeUntil is forbidden."
3875
- },
3876
- schema: [
3877
- {
3878
- properties: {
3879
- alias: { type: "array", items: { type: "string" }, description: "An array of operator names that should be treated similarly to `takeUntil`." },
3880
- allow: { type: "array", items: { type: "string" }, description: "An array of operator names that are allowed to follow `takeUntil`.", default: DEFAULT_VALID_POST_COMPLETION_OPERATORS }
3881
- },
3882
- type: "object",
3883
- description: stripIndent8`
3884
- An optional object with optional \`alias\` and \`allow\` properties.
3885
- The \`alias\` property is an array containing the names of operators that aliases for \`takeUntil\`.
3886
- The \`allow\` property is an array containing the names of the operators that are allowed to follow \`takeUntil\`.`
3887
- }
3888
- ],
3889
- type: "problem"
3890
- },
3891
- name: "no-unsafe-takeuntil",
3892
- create: (context) => {
3893
- let checkedOperatorsRegExp = /^takeUntil$/;
3894
- const [config = {}] = context.options;
3895
- const { alias, allow = DEFAULT_VALID_POST_COMPLETION_OPERATORS } = config;
3896
- if (alias) {
3897
- checkedOperatorsRegExp = new RegExp(
3898
- `^(${alias.concat("takeUntil").join("|")})$`
3899
- );
3900
- }
3901
- const { couldBeObservable } = getTypeServices(context);
3902
- function checkNode(node) {
3903
- const pipeCallExpression = node.parent;
3904
- if (!pipeCallExpression.arguments || !couldBeObservable(pipeCallExpression)) {
3905
- return;
3906
- }
3907
- const { isOrderValid, operatorNode } = findIsLastOperatorOrderValid(
3908
- pipeCallExpression,
3909
- checkedOperatorsRegExp,
3910
- allow
3911
- );
3912
- if (!isOrderValid && operatorNode) {
3913
- context.report({
3914
- messageId: "forbidden",
3915
- node: operatorNode
3916
- });
3917
- }
3918
- }
3919
- return {
3920
- [`CallExpression[callee.property.name='pipe'] > CallExpression[callee.name=${checkedOperatorsRegExp}]`]: checkNode,
3921
- [`CallExpression[callee.property.name='pipe'] > CallExpression[callee.property.name=${checkedOperatorsRegExp}]`]: checkNode
3922
- };
3923
- }
3924
- });
3925
-
3926
- // src/rules/prefer-observer.ts
3927
- var defaultOptions17 = [];
3928
- var preferObserverRule = ruleCreator({
3929
- defaultOptions: defaultOptions17,
3930
- meta: {
3931
- docs: {
3932
- description: "Disallow passing separate handlers to `subscribe` and `tap`.",
3933
- recommended: "recommended",
3934
- requiresTypeChecking: true
3935
- },
3936
- fixable: "code",
3937
- hasSuggestions: true,
3938
- messages: {
3939
- forbidden: "Passing separate handlers is forbidden; pass an observer instead.",
3940
- suggest: "Replace with observer object."
3941
- },
3942
- schema: [
3943
- {
3944
- properties: {
3945
- allowNext: { type: "boolean", description: "Allows a single `next` callback.", default: true }
3946
- },
3947
- type: "object"
3948
- }
3949
- ],
3950
- type: "problem"
3951
- },
3952
- name: "prefer-observer",
3953
- create: (context) => {
3954
- const { couldBeFunction: couldBeFunction2, couldBeObservable } = getTypeServices(context);
3955
- const [config = {}] = context.options;
3956
- const { allowNext = true } = config;
3957
- function checkArgs(callExpression, reportNode) {
3958
- const { arguments: args, callee } = callExpression;
3959
- if (isMemberExpression(callee) && !couldBeObservable(callee.object)) {
3960
- return;
3961
- }
3962
- function* fix(fixer) {
3963
- const sourceCode = context.sourceCode;
3964
- const [nextArg, errorArg, completeArg] = args;
3965
- const nextArgText = nextArg ? sourceCode.getText(nextArg) : "";
3966
- const errorArgText = errorArg ? sourceCode.getText(errorArg) : "";
3967
- const completeArgText = completeArg ? sourceCode.getText(completeArg) : "";
3968
- let observer = "{";
3969
- if (nextArgText && nextArgText !== "undefined" && nextArgText !== "null") {
3970
- observer += ` next: ${nextArgText}${isValidArgText(errorArgText) || isValidArgText(completeArgText) ? "," : ""}`;
3971
- }
3972
- if (errorArgText && errorArgText !== "undefined" && errorArgText !== "null") {
3973
- observer += ` error: ${errorArgText}${isValidArgText(completeArgText) ? "," : ""}`;
3974
- }
3975
- if (completeArgText && completeArgText !== "undefined" && completeArgText !== "null") {
3976
- observer += ` complete: ${completeArgText}`;
3977
- }
3978
- observer += " }";
3979
- yield fixer.replaceText(callExpression.arguments[0], observer);
3980
- const [, start] = callExpression.arguments[0].range;
3981
- const [, end] = callExpression.arguments[callExpression.arguments.length - 1].range;
3982
- yield fixer.removeRange([start, end]);
3983
- }
3984
- if (args.length > 1) {
3985
- context.report({
3986
- messageId: "forbidden",
3987
- node: reportNode,
3988
- fix,
3989
- suggest: [
3990
- {
3991
- messageId: "suggest",
3992
- fix
3993
- }
3994
- ]
3995
- });
3996
- } else if (args.length === 1 && !allowNext) {
3997
- const [arg] = args;
3998
- if (isArrowFunctionExpression(arg) || isFunctionExpression(arg) || couldBeFunction2(arg)) {
3999
- context.report({
4000
- messageId: "forbidden",
4001
- node: reportNode,
4002
- fix,
4003
- suggest: [
4004
- {
4005
- messageId: "suggest",
4006
- fix
4007
- }
4008
- ]
4009
- });
4010
- }
4011
- }
4012
- }
4013
- return {
4014
- "CallExpression[callee.property.name='pipe'] > CallExpression[callee.name='tap']": (node) => {
4015
- checkArgs(node, node.callee);
4016
- },
4017
- "CallExpression[callee.property.name='subscribe']": (node) => {
4018
- checkArgs(node, node.callee.property);
4019
- }
4020
- };
4021
- }
4022
- });
4023
- function isValidArgText(argText) {
4024
- return argText && argText !== "undefined" && argText !== "null";
4025
- }
4026
-
4027
- // src/rules/prefer-root-operators.ts
4028
- var RENAMED_OPERATORS = {
4029
- combineLatest: "combineLatestWith",
4030
- concat: "concatWith",
4031
- merge: "mergeWith",
4032
- onErrorResumeNext: "onErrorResumeNextWith",
4033
- race: "raceWith",
4034
- zip: "zipWith"
4035
- };
4036
- var DEPRECATED_OPERATORS = [
4037
- "partition"
4038
- ];
4039
- var preferRootOperatorsRule = ruleCreator({
4040
- defaultOptions: [],
4041
- meta: {
4042
- docs: {
4043
- description: "Disallow importing operators from `rxjs/operators`.",
4044
- recommended: "recommended"
4045
- },
4046
- fixable: "code",
4047
- hasSuggestions: true,
4048
- messages: {
4049
- forbidden: "RxJS imports from `rxjs/operators` are forbidden; import from `rxjs` instead.",
4050
- forbiddenWithoutFix: "RxJS imports from `rxjs/operators` are forbidden; import from `rxjs` instead. Note some operators may have been renamed or deprecated.",
4051
- suggest: "Replace with import from `rxjs`."
4052
- },
4053
- schema: [],
4054
- type: "suggestion"
4055
- },
4056
- name: "prefer-root-operators",
4057
- create: (context) => {
4058
- function getQuote(raw) {
4059
- const match = /^\s*('|")/.exec(raw);
4060
- if (!match) {
4061
- return void 0;
4062
- }
4063
- const [, quote] = match;
4064
- return quote;
4065
- }
4066
- function getSourceReplacement(rawLocation) {
4067
- const quote = getQuote(rawLocation);
4068
- if (!quote) {
4069
- return void 0;
4070
- }
4071
- if (/^['"]rxjs\/operators/.test(rawLocation)) {
4072
- return `${quote}rxjs${quote}`;
4073
- }
4074
- return void 0;
4075
- }
4076
- function hasDeprecatedOperators(specifiers) {
4077
- return !!(specifiers == null ? void 0 : specifiers.some((s) => DEPRECATED_OPERATORS.includes(getName(getOperatorNode(s)))));
4078
- }
4079
- function getName(node) {
4080
- return isIdentifier(node) ? node.name : node.value;
4081
- }
4082
- function getOperatorNode(node) {
4083
- return isImportSpecifier(node) ? node.imported : node.local;
4084
- }
4085
- function getAliasNode(node) {
4086
- return isImportSpecifier(node) ? node.local : node.exported;
4087
- }
4088
- function getOperatorReplacement(name2) {
4089
- return RENAMED_OPERATORS[name2];
4090
- }
4091
- function isNodesEqual(a, b) {
4092
- return a.range[0] === b.range[0] && a.range[1] === b.range[1];
4093
- }
4094
- function createFix(source, replacement, specifiers) {
4095
- return function* fix(fixer) {
4096
- yield fixer.replaceText(source, replacement);
4097
- for (const specifier of specifiers) {
4098
- const operatorNode = getOperatorNode(specifier);
4099
- const operatorName = getName(operatorNode);
4100
- const operatorReplacement = getOperatorReplacement(operatorName);
4101
- if (!operatorReplacement) {
4102
- continue;
4103
- }
4104
- const aliasNode = getAliasNode(specifier);
4105
- if (isNodesEqual(aliasNode, operatorNode)) {
4106
- yield fixer.insertTextBefore(operatorNode, operatorReplacement + " as ");
4107
- } else if (isIdentifier(operatorNode)) {
4108
- yield fixer.replaceText(operatorNode, operatorReplacement);
4109
- } else {
4110
- const quote = getQuote(operatorNode.raw);
4111
- if (!quote) {
4112
- continue;
4113
- }
4114
- yield fixer.replaceText(operatorNode, quote + operatorReplacement + quote);
4115
- }
4116
- }
4117
- };
4118
- }
4119
- function reportNode(source, specifiers) {
4120
- const replacement = getSourceReplacement(source.raw);
4121
- if (!replacement || hasDeprecatedOperators(specifiers)) {
4122
- context.report({
4123
- messageId: "forbiddenWithoutFix",
4124
- node: source
4125
- });
4126
- return;
4127
- }
4128
- if (!specifiers) {
4129
- context.report({
4130
- messageId: "forbiddenWithoutFix",
4131
- node: source,
4132
- suggest: [{ messageId: "suggest", fix: (fixer) => fixer.replaceText(source, replacement) }]
4133
- });
4134
- return;
4135
- }
4136
- const fix = createFix(source, replacement, specifiers);
4137
- context.report({
4138
- fix,
4139
- messageId: "forbidden",
4140
- node: source,
4141
- suggest: [{ messageId: "suggest", fix }]
4142
- });
4143
- }
4144
- return {
4145
- 'ImportDeclaration[source.value="rxjs/operators"]': (node) => {
4146
- const specifiers = node.specifiers.length && node.specifiers.every((importClause) => isImportSpecifier(importClause)) ? node.specifiers : void 0;
4147
- reportNode(node.source, specifiers);
4148
- },
4149
- 'ImportExpression[source.value="rxjs/operators"]': (node) => {
4150
- if (isLiteral(node.source)) {
4151
- reportNode(node.source);
4152
- }
4153
- },
4154
- 'ExportNamedDeclaration[source.value="rxjs/operators"]': (node) => {
4155
- reportNode(node.source, node.specifiers);
4156
- },
4157
- 'ExportAllDeclaration[source.value="rxjs/operators"]': (node) => {
4158
- reportNode(node.source);
4159
- }
4160
- };
4161
- }
4162
- });
4163
-
4164
- // src/rules/suffix-subjects.ts
4165
- import { ESLintUtils as ESLintUtils12 } from "@typescript-eslint/utils";
4166
- var defaultOptions18 = [];
4167
- var baseShouldHaveSuffix = 'Subject identifiers must end with "{{suffix}}".';
4168
- var suffixSubjectsRule = ruleCreator({
4169
- defaultOptions: defaultOptions18,
4170
- meta: {
4171
- docs: {
4172
- description: "Enforce the use of a suffix in subject identifiers.",
4173
- requiresTypeChecking: true
4174
- },
4175
- messages: {
4176
- forbidden: baseShouldHaveSuffix,
4177
- forbiddenProperty: `${baseShouldHaveSuffix} Add a type annotation, assertion, or 'satisfies' to silence this rule.`
4178
- },
4179
- schema: [
4180
- {
4181
- properties: {
4182
- parameters: { type: "boolean", description: "Require for parameters." },
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." },
4185
- suffix: { type: "string", description: "The suffix to enforce." },
4186
- types: { type: "object", description: "Enforce for specific types. Keys are a RegExp, values are a boolean." },
4187
- variables: { type: "boolean", description: "Require for variables." }
4188
- },
4189
- type: "object"
4190
- }
4191
- ],
4192
- type: "problem"
4193
- },
4194
- name: "suffix-subjects",
4195
- create: (context) => {
4196
- const { esTreeNodeToTSNodeMap } = ESLintUtils12.getParserServices(context);
4197
- const { couldBeType: couldBeType2 } = getTypeServices(context);
4198
- const [config = {}] = context.options;
4199
- const validate = {
4200
- parameters: true,
4201
- properties: true,
4202
- objects: true,
4203
- variables: true,
4204
- ...config
4205
- };
4206
- const types = [];
4207
- if (config.types) {
4208
- Object.entries(config.types).forEach(
4209
- ([key, validate2]) => {
4210
- types.push({ regExp: new RegExp(key), validate: validate2 });
4211
- }
4212
- );
4213
- } else {
4214
- types.push({
4215
- regExp: /^EventEmitter$/,
4216
- validate: false
4217
- });
4218
- }
4219
- const { suffix = "Subject" } = config;
4220
- const suffixRegex = new RegExp(
4221
- String.raw`${escapeRegExp(suffix)}\$?$`,
4222
- "i"
4223
- );
4224
- function checkNode(nameNode, typeNode, shouldMessage = "forbidden") {
4225
- const tsNode = esTreeNodeToTSNodeMap.get(nameNode);
4226
- const text = tsNode.getText();
4227
- if (!suffixRegex.test(text) && couldBeType2(typeNode != null ? typeNode : nameNode, "Subject")) {
4228
- for (const type of types) {
4229
- const { regExp, validate: validate2 } = type;
4230
- if (couldBeType2(typeNode != null ? typeNode : nameNode, regExp) && !validate2) {
4231
- return;
4232
- }
4233
- }
4234
- context.report({
4235
- data: { suffix },
4236
- loc: getLoc(tsNode),
4237
- messageId: shouldMessage
4238
- });
4239
- }
4240
- }
4241
- return {
4242
- "ArrayPattern > Identifier": (node) => {
4243
- const found = findParent(
4244
- node,
4245
- "ArrowFunctionExpression",
4246
- "FunctionDeclaration",
4247
- "FunctionExpression",
4248
- "VariableDeclarator"
4249
- );
4250
- if (!found) {
4251
- return;
4252
- }
4253
- if (!validate.variables && isVariableDeclarator(found)) {
4254
- return;
4255
- }
4256
- if (!validate.parameters) {
4257
- return;
4258
- }
4259
- checkNode(node);
4260
- },
4261
- "ArrowFunctionExpression > Identifier": (node) => {
4262
- if (validate.parameters) {
4263
- const parent = node.parent;
4264
- if (node !== parent.body) {
4265
- checkNode(node);
4266
- }
4267
- }
4268
- },
4269
- "PropertyDefinition[computed=false]": (node) => {
4270
- const anyNode = node;
4271
- if (validate.properties) {
4272
- if (node.override) {
4273
- return;
4274
- }
4275
- checkNode(anyNode.key);
4276
- }
4277
- },
4278
- "FunctionDeclaration > Identifier": (node) => {
4279
- if (validate.parameters) {
4280
- const parent = node.parent;
4281
- if (node !== parent.id) {
4282
- checkNode(node);
4283
- }
4284
- }
4285
- },
4286
- "FunctionExpression > Identifier": (node) => {
4287
- if (validate.parameters) {
4288
- const parent = node.parent;
4289
- if (node !== parent.id) {
4290
- checkNode(node);
4291
- }
4292
- }
4293
- },
4294
- "MethodDefinition[kind='get'][computed=false]": (node) => {
4295
- if (validate.properties) {
4296
- if (node.override) {
4297
- return;
4298
- }
4299
- checkNode(node.key, node);
4300
- }
4301
- },
4302
- "MethodDefinition[kind='set'][computed=false]": (node) => {
4303
- if (validate.properties) {
4304
- if (node.override) {
4305
- return;
4306
- }
4307
- checkNode(node.key, node);
4308
- }
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
- },
4323
- "ObjectExpression > Property[computed=false] > Identifier": (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;
4345
- }
4346
- }
4347
- checkNode(node, void 0, "forbiddenProperty");
4348
- },
4349
- "ObjectPattern > Property > Identifier": (node) => {
4350
- const found = findParent(
4351
- node,
4352
- "ArrowFunctionExpression",
4353
- "FunctionDeclaration",
4354
- "FunctionExpression",
4355
- "VariableDeclarator"
4356
- );
4357
- if (!found) {
4358
- return;
4359
- }
4360
- if (!validate.variables && isVariableDeclarator(found)) {
4361
- return;
4362
- }
4363
- if (!validate.parameters) {
4364
- return;
4365
- }
4366
- const parent = node.parent;
4367
- if (node === parent.value) {
4368
- checkNode(node);
4369
- }
4370
- },
4371
- "TSCallSignatureDeclaration > Identifier": (node) => {
4372
- if (validate.parameters) {
4373
- checkNode(node);
4374
- }
4375
- },
4376
- "TSConstructSignatureDeclaration > Identifier": (node) => {
4377
- if (validate.parameters) {
4378
- checkNode(node);
4379
- }
4380
- },
4381
- "TSMethodSignature > Identifier": (node) => {
4382
- if (validate.parameters) {
4383
- checkNode(node);
4384
- }
4385
- },
4386
- "TSParameterProperty > Identifier": (node) => {
4387
- if (validate.parameters || validate.properties) {
4388
- checkNode(node);
4389
- }
4390
- },
4391
- "TSPropertySignature[computed=false]": (node) => {
4392
- if (validate.properties) {
4393
- checkNode(node.key);
4394
- }
4395
- },
4396
- "VariableDeclarator > Identifier": (node) => {
4397
- const parent = node.parent;
4398
- if (validate.variables && node === parent.id) {
4399
- checkNode(node);
4400
- }
4401
- }
4402
- };
4403
- }
4404
- });
4405
-
4406
- // src/rules/throw-error.ts
4407
- import { ESLintUtils as ESLintUtils13 } from "@typescript-eslint/utils";
4408
- import * as tsutils6 from "ts-api-utils";
4409
- var defaultOptions19 = [];
4410
- var throwErrorRule = ruleCreator({
4411
- defaultOptions: defaultOptions19,
4412
- meta: {
4413
- docs: {
4414
- description: "Enforce passing only `Error` values to `throwError` or `Subject.error`.",
4415
- recommended: {
4416
- recommended: true,
4417
- strict: [{ allowThrowingAny: false, allowThrowingUnknown: false }]
4418
- },
4419
- requiresTypeChecking: true
4420
- },
4421
- messages: {
4422
- forbidden: "Passing non-Error values is forbidden.",
4423
- suggestErrorConstructor: "Wrap string in Error constructor."
4424
- },
4425
- schema: [
4426
- {
4427
- properties: {
4428
- allowThrowingAny: { type: "boolean", default: true, description: "Whether to always allow throwing values typed as `any`." },
4429
- allowThrowingUnknown: { type: "boolean", default: true, description: "Whether to always allow throwing values typed as `unknown`." }
4430
- },
4431
- type: "object"
4432
- }
4433
- ],
4434
- type: "problem",
4435
- hasSuggestions: true
4436
- },
4437
- name: "throw-error",
4438
- create: (context) => {
4439
- const { esTreeNodeToTSNodeMap, program, getTypeAtLocation } = ESLintUtils13.getParserServices(context);
4440
- const { couldBeObservable, couldBeSubject } = getTypeServices(context);
4441
- const [config = {}] = context.options;
4442
- const { allowThrowingAny = true, allowThrowingUnknown = true } = config;
4443
- function checkThrowArgument(node, noFunction = false) {
4444
- var _a;
4445
- let type = getTypeAtLocation(node);
4446
- let reportNode = node;
4447
- if (!noFunction && couldBeFunction(type)) {
4448
- reportNode = (_a = node.body) != null ? _a : node;
4449
- const tsNode = esTreeNodeToTSNodeMap.get(node);
4450
- const annotation = tsNode.type;
4451
- const body = tsNode.body;
4452
- type = program.getTypeChecker().getTypeAtLocation(annotation != null ? annotation : body);
4453
- }
4454
- if (allowThrowingAny && tsutils6.isIntrinsicAnyType(type)) {
4455
- return;
4456
- }
4457
- if (allowThrowingUnknown && tsutils6.isIntrinsicUnknownType(type)) {
4458
- return;
4459
- }
4460
- if (couldBeType(type, /^Error$/)) {
4461
- return;
4462
- }
4463
- const isString = isTemplateLiteral(reportNode) || isLiteral(reportNode) && typeof reportNode.value === "string";
4464
- context.report({
4465
- messageId: "forbidden",
4466
- node: reportNode,
4467
- ...isString && {
4468
- suggest: [
4469
- {
4470
- messageId: "suggestErrorConstructor",
4471
- fix: (fixer) => {
4472
- const sourceCode = context.sourceCode;
4473
- const nodeText = sourceCode.getText(reportNode);
4474
- return fixer.replaceText(reportNode, `new Error(${nodeText})`);
4475
- }
4476
- }
4477
- ]
4478
- }
4479
- });
4480
- }
4481
- function checkThrowError(node) {
4482
- if (couldBeObservable(node)) {
4483
- const [arg] = node.arguments;
4484
- if (arg) {
4485
- checkThrowArgument(arg);
4486
- }
4487
- }
4488
- }
4489
- function checkSubjectError(node) {
4490
- if (isMemberExpression(node.callee) && couldBeSubject(node.callee.object)) {
4491
- const [arg] = node.arguments;
4492
- if (arg) {
4493
- checkThrowArgument(arg, true);
4494
- }
4495
- }
4496
- }
4497
- return {
4498
- "CallExpression[callee.name='throwError']": checkThrowError,
4499
- "CallExpression[callee.property.name='throwError']": checkThrowError,
4500
- "CallExpression[callee.property.name='error']": checkSubjectError
4501
- };
4502
- }
4503
- });
4504
-
4505
- // src/index.ts
4506
- var allRules = {
4507
- "ban-observables": banObservablesRule,
4508
- "ban-operators": banOperatorsRule,
4509
- "finnish": finnishRule,
4510
- "just": justRule,
4511
- "macro": macroRule,
4512
- "no-async-subscribe": noAsyncSubscribeRule,
4513
- "no-compat": noCompatRule,
4514
- "no-connectable": noConnectableRule,
4515
- "no-create": noCreateRule,
4516
- "no-cyclic-action": noCyclicActionRule,
4517
- "no-explicit-generics": noExplicitGenericsRule,
4518
- "no-exposed-subjects": noExposedSubjectsRule,
4519
- "no-finnish": noFinnishRule,
4520
- "no-floating-observables": noFloatingObservablesRule,
4521
- "no-ignored-default-value": noIgnoredDefaultValueRule,
4522
- "no-ignored-error": noIgnoredErrorRule,
4523
- "no-ignored-notifier": noIgnoredNotifierRule,
4524
- "no-ignored-observable": noIgnoredObservableRule,
4525
- "no-ignored-replay-buffer": noIgnoredReplayBufferRule,
4526
- "no-ignored-subscribe": noIgnoredSubscribeRule,
4527
- "no-ignored-subscription": noIgnoredSubscriptionRule,
4528
- "no-ignored-takewhile-value": noIgnoredTakewhileValueRule,
4529
- "no-implicit-any-catch": noImplicitAnyCatchRule,
4530
- "no-index": noIndexRule,
4531
- "no-internal": noInternalRule,
4532
- "no-misused-observables": noMisusedObservablesRule,
4533
- "no-nested-subscribe": noNestedSubscribeRule,
4534
- "no-redundant-notify": noRedundantNotifyRule,
4535
- "no-sharereplay": noSharereplayRule,
4536
- "no-sharereplay-before-takeuntil": noSharereplayBeforeTakeuntilRule,
4537
- "no-subclass": noSubclassRule,
4538
- "no-subject-unsubscribe": noSubjectUnsubscribeRule,
4539
- "no-subject-value": noSubjectValueRule,
4540
- "no-subscribe-handlers": noSubscribeHandlersRule,
4541
- "no-subscribe-in-pipe": noSubscribeInPipeRule,
4542
- "no-tap": noTapRule,
4543
- "no-topromise": noTopromiseRule,
4544
- "no-unbound-methods": noUnboundMethodsRule,
4545
- "no-unnecessary-collection": noUnnecessaryCollectionRule,
4546
- "no-unsafe-catch": noUnsafeCatchRule,
4547
- "no-unsafe-first": noUnsafeFirstRule,
4548
- "no-unsafe-subject-next": noUnsafeSubjectNext,
4549
- "no-unsafe-switchmap": noUnsafeSwitchmapRule,
4550
- "no-unsafe-takeuntil": noUnsafeTakeuntilRule,
4551
- "prefer-observer": preferObserverRule,
4552
- "prefer-root-operators": preferRootOperatorsRule,
4553
- "suffix-subjects": suffixSubjectsRule,
4554
- "throw-error": throwErrorRule
4555
- };
4556
- var plugin = {
4557
- meta: {
4558
- name,
4559
- version,
4560
- namespace: "rxjs-x"
4561
- },
4562
- /** Compatibility with `defineConfig` until https://github.com/typescript-eslint/typescript-eslint/issues/11543 is addressed. */
4563
- rules: allRules
4564
- };
4565
- var rxjsX = {
4566
- ...plugin,
4567
- configs: {
4568
- "recommended": createRecommendedConfig(plugin),
4569
- "strict": createStrictConfig(plugin),
4570
- "recommended-legacy": createLegacyRecommendedConfig()
4571
- }
4572
- };
4573
- var index_default = rxjsX;
4574
- export {
4575
- index_default as default
4576
- };