eslint-plugin-rxjs-x 0.9.1 → 0.9.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/index.d.mts +6 -5
- package/dist/index.d.ts +6 -5
- package/dist/index.js +98 -50
- package/dist/index.mjs +98 -50
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -128,7 +128,7 @@ The package includes the following rules.
|
|
|
128
128
|
| [no-async-subscribe](docs/rules/no-async-subscribe.md) | Disallow passing `async` functions to `subscribe`. | ✅ 🔒 | | | 💭 | |
|
|
129
129
|
| [no-compat](docs/rules/no-compat.md) | Disallow the `rxjs-compat` package. | | | | | ❌ |
|
|
130
130
|
| [no-connectable](docs/rules/no-connectable.md) | Disallow operators that return connectable observables. | | | | 💭 | |
|
|
131
|
-
| [no-create](docs/rules/no-create.md) | Disallow the static `Observable.create`
|
|
131
|
+
| [no-create](docs/rules/no-create.md) | Disallow the static `Observable.create` and `Subject.create` functions. | ✅ 🔒 | | | 💭 | |
|
|
132
132
|
| [no-cyclic-action](docs/rules/no-cyclic-action.md) | Disallow cyclic actions in effects and epics. | | | | 💭 | |
|
|
133
133
|
| [no-explicit-generics](docs/rules/no-explicit-generics.md) | Disallow unnecessary explicit generic type arguments. | | | | 💭 | |
|
|
134
134
|
| [no-exposed-subjects](docs/rules/no-exposed-subjects.md) | Disallow public and protected subjects. | 🔒 | | | 💭 | |
|
|
@@ -142,7 +142,7 @@ The package includes the following rules.
|
|
|
142
142
|
| [no-ignored-subscribe](docs/rules/no-ignored-subscribe.md) | Disallow calling `subscribe` without specifying arguments. | | | | 💭 | |
|
|
143
143
|
| [no-ignored-subscription](docs/rules/no-ignored-subscription.md) | Disallow ignoring the subscription returned by `subscribe`. | | | | 💭 | |
|
|
144
144
|
| [no-ignored-takewhile-value](docs/rules/no-ignored-takewhile-value.md) | Disallow ignoring the value within `takeWhile`. | ✅ 🔒 | | | | |
|
|
145
|
-
| [no-implicit-any-catch](docs/rules/no-implicit-any-catch.md) | Disallow implicit `any` error parameters in `catchError`
|
|
145
|
+
| [no-implicit-any-catch](docs/rules/no-implicit-any-catch.md) | Disallow implicit `any` error parameters in `catchError`, `subscribe`, and `tap`. | ✅ 🔒 | 🔧 | 💡 | 💭 | |
|
|
146
146
|
| [no-index](docs/rules/no-index.md) | Disallow importing index modules. | ✅ 🔒 | | | | |
|
|
147
147
|
| [no-internal](docs/rules/no-internal.md) | Disallow importing internal modules. | ✅ 🔒 | 🔧 | 💡 | | |
|
|
148
148
|
| [no-misused-observables](docs/rules/no-misused-observables.md) | Disallow Observables in places not designed to handle them. | 🔒 | | | 💭 | |
|
|
@@ -167,6 +167,6 @@ The package includes the following rules.
|
|
|
167
167
|
| [prefer-observer](docs/rules/prefer-observer.md) | Disallow passing separate handlers to `subscribe` and `tap`. | ✅ 🔒 | 🔧 | 💡 | 💭 | |
|
|
168
168
|
| [prefer-root-operators](docs/rules/prefer-root-operators.md) | Disallow importing operators from `rxjs/operators`. | ✅ 🔒 | 🔧 | 💡 | | |
|
|
169
169
|
| [suffix-subjects](docs/rules/suffix-subjects.md) | Enforce the use of a suffix in subject identifiers. | | | | 💭 | |
|
|
170
|
-
| [throw-error](docs/rules/throw-error.md) | Enforce passing only `Error` values to `throwError` or `Subject.error`. | ✅ 🔒 | |
|
|
170
|
+
| [throw-error](docs/rules/throw-error.md) | Enforce passing only `Error` values to `throwError` or `Subject.error`. | ✅ 🔒 | | 💡 | 💭 | |
|
|
171
171
|
|
|
172
172
|
<!-- end auto-generated rules list -->
|
package/dist/index.d.mts
CHANGED
|
@@ -50,8 +50,8 @@ declare const allRules: {
|
|
|
50
50
|
description: "Disallow operators that return connectable observables.";
|
|
51
51
|
requiresTypeChecking: true;
|
|
52
52
|
}, TSESLint.RuleListener>;
|
|
53
|
-
'no-create': TSESLint.RuleModule<"forbidden", [], {
|
|
54
|
-
description: "Disallow the static `Observable.create`
|
|
53
|
+
'no-create': TSESLint.RuleModule<"forbidden" | "forbiddenSubject", [], {
|
|
54
|
+
description: "Disallow the static `Observable.create` and `Subject.create` functions.";
|
|
55
55
|
recommended: "recommended";
|
|
56
56
|
requiresTypeChecking: true;
|
|
57
57
|
}, TSESLint.RuleListener>;
|
|
@@ -120,10 +120,11 @@ declare const allRules: {
|
|
|
120
120
|
description: "Disallow ignoring the value within `takeWhile`.";
|
|
121
121
|
recommended: "recommended";
|
|
122
122
|
}, TSESLint.RuleListener>;
|
|
123
|
-
'no-implicit-any-catch': TSESLint.RuleModule<"explicitAny" | "implicitAny" | "narrowed" | "suggestExplicitUnknown" | "suggestExplicitAny", readonly {
|
|
123
|
+
'no-implicit-any-catch': TSESLint.RuleModule<"explicitAny" | "implicitAny" | "narrowed" | "narrowedAllowError" | "suggestExplicitUnknown" | "suggestExplicitAny" | "suggestExplicitError", readonly {
|
|
124
124
|
allowExplicitAny?: boolean;
|
|
125
|
+
allowExplicitError?: boolean;
|
|
125
126
|
}[], {
|
|
126
|
-
description: "Disallow implicit `any` error parameters in `catchError`
|
|
127
|
+
description: "Disallow implicit `any` error parameters in `catchError`, `subscribe`, and `tap`.";
|
|
127
128
|
recommended: {
|
|
128
129
|
recommended: true;
|
|
129
130
|
strict: [{
|
|
@@ -267,7 +268,7 @@ declare const allRules: {
|
|
|
267
268
|
description: "Enforce the use of a suffix in subject identifiers.";
|
|
268
269
|
requiresTypeChecking: true;
|
|
269
270
|
}, TSESLint.RuleListener>;
|
|
270
|
-
'throw-error': TSESLint.RuleModule<"forbidden", readonly {
|
|
271
|
+
'throw-error': TSESLint.RuleModule<"forbidden" | "suggestErrorConstructor", readonly {
|
|
271
272
|
allowThrowingAny?: boolean;
|
|
272
273
|
allowThrowingUnknown?: boolean;
|
|
273
274
|
}[], {
|
package/dist/index.d.ts
CHANGED
|
@@ -50,8 +50,8 @@ declare const allRules: {
|
|
|
50
50
|
description: "Disallow operators that return connectable observables.";
|
|
51
51
|
requiresTypeChecking: true;
|
|
52
52
|
}, TSESLint.RuleListener>;
|
|
53
|
-
'no-create': TSESLint.RuleModule<"forbidden", [], {
|
|
54
|
-
description: "Disallow the static `Observable.create`
|
|
53
|
+
'no-create': TSESLint.RuleModule<"forbidden" | "forbiddenSubject", [], {
|
|
54
|
+
description: "Disallow the static `Observable.create` and `Subject.create` functions.";
|
|
55
55
|
recommended: "recommended";
|
|
56
56
|
requiresTypeChecking: true;
|
|
57
57
|
}, TSESLint.RuleListener>;
|
|
@@ -120,10 +120,11 @@ declare const allRules: {
|
|
|
120
120
|
description: "Disallow ignoring the value within `takeWhile`.";
|
|
121
121
|
recommended: "recommended";
|
|
122
122
|
}, TSESLint.RuleListener>;
|
|
123
|
-
'no-implicit-any-catch': TSESLint.RuleModule<"explicitAny" | "implicitAny" | "narrowed" | "suggestExplicitUnknown" | "suggestExplicitAny", readonly {
|
|
123
|
+
'no-implicit-any-catch': TSESLint.RuleModule<"explicitAny" | "implicitAny" | "narrowed" | "narrowedAllowError" | "suggestExplicitUnknown" | "suggestExplicitAny" | "suggestExplicitError", readonly {
|
|
124
124
|
allowExplicitAny?: boolean;
|
|
125
|
+
allowExplicitError?: boolean;
|
|
125
126
|
}[], {
|
|
126
|
-
description: "Disallow implicit `any` error parameters in `catchError`
|
|
127
|
+
description: "Disallow implicit `any` error parameters in `catchError`, `subscribe`, and `tap`.";
|
|
127
128
|
recommended: {
|
|
128
129
|
recommended: true;
|
|
129
130
|
strict: [{
|
|
@@ -267,7 +268,7 @@ declare const allRules: {
|
|
|
267
268
|
description: "Enforce the use of a suffix in subject identifiers.";
|
|
268
269
|
requiresTypeChecking: true;
|
|
269
270
|
}, TSESLint.RuleListener>;
|
|
270
|
-
'throw-error': TSESLint.RuleModule<"forbidden", readonly {
|
|
271
|
+
'throw-error': TSESLint.RuleModule<"forbidden" | "suggestErrorConstructor", readonly {
|
|
271
272
|
allowThrowingAny?: boolean;
|
|
272
273
|
allowThrowingUnknown?: boolean;
|
|
273
274
|
}[], {
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }// package.json
|
|
2
2
|
var name = "eslint-plugin-rxjs-x";
|
|
3
|
-
var version = "0.9.
|
|
3
|
+
var version = "0.9.3";
|
|
4
4
|
|
|
5
5
|
// src/configs/recommended.ts
|
|
6
6
|
var createRecommendedConfig = (plugin2) => ({
|
|
@@ -117,7 +117,10 @@ function couldBeType(type, name2, qualified) {
|
|
|
117
117
|
if (tsutils.isTypeReference(type)) {
|
|
118
118
|
type = type.target;
|
|
119
119
|
}
|
|
120
|
-
if (isType(type, name2, qualified)) {
|
|
120
|
+
if (isType(type.symbol, name2, qualified)) {
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
123
|
+
if (type.aliasSymbol && isType(type.aliasSymbol, name2, qualified)) {
|
|
121
124
|
return true;
|
|
122
125
|
}
|
|
123
126
|
if (tsutils.isUnionOrIntersectionType(type)) {
|
|
@@ -132,16 +135,16 @@ function couldBeType(type, name2, qualified) {
|
|
|
132
135
|
}
|
|
133
136
|
return false;
|
|
134
137
|
}
|
|
135
|
-
function isType(
|
|
136
|
-
if (!
|
|
138
|
+
function isType(symbol, name2, qualified) {
|
|
139
|
+
if (!symbol) {
|
|
137
140
|
return false;
|
|
138
141
|
}
|
|
139
142
|
if (qualified && !qualified.name.test(
|
|
140
|
-
qualified.typeChecker.getFullyQualifiedName(
|
|
143
|
+
qualified.typeChecker.getFullyQualifiedName(symbol)
|
|
141
144
|
)) {
|
|
142
145
|
return false;
|
|
143
146
|
}
|
|
144
|
-
return typeof name2 === "string" ?
|
|
147
|
+
return typeof name2 === "string" ? symbol.name === name2 : Boolean(symbol.name.match(name2));
|
|
145
148
|
}
|
|
146
149
|
function couldImplement(type, name2, qualified) {
|
|
147
150
|
const { symbol } = type;
|
|
@@ -274,6 +277,9 @@ function isJSXExpressionContainer(node) {
|
|
|
274
277
|
function isLiteral(node) {
|
|
275
278
|
return node.type === _utils.AST_NODE_TYPES.Literal;
|
|
276
279
|
}
|
|
280
|
+
function isTemplateLiteral(node) {
|
|
281
|
+
return node.type === _utils.AST_NODE_TYPES.TemplateLiteral;
|
|
282
|
+
}
|
|
277
283
|
function isMemberExpression(node) {
|
|
278
284
|
return node.type === _utils.AST_NODE_TYPES.MemberExpression;
|
|
279
285
|
}
|
|
@@ -1103,19 +1109,20 @@ var noCreateRule = ruleCreator({
|
|
|
1103
1109
|
defaultOptions: [],
|
|
1104
1110
|
meta: {
|
|
1105
1111
|
docs: {
|
|
1106
|
-
description: "Disallow the static `Observable.create`
|
|
1112
|
+
description: "Disallow the static `Observable.create` and `Subject.create` functions.",
|
|
1107
1113
|
recommended: "recommended",
|
|
1108
1114
|
requiresTypeChecking: true
|
|
1109
1115
|
},
|
|
1110
1116
|
messages: {
|
|
1111
|
-
forbidden: "Observable.create is forbidden; use new Observable."
|
|
1117
|
+
forbidden: "Observable.create is forbidden; use new Observable.",
|
|
1118
|
+
forbiddenSubject: "Subject.create is forbidden."
|
|
1112
1119
|
},
|
|
1113
1120
|
schema: [],
|
|
1114
1121
|
type: "problem"
|
|
1115
1122
|
},
|
|
1116
1123
|
name: "no-create",
|
|
1117
1124
|
create: (context) => {
|
|
1118
|
-
const { couldBeObservable } = getTypeServices(context);
|
|
1125
|
+
const { couldBeObservable, couldBeType: couldBeType2 } = getTypeServices(context);
|
|
1119
1126
|
return {
|
|
1120
1127
|
"CallExpression > MemberExpression[object.name='Observable'] > Identifier[name='create']": (node) => {
|
|
1121
1128
|
const memberExpression = node.parent;
|
|
@@ -1125,6 +1132,15 @@ var noCreateRule = ruleCreator({
|
|
|
1125
1132
|
node
|
|
1126
1133
|
});
|
|
1127
1134
|
}
|
|
1135
|
+
},
|
|
1136
|
+
"CallExpression > MemberExpression[object.name=/^(Subject|BehaviorSubject|AsyncSubject|ReplaySubject)$/] > Identifier[name='create']": (node) => {
|
|
1137
|
+
const memberExpression = node.parent;
|
|
1138
|
+
if (couldBeType2(memberExpression.object, /^(Subject|BehaviorSubject|AsyncSubject|ReplaySubject)$/)) {
|
|
1139
|
+
context.report({
|
|
1140
|
+
messageId: "forbiddenSubject",
|
|
1141
|
+
node
|
|
1142
|
+
});
|
|
1143
|
+
}
|
|
1128
1144
|
}
|
|
1129
1145
|
};
|
|
1130
1146
|
}
|
|
@@ -2090,7 +2106,7 @@ var noImplicitAnyCatchRule = ruleCreator({
|
|
|
2090
2106
|
defaultOptions: defaultOptions8,
|
|
2091
2107
|
meta: {
|
|
2092
2108
|
docs: {
|
|
2093
|
-
description: "Disallow implicit `any` error parameters in `catchError`
|
|
2109
|
+
description: "Disallow implicit `any` error parameters in `catchError`, `subscribe`, and `tap`.",
|
|
2094
2110
|
recommended: {
|
|
2095
2111
|
recommended: true,
|
|
2096
2112
|
strict: [{
|
|
@@ -2105,8 +2121,10 @@ var noImplicitAnyCatchRule = ruleCreator({
|
|
|
2105
2121
|
explicitAny: "Explicit `any` in error callback.",
|
|
2106
2122
|
implicitAny: "Implicit `any` in error callback.",
|
|
2107
2123
|
narrowed: "Error type must be `unknown` or `any`.",
|
|
2124
|
+
narrowedAllowError: "Error type must be `unknown`, `any`, or `Error`.",
|
|
2108
2125
|
suggestExplicitUnknown: "Use `unknown` instead to explicitly and safely assert the type is correct.",
|
|
2109
|
-
suggestExplicitAny: "Use `any` instead to explicitly opt out of type safety."
|
|
2126
|
+
suggestExplicitAny: "Use `any` instead to explicitly opt out of type safety.",
|
|
2127
|
+
suggestExplicitError: "Use `Error` instead."
|
|
2110
2128
|
},
|
|
2111
2129
|
schema: [
|
|
2112
2130
|
{
|
|
@@ -2116,6 +2134,11 @@ var noImplicitAnyCatchRule = ruleCreator({
|
|
|
2116
2134
|
type: "boolean",
|
|
2117
2135
|
description: "Allow error variable to be explicitly typed as `any`.",
|
|
2118
2136
|
default: true
|
|
2137
|
+
},
|
|
2138
|
+
allowExplicitError: {
|
|
2139
|
+
type: "boolean",
|
|
2140
|
+
description: "Allow narrowing error type to `Error`.",
|
|
2141
|
+
default: false
|
|
2119
2142
|
}
|
|
2120
2143
|
},
|
|
2121
2144
|
type: "object"
|
|
@@ -2126,7 +2149,7 @@ var noImplicitAnyCatchRule = ruleCreator({
|
|
|
2126
2149
|
name: "no-implicit-any-catch",
|
|
2127
2150
|
create: (context) => {
|
|
2128
2151
|
const [config = {}] = context.options;
|
|
2129
|
-
const { allowExplicitAny = true } = config;
|
|
2152
|
+
const { allowExplicitAny = true, allowExplicitError = false } = config;
|
|
2130
2153
|
const { couldBeObservable } = getTypeServices(context);
|
|
2131
2154
|
const sourceCode = context.sourceCode;
|
|
2132
2155
|
function createReplacerFix(typeAnnotation, replaceWith) {
|
|
@@ -2171,20 +2194,33 @@ var noImplicitAnyCatchRule = ruleCreator({
|
|
|
2171
2194
|
]
|
|
2172
2195
|
});
|
|
2173
2196
|
} else if (type !== _utils.AST_NODE_TYPES.TSUnknownKeyword) {
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2197
|
+
let isAllowedError = false;
|
|
2198
|
+
if (allowExplicitError && type === _utils.AST_NODE_TYPES.TSTypeReference) {
|
|
2199
|
+
const typeRef = typeAnnotation.typeAnnotation;
|
|
2200
|
+
if (isIdentifier(typeRef.typeName)) {
|
|
2201
|
+
isAllowedError = typeRef.typeName.name === "Error";
|
|
2202
|
+
}
|
|
2203
|
+
}
|
|
2204
|
+
if (!isAllowedError) {
|
|
2205
|
+
context.report({
|
|
2206
|
+
messageId: allowExplicitError ? "narrowedAllowError" : "narrowed",
|
|
2207
|
+
node: param,
|
|
2208
|
+
suggest: [
|
|
2209
|
+
{
|
|
2210
|
+
messageId: "suggestExplicitUnknown",
|
|
2211
|
+
fix: createReplacerFix(typeAnnotation, "unknown")
|
|
2212
|
+
},
|
|
2213
|
+
allowExplicitAny ? {
|
|
2214
|
+
messageId: "suggestExplicitAny",
|
|
2215
|
+
fix: createReplacerFix(typeAnnotation, "any")
|
|
2216
|
+
} : null,
|
|
2217
|
+
allowExplicitError && !isAllowedError ? {
|
|
2218
|
+
messageId: "suggestExplicitError",
|
|
2219
|
+
fix: createReplacerFix(typeAnnotation, "Error")
|
|
2220
|
+
} : null
|
|
2221
|
+
].filter((x) => !!x)
|
|
2222
|
+
});
|
|
2223
|
+
}
|
|
2188
2224
|
}
|
|
2189
2225
|
} else {
|
|
2190
2226
|
const hasRestParams = restParams.length > 0;
|
|
@@ -3356,7 +3392,7 @@ var noUnboundMethodsRule = ruleCreator({
|
|
|
3356
3392
|
const { couldBeObservable, couldBeSubscription } = getTypeServices(context);
|
|
3357
3393
|
const nodeMap = /* @__PURE__ */ new WeakMap();
|
|
3358
3394
|
const [config = {}] = context.options;
|
|
3359
|
-
const { allowTypes =
|
|
3395
|
+
const { allowTypes = DEFAULT_UNBOUND_ALLOWED_TYPES } = config;
|
|
3360
3396
|
function mapArguments(node) {
|
|
3361
3397
|
node.arguments.filter(isMemberExpression).forEach((arg) => {
|
|
3362
3398
|
const argType = getTypeAtLocation(arg);
|
|
@@ -3678,6 +3714,16 @@ var noUnsafeSubjectNext = ruleCreator({
|
|
|
3678
3714
|
// src/rules/no-unsafe-switchmap.ts
|
|
3679
3715
|
|
|
3680
3716
|
var _decamelize = require('decamelize'); var _decamelize2 = _interopRequireDefault(_decamelize);
|
|
3717
|
+
var DEFAULT_DISALLOW = [
|
|
3718
|
+
"add",
|
|
3719
|
+
"create",
|
|
3720
|
+
"delete",
|
|
3721
|
+
"post",
|
|
3722
|
+
"put",
|
|
3723
|
+
"remove",
|
|
3724
|
+
"set",
|
|
3725
|
+
"update"
|
|
3726
|
+
];
|
|
3681
3727
|
var defaultOptions15 = [];
|
|
3682
3728
|
var noUnsafeSwitchmapRule = ruleCreator({
|
|
3683
3729
|
defaultOptions: defaultOptions15,
|
|
@@ -3704,7 +3750,8 @@ var noUnsafeSwitchmapRule = ruleCreator({
|
|
|
3704
3750
|
oneOf: [
|
|
3705
3751
|
{ type: "string", description: "A regular expression string." },
|
|
3706
3752
|
{ type: "array", items: { type: "string" }, description: "An array of words." }
|
|
3707
|
-
]
|
|
3753
|
+
],
|
|
3754
|
+
default: DEFAULT_DISALLOW
|
|
3708
3755
|
},
|
|
3709
3756
|
observable: {
|
|
3710
3757
|
type: "string",
|
|
@@ -3727,29 +3774,15 @@ var noUnsafeSwitchmapRule = ruleCreator({
|
|
|
3727
3774
|
name: "no-unsafe-switchmap",
|
|
3728
3775
|
create: (context) => {
|
|
3729
3776
|
var _a, _b, _c;
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
"create",
|
|
3733
|
-
"delete",
|
|
3734
|
-
"post",
|
|
3735
|
-
"put",
|
|
3736
|
-
"remove",
|
|
3737
|
-
"set",
|
|
3738
|
-
"update"
|
|
3739
|
-
];
|
|
3740
|
-
let allowRegExp;
|
|
3741
|
-
let disallowRegExp;
|
|
3742
|
-
let observableRegExp;
|
|
3777
|
+
let allowRegExp = void 0;
|
|
3778
|
+
let disallowRegExp = void 0;
|
|
3743
3779
|
const [config = {}] = context.options;
|
|
3744
|
-
if (config.allow
|
|
3780
|
+
if (config.allow) {
|
|
3745
3781
|
allowRegExp = createRegExpForWords((_a = config.allow) != null ? _a : []);
|
|
3746
|
-
disallowRegExp = createRegExpForWords((_b = config.disallow) != null ? _b : []);
|
|
3747
|
-
observableRegExp = new RegExp((_c = config.observable) != null ? _c : defaultObservable);
|
|
3748
3782
|
} else {
|
|
3749
|
-
|
|
3750
|
-
disallowRegExp = createRegExpForWords(defaultDisallow);
|
|
3751
|
-
observableRegExp = new RegExp(defaultObservable);
|
|
3783
|
+
disallowRegExp = createRegExpForWords((_b = config.disallow) != null ? _b : DEFAULT_DISALLOW);
|
|
3752
3784
|
}
|
|
3785
|
+
const observableRegExp = new RegExp((_c = config.observable) != null ? _c : defaultObservable);
|
|
3753
3786
|
const { couldBeObservable } = getTypeServices(context);
|
|
3754
3787
|
function shouldDisallow(args) {
|
|
3755
3788
|
const names = args.map((arg) => {
|
|
@@ -4317,7 +4350,8 @@ var throwErrorRule = ruleCreator({
|
|
|
4317
4350
|
requiresTypeChecking: true
|
|
4318
4351
|
},
|
|
4319
4352
|
messages: {
|
|
4320
|
-
forbidden: "Passing non-Error values is forbidden."
|
|
4353
|
+
forbidden: "Passing non-Error values is forbidden.",
|
|
4354
|
+
suggestErrorConstructor: "Wrap string in Error constructor."
|
|
4321
4355
|
},
|
|
4322
4356
|
schema: [
|
|
4323
4357
|
{
|
|
@@ -4328,7 +4362,8 @@ var throwErrorRule = ruleCreator({
|
|
|
4328
4362
|
type: "object"
|
|
4329
4363
|
}
|
|
4330
4364
|
],
|
|
4331
|
-
type: "problem"
|
|
4365
|
+
type: "problem",
|
|
4366
|
+
hasSuggestions: true
|
|
4332
4367
|
},
|
|
4333
4368
|
name: "throw-error",
|
|
4334
4369
|
create: (context) => {
|
|
@@ -4356,9 +4391,22 @@ var throwErrorRule = ruleCreator({
|
|
|
4356
4391
|
if (couldBeType(type, /^Error$/)) {
|
|
4357
4392
|
return;
|
|
4358
4393
|
}
|
|
4394
|
+
const isString = isTemplateLiteral(reportNode) || isLiteral(reportNode) && typeof reportNode.value === "string";
|
|
4359
4395
|
context.report({
|
|
4360
4396
|
messageId: "forbidden",
|
|
4361
|
-
node: reportNode
|
|
4397
|
+
node: reportNode,
|
|
4398
|
+
...isString && {
|
|
4399
|
+
suggest: [
|
|
4400
|
+
{
|
|
4401
|
+
messageId: "suggestErrorConstructor",
|
|
4402
|
+
fix: (fixer) => {
|
|
4403
|
+
const sourceCode = context.sourceCode;
|
|
4404
|
+
const nodeText = sourceCode.getText(reportNode);
|
|
4405
|
+
return fixer.replaceText(reportNode, `new Error(${nodeText})`);
|
|
4406
|
+
}
|
|
4407
|
+
}
|
|
4408
|
+
]
|
|
4409
|
+
}
|
|
4362
4410
|
});
|
|
4363
4411
|
}
|
|
4364
4412
|
function checkThrowError(node) {
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// package.json
|
|
2
2
|
var name = "eslint-plugin-rxjs-x";
|
|
3
|
-
var version = "0.9.
|
|
3
|
+
var version = "0.9.3";
|
|
4
4
|
|
|
5
5
|
// src/configs/recommended.ts
|
|
6
6
|
var createRecommendedConfig = (plugin2) => ({
|
|
@@ -117,7 +117,10 @@ function couldBeType(type, name2, qualified) {
|
|
|
117
117
|
if (tsutils.isTypeReference(type)) {
|
|
118
118
|
type = type.target;
|
|
119
119
|
}
|
|
120
|
-
if (isType(type, name2, qualified)) {
|
|
120
|
+
if (isType(type.symbol, name2, qualified)) {
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
123
|
+
if (type.aliasSymbol && isType(type.aliasSymbol, name2, qualified)) {
|
|
121
124
|
return true;
|
|
122
125
|
}
|
|
123
126
|
if (tsutils.isUnionOrIntersectionType(type)) {
|
|
@@ -132,16 +135,16 @@ function couldBeType(type, name2, qualified) {
|
|
|
132
135
|
}
|
|
133
136
|
return false;
|
|
134
137
|
}
|
|
135
|
-
function isType(
|
|
136
|
-
if (!
|
|
138
|
+
function isType(symbol, name2, qualified) {
|
|
139
|
+
if (!symbol) {
|
|
137
140
|
return false;
|
|
138
141
|
}
|
|
139
142
|
if (qualified && !qualified.name.test(
|
|
140
|
-
qualified.typeChecker.getFullyQualifiedName(
|
|
143
|
+
qualified.typeChecker.getFullyQualifiedName(symbol)
|
|
141
144
|
)) {
|
|
142
145
|
return false;
|
|
143
146
|
}
|
|
144
|
-
return typeof name2 === "string" ?
|
|
147
|
+
return typeof name2 === "string" ? symbol.name === name2 : Boolean(symbol.name.match(name2));
|
|
145
148
|
}
|
|
146
149
|
function couldImplement(type, name2, qualified) {
|
|
147
150
|
const { symbol } = type;
|
|
@@ -274,6 +277,9 @@ function isJSXExpressionContainer(node) {
|
|
|
274
277
|
function isLiteral(node) {
|
|
275
278
|
return node.type === AST_NODE_TYPES.Literal;
|
|
276
279
|
}
|
|
280
|
+
function isTemplateLiteral(node) {
|
|
281
|
+
return node.type === AST_NODE_TYPES.TemplateLiteral;
|
|
282
|
+
}
|
|
277
283
|
function isMemberExpression(node) {
|
|
278
284
|
return node.type === AST_NODE_TYPES.MemberExpression;
|
|
279
285
|
}
|
|
@@ -1103,19 +1109,20 @@ var noCreateRule = ruleCreator({
|
|
|
1103
1109
|
defaultOptions: [],
|
|
1104
1110
|
meta: {
|
|
1105
1111
|
docs: {
|
|
1106
|
-
description: "Disallow the static `Observable.create`
|
|
1112
|
+
description: "Disallow the static `Observable.create` and `Subject.create` functions.",
|
|
1107
1113
|
recommended: "recommended",
|
|
1108
1114
|
requiresTypeChecking: true
|
|
1109
1115
|
},
|
|
1110
1116
|
messages: {
|
|
1111
|
-
forbidden: "Observable.create is forbidden; use new Observable."
|
|
1117
|
+
forbidden: "Observable.create is forbidden; use new Observable.",
|
|
1118
|
+
forbiddenSubject: "Subject.create is forbidden."
|
|
1112
1119
|
},
|
|
1113
1120
|
schema: [],
|
|
1114
1121
|
type: "problem"
|
|
1115
1122
|
},
|
|
1116
1123
|
name: "no-create",
|
|
1117
1124
|
create: (context) => {
|
|
1118
|
-
const { couldBeObservable } = getTypeServices(context);
|
|
1125
|
+
const { couldBeObservable, couldBeType: couldBeType2 } = getTypeServices(context);
|
|
1119
1126
|
return {
|
|
1120
1127
|
"CallExpression > MemberExpression[object.name='Observable'] > Identifier[name='create']": (node) => {
|
|
1121
1128
|
const memberExpression = node.parent;
|
|
@@ -1125,6 +1132,15 @@ var noCreateRule = ruleCreator({
|
|
|
1125
1132
|
node
|
|
1126
1133
|
});
|
|
1127
1134
|
}
|
|
1135
|
+
},
|
|
1136
|
+
"CallExpression > MemberExpression[object.name=/^(Subject|BehaviorSubject|AsyncSubject|ReplaySubject)$/] > Identifier[name='create']": (node) => {
|
|
1137
|
+
const memberExpression = node.parent;
|
|
1138
|
+
if (couldBeType2(memberExpression.object, /^(Subject|BehaviorSubject|AsyncSubject|ReplaySubject)$/)) {
|
|
1139
|
+
context.report({
|
|
1140
|
+
messageId: "forbiddenSubject",
|
|
1141
|
+
node
|
|
1142
|
+
});
|
|
1143
|
+
}
|
|
1128
1144
|
}
|
|
1129
1145
|
};
|
|
1130
1146
|
}
|
|
@@ -2090,7 +2106,7 @@ var noImplicitAnyCatchRule = ruleCreator({
|
|
|
2090
2106
|
defaultOptions: defaultOptions8,
|
|
2091
2107
|
meta: {
|
|
2092
2108
|
docs: {
|
|
2093
|
-
description: "Disallow implicit `any` error parameters in `catchError`
|
|
2109
|
+
description: "Disallow implicit `any` error parameters in `catchError`, `subscribe`, and `tap`.",
|
|
2094
2110
|
recommended: {
|
|
2095
2111
|
recommended: true,
|
|
2096
2112
|
strict: [{
|
|
@@ -2105,8 +2121,10 @@ var noImplicitAnyCatchRule = ruleCreator({
|
|
|
2105
2121
|
explicitAny: "Explicit `any` in error callback.",
|
|
2106
2122
|
implicitAny: "Implicit `any` in error callback.",
|
|
2107
2123
|
narrowed: "Error type must be `unknown` or `any`.",
|
|
2124
|
+
narrowedAllowError: "Error type must be `unknown`, `any`, or `Error`.",
|
|
2108
2125
|
suggestExplicitUnknown: "Use `unknown` instead to explicitly and safely assert the type is correct.",
|
|
2109
|
-
suggestExplicitAny: "Use `any` instead to explicitly opt out of type safety."
|
|
2126
|
+
suggestExplicitAny: "Use `any` instead to explicitly opt out of type safety.",
|
|
2127
|
+
suggestExplicitError: "Use `Error` instead."
|
|
2110
2128
|
},
|
|
2111
2129
|
schema: [
|
|
2112
2130
|
{
|
|
@@ -2116,6 +2134,11 @@ var noImplicitAnyCatchRule = ruleCreator({
|
|
|
2116
2134
|
type: "boolean",
|
|
2117
2135
|
description: "Allow error variable to be explicitly typed as `any`.",
|
|
2118
2136
|
default: true
|
|
2137
|
+
},
|
|
2138
|
+
allowExplicitError: {
|
|
2139
|
+
type: "boolean",
|
|
2140
|
+
description: "Allow narrowing error type to `Error`.",
|
|
2141
|
+
default: false
|
|
2119
2142
|
}
|
|
2120
2143
|
},
|
|
2121
2144
|
type: "object"
|
|
@@ -2126,7 +2149,7 @@ var noImplicitAnyCatchRule = ruleCreator({
|
|
|
2126
2149
|
name: "no-implicit-any-catch",
|
|
2127
2150
|
create: (context) => {
|
|
2128
2151
|
const [config = {}] = context.options;
|
|
2129
|
-
const { allowExplicitAny = true } = config;
|
|
2152
|
+
const { allowExplicitAny = true, allowExplicitError = false } = config;
|
|
2130
2153
|
const { couldBeObservable } = getTypeServices(context);
|
|
2131
2154
|
const sourceCode = context.sourceCode;
|
|
2132
2155
|
function createReplacerFix(typeAnnotation, replaceWith) {
|
|
@@ -2171,20 +2194,33 @@ var noImplicitAnyCatchRule = ruleCreator({
|
|
|
2171
2194
|
]
|
|
2172
2195
|
});
|
|
2173
2196
|
} else if (type !== AST_NODE_TYPES4.TSUnknownKeyword) {
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2197
|
+
let isAllowedError = false;
|
|
2198
|
+
if (allowExplicitError && type === AST_NODE_TYPES4.TSTypeReference) {
|
|
2199
|
+
const typeRef = typeAnnotation.typeAnnotation;
|
|
2200
|
+
if (isIdentifier(typeRef.typeName)) {
|
|
2201
|
+
isAllowedError = typeRef.typeName.name === "Error";
|
|
2202
|
+
}
|
|
2203
|
+
}
|
|
2204
|
+
if (!isAllowedError) {
|
|
2205
|
+
context.report({
|
|
2206
|
+
messageId: allowExplicitError ? "narrowedAllowError" : "narrowed",
|
|
2207
|
+
node: param,
|
|
2208
|
+
suggest: [
|
|
2209
|
+
{
|
|
2210
|
+
messageId: "suggestExplicitUnknown",
|
|
2211
|
+
fix: createReplacerFix(typeAnnotation, "unknown")
|
|
2212
|
+
},
|
|
2213
|
+
allowExplicitAny ? {
|
|
2214
|
+
messageId: "suggestExplicitAny",
|
|
2215
|
+
fix: createReplacerFix(typeAnnotation, "any")
|
|
2216
|
+
} : null,
|
|
2217
|
+
allowExplicitError && !isAllowedError ? {
|
|
2218
|
+
messageId: "suggestExplicitError",
|
|
2219
|
+
fix: createReplacerFix(typeAnnotation, "Error")
|
|
2220
|
+
} : null
|
|
2221
|
+
].filter((x) => !!x)
|
|
2222
|
+
});
|
|
2223
|
+
}
|
|
2188
2224
|
}
|
|
2189
2225
|
} else {
|
|
2190
2226
|
const hasRestParams = restParams.length > 0;
|
|
@@ -3356,7 +3392,7 @@ var noUnboundMethodsRule = ruleCreator({
|
|
|
3356
3392
|
const { couldBeObservable, couldBeSubscription } = getTypeServices(context);
|
|
3357
3393
|
const nodeMap = /* @__PURE__ */ new WeakMap();
|
|
3358
3394
|
const [config = {}] = context.options;
|
|
3359
|
-
const { allowTypes =
|
|
3395
|
+
const { allowTypes = DEFAULT_UNBOUND_ALLOWED_TYPES } = config;
|
|
3360
3396
|
function mapArguments(node) {
|
|
3361
3397
|
node.arguments.filter(isMemberExpression).forEach((arg) => {
|
|
3362
3398
|
const argType = getTypeAtLocation(arg);
|
|
@@ -3678,6 +3714,16 @@ var noUnsafeSubjectNext = ruleCreator({
|
|
|
3678
3714
|
// src/rules/no-unsafe-switchmap.ts
|
|
3679
3715
|
import { stripIndent as stripIndent7 } from "common-tags";
|
|
3680
3716
|
import decamelize from "decamelize";
|
|
3717
|
+
var DEFAULT_DISALLOW = [
|
|
3718
|
+
"add",
|
|
3719
|
+
"create",
|
|
3720
|
+
"delete",
|
|
3721
|
+
"post",
|
|
3722
|
+
"put",
|
|
3723
|
+
"remove",
|
|
3724
|
+
"set",
|
|
3725
|
+
"update"
|
|
3726
|
+
];
|
|
3681
3727
|
var defaultOptions15 = [];
|
|
3682
3728
|
var noUnsafeSwitchmapRule = ruleCreator({
|
|
3683
3729
|
defaultOptions: defaultOptions15,
|
|
@@ -3704,7 +3750,8 @@ var noUnsafeSwitchmapRule = ruleCreator({
|
|
|
3704
3750
|
oneOf: [
|
|
3705
3751
|
{ type: "string", description: "A regular expression string." },
|
|
3706
3752
|
{ type: "array", items: { type: "string" }, description: "An array of words." }
|
|
3707
|
-
]
|
|
3753
|
+
],
|
|
3754
|
+
default: DEFAULT_DISALLOW
|
|
3708
3755
|
},
|
|
3709
3756
|
observable: {
|
|
3710
3757
|
type: "string",
|
|
@@ -3727,29 +3774,15 @@ var noUnsafeSwitchmapRule = ruleCreator({
|
|
|
3727
3774
|
name: "no-unsafe-switchmap",
|
|
3728
3775
|
create: (context) => {
|
|
3729
3776
|
var _a, _b, _c;
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
"create",
|
|
3733
|
-
"delete",
|
|
3734
|
-
"post",
|
|
3735
|
-
"put",
|
|
3736
|
-
"remove",
|
|
3737
|
-
"set",
|
|
3738
|
-
"update"
|
|
3739
|
-
];
|
|
3740
|
-
let allowRegExp;
|
|
3741
|
-
let disallowRegExp;
|
|
3742
|
-
let observableRegExp;
|
|
3777
|
+
let allowRegExp = void 0;
|
|
3778
|
+
let disallowRegExp = void 0;
|
|
3743
3779
|
const [config = {}] = context.options;
|
|
3744
|
-
if (config.allow
|
|
3780
|
+
if (config.allow) {
|
|
3745
3781
|
allowRegExp = createRegExpForWords((_a = config.allow) != null ? _a : []);
|
|
3746
|
-
disallowRegExp = createRegExpForWords((_b = config.disallow) != null ? _b : []);
|
|
3747
|
-
observableRegExp = new RegExp((_c = config.observable) != null ? _c : defaultObservable);
|
|
3748
3782
|
} else {
|
|
3749
|
-
|
|
3750
|
-
disallowRegExp = createRegExpForWords(defaultDisallow);
|
|
3751
|
-
observableRegExp = new RegExp(defaultObservable);
|
|
3783
|
+
disallowRegExp = createRegExpForWords((_b = config.disallow) != null ? _b : DEFAULT_DISALLOW);
|
|
3752
3784
|
}
|
|
3785
|
+
const observableRegExp = new RegExp((_c = config.observable) != null ? _c : defaultObservable);
|
|
3753
3786
|
const { couldBeObservable } = getTypeServices(context);
|
|
3754
3787
|
function shouldDisallow(args) {
|
|
3755
3788
|
const names = args.map((arg) => {
|
|
@@ -4317,7 +4350,8 @@ var throwErrorRule = ruleCreator({
|
|
|
4317
4350
|
requiresTypeChecking: true
|
|
4318
4351
|
},
|
|
4319
4352
|
messages: {
|
|
4320
|
-
forbidden: "Passing non-Error values is forbidden."
|
|
4353
|
+
forbidden: "Passing non-Error values is forbidden.",
|
|
4354
|
+
suggestErrorConstructor: "Wrap string in Error constructor."
|
|
4321
4355
|
},
|
|
4322
4356
|
schema: [
|
|
4323
4357
|
{
|
|
@@ -4328,7 +4362,8 @@ var throwErrorRule = ruleCreator({
|
|
|
4328
4362
|
type: "object"
|
|
4329
4363
|
}
|
|
4330
4364
|
],
|
|
4331
|
-
type: "problem"
|
|
4365
|
+
type: "problem",
|
|
4366
|
+
hasSuggestions: true
|
|
4332
4367
|
},
|
|
4333
4368
|
name: "throw-error",
|
|
4334
4369
|
create: (context) => {
|
|
@@ -4356,9 +4391,22 @@ var throwErrorRule = ruleCreator({
|
|
|
4356
4391
|
if (couldBeType(type, /^Error$/)) {
|
|
4357
4392
|
return;
|
|
4358
4393
|
}
|
|
4394
|
+
const isString = isTemplateLiteral(reportNode) || isLiteral(reportNode) && typeof reportNode.value === "string";
|
|
4359
4395
|
context.report({
|
|
4360
4396
|
messageId: "forbidden",
|
|
4361
|
-
node: reportNode
|
|
4397
|
+
node: reportNode,
|
|
4398
|
+
...isString && {
|
|
4399
|
+
suggest: [
|
|
4400
|
+
{
|
|
4401
|
+
messageId: "suggestErrorConstructor",
|
|
4402
|
+
fix: (fixer) => {
|
|
4403
|
+
const sourceCode = context.sourceCode;
|
|
4404
|
+
const nodeText = sourceCode.getText(reportNode);
|
|
4405
|
+
return fixer.replaceText(reportNode, `new Error(${nodeText})`);
|
|
4406
|
+
}
|
|
4407
|
+
}
|
|
4408
|
+
]
|
|
4409
|
+
}
|
|
4362
4410
|
});
|
|
4363
4411
|
}
|
|
4364
4412
|
function checkThrowError(node) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-rxjs-x",
|
|
3
3
|
"type": "commonjs",
|
|
4
|
-
"version": "0.9.
|
|
4
|
+
"version": "0.9.3",
|
|
5
5
|
"packageManager": "yarn@4.12.0+sha512.f45ab632439a67f8bc759bf32ead036a1f413287b9042726b7cc4818b7b49e14e9423ba49b18f9e06ea4941c1ad062385b1d8760a8d5091a1a31e5f6219afca8",
|
|
6
6
|
"description": "Modern ESLint plugin for RxJS",
|
|
7
7
|
"author": "Jason Weinzierl <weinzierljason@gmail.com>",
|
|
@@ -84,12 +84,12 @@
|
|
|
84
84
|
"@typescript/vfs": "^1.6.2",
|
|
85
85
|
"@vitest/coverage-v8": "^3.2.4",
|
|
86
86
|
"@vitest/eslint-plugin": "^1.4.0",
|
|
87
|
-
"bumpp": "^10.4.
|
|
87
|
+
"bumpp": "^10.4.1",
|
|
88
88
|
"eslint": "^9.39.2",
|
|
89
89
|
"eslint-config-flat-gitignore": "^2.1.0",
|
|
90
90
|
"eslint-doc-generator": "^2.4.0",
|
|
91
91
|
"eslint-import-resolver-typescript": "^4.4.4",
|
|
92
|
-
"eslint-plugin-eslint-plugin": "
|
|
92
|
+
"eslint-plugin-eslint-plugin": "patch:eslint-plugin-eslint-plugin@npm%3A7.3.0#~/.yarn/patches/eslint-plugin-eslint-plugin-npm-7.3.0-d800475165.patch",
|
|
93
93
|
"eslint-plugin-import-x": "^4.16.1",
|
|
94
94
|
"eslint-plugin-n": "^17.23.2",
|
|
95
95
|
"markdownlint-cli2": "~0.19.0",
|