eslint-plugin-rxjs-x 0.8.4 → 0.9.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/LICENSE CHANGED
@@ -1,7 +1,7 @@
1
1
  MIT License
2
2
 
3
3
  Copyright (c) 2019 Nicholas Jamieson and contributors
4
- Copyright (c) 2024-2025 Jason Weinzierl and contributors
4
+ Copyright (c) 2024-2026 Jason Weinzierl and contributors
5
5
 
6
6
  Permission is hereby granted, free of charge, to any person obtaining a copy
7
7
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -2,87 +2,97 @@
2
2
 
3
3
  [![GitHub License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/JasonWeinzierl/eslint-plugin-rxjs-x/blob/master/LICENSE)
4
4
  [![NPM version](https://img.shields.io/npm/v/eslint-plugin-rxjs-x.svg)](https://www.npmjs.com/package/eslint-plugin-rxjs-x)
5
+ [![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/JasonWeinzierl/eslint-plugin-rxjs-x/badge)](https://scorecard.dev/viewer/?uri=github.com/JasonWeinzierl/eslint-plugin-rxjs-x)
5
6
 
6
7
  This ESLint plugin is intended to prevent issues with [RxJS](https://github.com/ReactiveX/rxjs).
7
8
 
8
9
  Most of these rules require TypeScript typed linting and are indicated as such below.
9
10
 
10
- ## Migration Guide from `eslint-plugin-rxjs`
11
+ ## Installation Guide (Flat Configuration)
11
12
 
12
- This project started as a fork of [`eslint-plugin-rxjs`](https://github.com/cartant/eslint-plugin-rxjs)
13
- but has since introduced new features which involve breaking changes.
13
+ See [typescript-eslint's Getting Started](https://typescript-eslint.io/getting-started) for a full ESLint setup guide.
14
14
 
15
- 1. Migrate your config from the old `.eslintrc` format to `eslint.config.mjs` (or similar), and uninstall `eslint-plugin-rxjs`.
16
- - See ESLint's guide here: [https://eslint.org/docs/latest/use/configure/migration-guide].
17
- - If you need to continue using the deprecated format, use the original `eslint-plugin-rxjs` or a different fork.
18
- 2. Install `eslint-plugin-rxjs-x`, and import it into your config.
15
+ 1. Install `eslint-plugin-rxjs-x` using your preferred package manager.
16
+ 2. Enable typed linting.
17
+ - See [Linting with Type Information](https://typescript-eslint.io/getting-started/typed-linting/) for more information.
18
+ 3. Import this plugin into your config.
19
+ Add the `rxjsX.configs.recommended` shared config to your configuration like so:
19
20
 
20
21
  ```diff
22
+ // @ts-check
23
+ import { defineConfig } from 'eslint/config';
24
+ import tseslint from 'typescript-eslint';
21
25
  + import rxjsX from 'eslint-plugin-rxjs-x';
26
+
27
+ export default defineConfig({
28
+ extends: [
29
+ tseslint.configs.recommended,
30
+ + rxjsX.configs.recommended,
31
+ ],
32
+ languageOptions: {
33
+ parserOptions: {
34
+ projectService: true,
35
+ },
36
+ },
37
+ });
22
38
  ```
23
39
 
24
- 3. If you previously used the `plugin:rxjs/recommended` shared config, add `rxjsX.configs.recommended` to your `extends` block:
40
+ Additionally, consider if the `rxjsX.configs.strict` shared config is right for your project.
41
+
42
+ ## Legacy Migration Guide from `eslint-plugin-rxjs`
43
+
44
+ > [!TIP]
45
+ > A complete description of all changes from `eslint-plugin-rxjs` are documented in the [CHANGELOG](CHANGELOG.md) file.
46
+
47
+ This project started as a fork of [`eslint-plugin-rxjs`](https://github.com/cartant/eslint-plugin-rxjs)
48
+ but is still compatible with the eslintrc configuration format.
49
+
50
+ > [!WARNING]
51
+ > eslintrc compatibility will be removed in v1.
52
+ > Users are highly encouraged to upgrade to ESLint's flat configuration format.
53
+ > See: [https://eslint.org/docs/latest/use/configure/migration-guide]
54
+
55
+ 1. Install `eslint-plugin-rxjs-x` using your preferred package manager.
56
+ 2. If you previously used the `plugin:rxjs/recommended` shared config,
57
+ replace it with `plugin:rxjs-x/recommended-legacy`:
25
58
 
26
59
  ```diff
27
- extends: [
28
- + rxjsX.configs.recommended,
60
+ "extends": [
61
+ "plugin:@typescript-eslint/recommended",
62
+ - "plugin:rxjs/recommended",
63
+ + "plugin:rxjs-x/recommended-legacy",
29
64
  ],
30
65
  ```
31
66
 
32
- - Note: `eslint-plugin-rxjs-x` provides a `strict` shared config, so consider using `rxjsX.configs.strict` instead.
33
- 4. If you previously did _not_ use a shared config, add the plugin to your `plugins` block with the new namespace:
67
+ 3. If you previously did _not_ use a shared config,
68
+ then replace the `rxjs` plugin to your `plugins` block:
34
69
 
35
70
  ```diff
36
- plugins: {
37
- + 'rxjs-x': rxjsX,
38
- },
71
+ "plugins": [
72
+ "@typescript-eslint",
73
+ - "rxjs",
74
+ + "rxjs-x",
75
+ ],
39
76
  ```
40
77
 
41
- - Note: this is unnecessary if you are using a shared config.
42
- 5. In your `rules` block, replace the namespace `rxjs` with `rxjs-x`:
78
+ - Note: this is unnecessary if you are using the `recommended-legacy` shared config.
79
+ 4. In your `rules` blocks, replace the namespace `rxjs` with `rxjs-x` for all rules:
43
80
 
44
81
  ```diff
45
- - 'rxjs/no-subject-value': 'error',
46
- + 'rxjs-x/no-subject-value': 'error',
82
+ "rules": {
83
+ - "rxjs/no-subject-value": "error",
84
+ + "rxjs-x/no-subject-value": "error",
85
+ },
47
86
  ```
48
87
 
49
- 6. If you previously used `rxjs/no-ignored-observable`, replace it with `rxjs-x/no-floating-observables`.
88
+ - Note: if your project has inline comments (e.g. `eslint-disable-next-line`) referencing `rxjs` rules, you must update the namespace there too.
89
+ 5. If you previously used `rxjs/no-ignored-observable`, consider replacing it with `rxjs-x/no-floating-observables`. `no-ignored-observable` will be removed in v1.
50
90
 
51
91
  ```diff
52
92
  - 'rxjs/no-ignored-observable': 'error',
53
93
  + 'rxjs-x/no-floating-observables': 'error',
54
94
  ```
55
95
 
56
- > [!TIP]
57
- > A complete description of all changes are documented in the [CHANGELOG](CHANGELOG.md) file.
58
-
59
- ## Installation Guide
60
-
61
- See [typescript-eslint's Getting Started](https://typescript-eslint.io/getting-started) for a full ESLint setup guide.
62
-
63
- 1. Enable typed linting.
64
- - See [Linting with Type Information](https://typescript-eslint.io/getting-started/typed-linting/) for more information.
65
- 2. Start with the `recommended` shared config in your `eslint.config.mjs`.
66
-
67
- ```js
68
- // @ts-check
69
- import { defineConfig } from 'eslint/config';
70
- import tseslint from 'typescript-eslint';
71
- import rxjsX from 'eslint-plugin-rxjs-x';
72
-
73
- export default defineConfig({
74
- extends: [
75
- ...tseslint.configs.recommended,
76
- rxjsX.configs.recommended,
77
- ],
78
- languageOptions: {
79
- parserOptions: {
80
- projectService: true,
81
- },
82
- },
83
- });
84
- ```
85
-
86
96
  ## Configs
87
97
 
88
98
  <!-- begin auto-generated configs list -->
@@ -120,13 +130,14 @@ The package includes the following rules.
120
130
  | [no-connectable](docs/rules/no-connectable.md) | Disallow operators that return connectable observables. | | | | 💭 | |
121
131
  | [no-create](docs/rules/no-create.md) | Disallow the static `Observable.create` function. | ✅ 🔒 | | | 💭 | |
122
132
  | [no-cyclic-action](docs/rules/no-cyclic-action.md) | Disallow cyclic actions in effects and epics. | | | | 💭 | |
123
- | [no-explicit-generics](docs/rules/no-explicit-generics.md) | Disallow unnecessary explicit generic type arguments. | | | | | |
133
+ | [no-explicit-generics](docs/rules/no-explicit-generics.md) | Disallow unnecessary explicit generic type arguments. | | | | 💭 | |
124
134
  | [no-exposed-subjects](docs/rules/no-exposed-subjects.md) | Disallow public and protected subjects. | 🔒 | | | 💭 | |
125
135
  | [no-finnish](docs/rules/no-finnish.md) | Disallow Finnish notation. | | | | 💭 | |
126
136
  | [no-floating-observables](docs/rules/no-floating-observables.md) | Require Observables to be handled appropriately. | 🔒 | | | 💭 | |
127
137
  | [no-ignored-default-value](docs/rules/no-ignored-default-value.md) | Disallow using `firstValueFrom`, `lastValueFrom`, `first`, and `last` without specifying a default value. | 🔒 | | | 💭 | |
128
138
  | [no-ignored-error](docs/rules/no-ignored-error.md) | Disallow calling `subscribe` without specifying an error handler. | 🔒 | | | 💭 | |
129
139
  | [no-ignored-notifier](docs/rules/no-ignored-notifier.md) | Disallow observables not composed from the `repeatWhen` or `retryWhen` notifier. | ✅ 🔒 | | | 💭 | |
140
+ | [no-ignored-observable](docs/rules/no-ignored-observable.md) | Disallow ignoring of observables returned by functions. | | | | | ❌ |
130
141
  | [no-ignored-replay-buffer](docs/rules/no-ignored-replay-buffer.md) | Disallow using `ReplaySubject`, `publishReplay` or `shareReplay` without specifying the buffer size. | ✅ 🔒 | | | | |
131
142
  | [no-ignored-subscribe](docs/rules/no-ignored-subscribe.md) | Disallow calling `subscribe` without specifying arguments. | | | | 💭 | |
132
143
  | [no-ignored-subscription](docs/rules/no-ignored-subscription.md) | Disallow ignoring the subscription returned by `subscribe`. | | | | 💭 | |
package/dist/index.d.mts CHANGED
@@ -62,6 +62,7 @@ declare const allRules: {
62
62
  }, TSESLint.RuleListener>;
63
63
  'no-explicit-generics': TSESLint.RuleModule<"forbidden", [], {
64
64
  description: "Disallow unnecessary explicit generic type arguments.";
65
+ requiresTypeChecking: true;
65
66
  }, TSESLint.RuleListener>;
66
67
  'no-exposed-subjects': TSESLint.RuleModule<"forbidden" | "forbiddenAllowProtected", readonly {
67
68
  allowProtected?: boolean;
@@ -96,6 +97,9 @@ declare const allRules: {
96
97
  recommended: "recommended";
97
98
  requiresTypeChecking: true;
98
99
  }, TSESLint.RuleListener>;
100
+ 'no-ignored-observable': TSESLint.RuleModule<"forbidden", [], {
101
+ description: "Disallow ignoring of observables returned by functions.";
102
+ }, TSESLint.RuleListener>;
99
103
  'no-ignored-replay-buffer': TSESLint.RuleModule<"forbidden", [], {
100
104
  description: "Disallow using `ReplaySubject`, `publishReplay` or `shareReplay` without specifying the buffer size.";
101
105
  recommended: "recommended";
@@ -115,7 +119,7 @@ declare const allRules: {
115
119
  description: "Disallow ignoring the value within `takeWhile`.";
116
120
  recommended: "recommended";
117
121
  }, TSESLint.RuleListener>;
118
- 'no-implicit-any-catch': TSESLint.RuleModule<"explicitAny" | "implicitAny" | "narrowed" | "suggestExplicitUnknown", readonly {
122
+ 'no-implicit-any-catch': TSESLint.RuleModule<"explicitAny" | "implicitAny" | "narrowed" | "suggestExplicitUnknown" | "suggestExplicitAny", readonly {
119
123
  allowExplicitAny?: boolean;
120
124
  }[], {
121
125
  description: "Disallow implicit `any` error parameters in `catchError` operators.";
@@ -241,7 +245,7 @@ declare const allRules: {
241
245
  recommended: "recommended";
242
246
  requiresTypeChecking: true;
243
247
  }, TSESLint.RuleListener>;
244
- 'prefer-observer': TSESLint.RuleModule<"forbidden", readonly {
248
+ 'prefer-observer': TSESLint.RuleModule<"forbidden" | "suggest", readonly {
245
249
  allowNext?: boolean;
246
250
  }[], {
247
251
  description: "Disallow passing separate handlers to `subscribe` and `tap`.";
@@ -348,6 +352,31 @@ declare const rxjsX: {
348
352
  }];
349
353
  };
350
354
  };
355
+ 'recommended-legacy': {
356
+ plugins: ["rxjs-x"];
357
+ rules: {
358
+ 'rxjs-x/no-async-subscribe': "error";
359
+ 'rxjs-x/no-create': "error";
360
+ 'rxjs-x/no-ignored-notifier': "error";
361
+ 'rxjs-x/no-ignored-replay-buffer': "error";
362
+ 'rxjs-x/no-ignored-takewhile-value': "error";
363
+ 'rxjs-x/no-implicit-any-catch': "error";
364
+ 'rxjs-x/no-index': "error";
365
+ 'rxjs-x/no-internal': "error";
366
+ 'rxjs-x/no-nested-subscribe': "error";
367
+ 'rxjs-x/no-redundant-notify': "error";
368
+ 'rxjs-x/no-sharereplay': "error";
369
+ 'rxjs-x/no-subject-unsubscribe': "error";
370
+ 'rxjs-x/no-subscribe-in-pipe': "error";
371
+ 'rxjs-x/no-topromise': "error";
372
+ 'rxjs-x/no-unbound-methods': "error";
373
+ 'rxjs-x/no-unsafe-subject-next': "error";
374
+ 'rxjs-x/no-unsafe-takeuntil': "error";
375
+ 'rxjs-x/prefer-observer': "error";
376
+ 'rxjs-x/prefer-root-operators': "error";
377
+ 'rxjs-x/throw-error': "error";
378
+ };
379
+ };
351
380
  };
352
381
  meta: {
353
382
  name: string;
package/dist/index.d.ts CHANGED
@@ -62,6 +62,7 @@ declare const allRules: {
62
62
  }, TSESLint.RuleListener>;
63
63
  'no-explicit-generics': TSESLint.RuleModule<"forbidden", [], {
64
64
  description: "Disallow unnecessary explicit generic type arguments.";
65
+ requiresTypeChecking: true;
65
66
  }, TSESLint.RuleListener>;
66
67
  'no-exposed-subjects': TSESLint.RuleModule<"forbidden" | "forbiddenAllowProtected", readonly {
67
68
  allowProtected?: boolean;
@@ -96,6 +97,9 @@ declare const allRules: {
96
97
  recommended: "recommended";
97
98
  requiresTypeChecking: true;
98
99
  }, TSESLint.RuleListener>;
100
+ 'no-ignored-observable': TSESLint.RuleModule<"forbidden", [], {
101
+ description: "Disallow ignoring of observables returned by functions.";
102
+ }, TSESLint.RuleListener>;
99
103
  'no-ignored-replay-buffer': TSESLint.RuleModule<"forbidden", [], {
100
104
  description: "Disallow using `ReplaySubject`, `publishReplay` or `shareReplay` without specifying the buffer size.";
101
105
  recommended: "recommended";
@@ -115,7 +119,7 @@ declare const allRules: {
115
119
  description: "Disallow ignoring the value within `takeWhile`.";
116
120
  recommended: "recommended";
117
121
  }, TSESLint.RuleListener>;
118
- 'no-implicit-any-catch': TSESLint.RuleModule<"explicitAny" | "implicitAny" | "narrowed" | "suggestExplicitUnknown", readonly {
122
+ 'no-implicit-any-catch': TSESLint.RuleModule<"explicitAny" | "implicitAny" | "narrowed" | "suggestExplicitUnknown" | "suggestExplicitAny", readonly {
119
123
  allowExplicitAny?: boolean;
120
124
  }[], {
121
125
  description: "Disallow implicit `any` error parameters in `catchError` operators.";
@@ -241,7 +245,7 @@ declare const allRules: {
241
245
  recommended: "recommended";
242
246
  requiresTypeChecking: true;
243
247
  }, TSESLint.RuleListener>;
244
- 'prefer-observer': TSESLint.RuleModule<"forbidden", readonly {
248
+ 'prefer-observer': TSESLint.RuleModule<"forbidden" | "suggest", readonly {
245
249
  allowNext?: boolean;
246
250
  }[], {
247
251
  description: "Disallow passing separate handlers to `subscribe` and `tap`.";
@@ -348,6 +352,31 @@ declare const rxjsX: {
348
352
  }];
349
353
  };
350
354
  };
355
+ 'recommended-legacy': {
356
+ plugins: ["rxjs-x"];
357
+ rules: {
358
+ 'rxjs-x/no-async-subscribe': "error";
359
+ 'rxjs-x/no-create': "error";
360
+ 'rxjs-x/no-ignored-notifier': "error";
361
+ 'rxjs-x/no-ignored-replay-buffer': "error";
362
+ 'rxjs-x/no-ignored-takewhile-value': "error";
363
+ 'rxjs-x/no-implicit-any-catch': "error";
364
+ 'rxjs-x/no-index': "error";
365
+ 'rxjs-x/no-internal': "error";
366
+ 'rxjs-x/no-nested-subscribe': "error";
367
+ 'rxjs-x/no-redundant-notify': "error";
368
+ 'rxjs-x/no-sharereplay': "error";
369
+ 'rxjs-x/no-subject-unsubscribe': "error";
370
+ 'rxjs-x/no-subscribe-in-pipe': "error";
371
+ 'rxjs-x/no-topromise': "error";
372
+ 'rxjs-x/no-unbound-methods': "error";
373
+ 'rxjs-x/no-unsafe-subject-next': "error";
374
+ 'rxjs-x/no-unsafe-takeuntil': "error";
375
+ 'rxjs-x/prefer-observer': "error";
376
+ 'rxjs-x/prefer-root-operators': "error";
377
+ 'rxjs-x/throw-error': "error";
378
+ };
379
+ };
351
380
  };
352
381
  meta: {
353
382
  name: string;