@ngrx/eslint-plugin 17.0.1 → 17.1.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ngrx/eslint-plugin",
3
- "version": "17.0.1",
3
+ "version": "17.1.0",
4
4
  "description": "NgRx ESLint Plugin",
5
5
  "repository": {
6
6
  "type": "git",
@@ -194,8 +194,18 @@ exports.default = (0, rule_creator_1.createRule)({
194
194
  }
195
195
  return [typeChecker.typeToString(actionType)];
196
196
  }
197
+ var firstPipe = true;
197
198
  return _a = {},
198
- _a["".concat(utils_1.createEffectExpression, ":not([arguments.1]:has(Property[key.name='dispatch'][value.value=false])) CallExpression[callee.property.name='pipe'][callee.object.property.name=").concat(actionsNames, "]")] = checkNode,
199
+ _a["".concat(utils_1.createEffectExpression, ":not([arguments.1]:has(Property[key.name='dispatch'][value.value=false])) CallExpression[callee.property.name='pipe'][callee.object.property.name=").concat(actionsNames, "]")] = function (node) {
200
+ if (firstPipe) {
201
+ checkNode(node);
202
+ firstPipe = false;
203
+ return;
204
+ }
205
+ },
206
+ _a["".concat(utils_1.createEffectExpression, ":not([arguments.1]:has(Property[key.name='dispatch'][value.value=false])) CallExpression[callee.property.name='pipe']:exit")] = function () {
207
+ firstPipe = true;
208
+ },
199
209
  _a;
200
210
  },
201
211
  });
@@ -1 +1 @@
1
- {"version":3,"file":"avoid-cyclic-effects.js","sourceRoot":"","sources":["../../../../../../modules/eslint-plugin/src/rules/effects/avoid-cyclic-effects.ts"],"names":[],"mappings":"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","sourcesContent":["import type { TSESTree } from '@typescript-eslint/experimental-utils';\nimport { getTypeServices } from 'eslint-etc';\nimport * as path from 'path';\nimport * as ts from 'typescript';\nimport { createRule } from '../../rule-creator';\nimport {\n asPattern,\n createEffectExpression,\n getNgRxEffectActions,\n isCallExpression,\n isIdentifier,\n isTypeReference,\n} from '../../utils';\n\nexport const messageId = 'avoidCyclicEffects';\n\ntype MessageIds = typeof messageId;\ntype Options = readonly [];\n\n// This rule is a modified version (to support dispatch: false) from the eslint-plugin-rxjs plugin.\n// The original implementation can be found at https://github.com/cartant/eslint-plugin-rxjs/blob/main/source/rules/no-cyclic-action.ts\n// Thank you Nicholas Jamieson (@cartant).\n\nexport default createRule<Options, MessageIds>({\n name: path.parse(__filename).name,\n meta: {\n type: 'problem',\n ngrxModule: 'effects',\n docs: {\n description: 'Avoid `Effect` that re-emit filtered actions.',\n recommended: 'warn',\n requiresTypeChecking: true,\n },\n schema: [],\n messages: {\n [messageId]: '`Effect` that re-emit filtered actions are forbidden.',\n },\n },\n defaultOptions: [],\n create: (context) => {\n const { identifiers = [] } = getNgRxEffectActions(context);\n const actionsNames = identifiers.length > 0 ? asPattern(identifiers) : null;\n\n if (!actionsNames) {\n return {};\n }\n\n const { getType, typeChecker } = getTypeServices(context);\n\n function checkNode(pipeCallExpression: TSESTree.CallExpression) {\n const operatorCallExpression = pipeCallExpression.arguments.find(\n (arg) =>\n isCallExpression(arg) &&\n isIdentifier(arg.callee) &&\n arg.callee.name === 'ofType'\n );\n if (!operatorCallExpression) {\n return;\n }\n const operatorType = getType(operatorCallExpression);\n const [signature] = typeChecker.getSignaturesOfType(\n operatorType,\n ts.SignatureKind.Call\n );\n\n if (!signature) {\n return;\n }\n const operatorReturnType =\n typeChecker.getReturnTypeOfSignature(signature);\n if (!isTypeReference(operatorReturnType)) {\n return;\n }\n const [operatorElementType] =\n typeChecker.getTypeArguments(operatorReturnType);\n if (!operatorElementType) {\n return;\n }\n\n const pipeType = getType(pipeCallExpression);\n if (!isTypeReference(pipeType)) {\n return;\n }\n const [pipeElementType] = typeChecker.getTypeArguments(pipeType);\n if (!pipeElementType) {\n return;\n }\n\n const operatorActionTypes = getActionTypes(operatorElementType);\n const pipeActionTypes = getActionTypes(pipeElementType);\n\n for (const actionType of operatorActionTypes) {\n if (pipeActionTypes.includes(actionType)) {\n context.report({\n node: pipeCallExpression.callee,\n messageId,\n });\n return;\n }\n }\n }\n\n function getActionType(symbol: ts.Symbol): ts.Type | null {\n const { valueDeclaration } = symbol;\n\n if (!valueDeclaration) {\n return null;\n }\n\n if (valueDeclaration.kind === ts.SyntaxKind.PropertyDeclaration) {\n const { parent } = symbol as typeof symbol & { parent: ts.Symbol };\n return parent.valueDeclaration\n ? typeChecker.getTypeOfSymbolAtLocation(\n parent,\n parent.valueDeclaration\n )\n : null;\n }\n\n return typeChecker.getTypeOfSymbolAtLocation(symbol, valueDeclaration);\n }\n\n function getActionTypes(type: ts.Type): string[] {\n if (type.isUnion()) {\n const memberActionTypes: string[] = [];\n for (const memberType of type.types) {\n memberActionTypes.push(...getActionTypes(memberType));\n }\n return memberActionTypes;\n }\n\n const symbol = typeChecker.getPropertyOfType(type, 'type');\n\n if (!symbol) {\n return [];\n }\n\n const actionType = getActionType(symbol);\n\n if (!actionType) {\n return [];\n }\n\n // TODO: support \"dynamic\" types\n // e.g. const genericFoo = createAction(`${subject} FOO`); (resolves to 'string')\n if (typeChecker.typeToString(actionType) === 'string') {\n return [];\n }\n return [typeChecker.typeToString(actionType)];\n }\n\n return {\n [`${createEffectExpression}:not([arguments.1]:has(Property[key.name='dispatch'][value.value=false])) CallExpression[callee.property.name='pipe'][callee.object.property.name=${actionsNames}]`]:\n checkNode,\n };\n },\n});\n"]}
1
+ {"version":3,"file":"avoid-cyclic-effects.js","sourceRoot":"","sources":["../../../../../../modules/eslint-plugin/src/rules/effects/avoid-cyclic-effects.ts"],"names":[],"mappings":"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","sourcesContent":["import type { TSESTree } from '@typescript-eslint/experimental-utils';\nimport { getTypeServices } from 'eslint-etc';\nimport * as path from 'path';\nimport * as ts from 'typescript';\nimport { createRule } from '../../rule-creator';\nimport {\n asPattern,\n createEffectExpression,\n getNgRxEffectActions,\n isCallExpression,\n isIdentifier,\n isTypeReference,\n} from '../../utils';\n\nexport const messageId = 'avoidCyclicEffects';\n\ntype MessageIds = typeof messageId;\ntype Options = readonly [];\n\n// This rule is a modified version (to support dispatch: false) from the eslint-plugin-rxjs plugin.\n// The original implementation can be found at https://github.com/cartant/eslint-plugin-rxjs/blob/main/source/rules/no-cyclic-action.ts\n// Thank you Nicholas Jamieson (@cartant).\n\nexport default createRule<Options, MessageIds>({\n name: path.parse(__filename).name,\n meta: {\n type: 'problem',\n ngrxModule: 'effects',\n docs: {\n description: 'Avoid `Effect` that re-emit filtered actions.',\n recommended: 'warn',\n requiresTypeChecking: true,\n },\n schema: [],\n messages: {\n [messageId]: '`Effect` that re-emit filtered actions are forbidden.',\n },\n },\n defaultOptions: [],\n create: (context) => {\n const { identifiers = [] } = getNgRxEffectActions(context);\n const actionsNames = identifiers.length > 0 ? asPattern(identifiers) : null;\n\n if (!actionsNames) {\n return {};\n }\n\n const { getType, typeChecker } = getTypeServices(context);\n\n function checkNode(pipeCallExpression: TSESTree.CallExpression) {\n const operatorCallExpression = pipeCallExpression.arguments.find(\n (arg) =>\n isCallExpression(arg) &&\n isIdentifier(arg.callee) &&\n arg.callee.name === 'ofType'\n );\n if (!operatorCallExpression) {\n return;\n }\n const operatorType = getType(operatorCallExpression);\n const [signature] = typeChecker.getSignaturesOfType(\n operatorType,\n ts.SignatureKind.Call\n );\n\n if (!signature) {\n return;\n }\n const operatorReturnType =\n typeChecker.getReturnTypeOfSignature(signature);\n if (!isTypeReference(operatorReturnType)) {\n return;\n }\n const [operatorElementType] =\n typeChecker.getTypeArguments(operatorReturnType);\n if (!operatorElementType) {\n return;\n }\n\n const pipeType = getType(pipeCallExpression);\n if (!isTypeReference(pipeType)) {\n return;\n }\n const [pipeElementType] = typeChecker.getTypeArguments(pipeType);\n if (!pipeElementType) {\n return;\n }\n\n const operatorActionTypes = getActionTypes(operatorElementType);\n const pipeActionTypes = getActionTypes(pipeElementType);\n\n for (const actionType of operatorActionTypes) {\n if (pipeActionTypes.includes(actionType)) {\n context.report({\n node: pipeCallExpression.callee,\n messageId,\n });\n return;\n }\n }\n }\n\n function getActionType(symbol: ts.Symbol): ts.Type | null {\n const { valueDeclaration } = symbol;\n\n if (!valueDeclaration) {\n return null;\n }\n\n if (valueDeclaration.kind === ts.SyntaxKind.PropertyDeclaration) {\n const { parent } = symbol as typeof symbol & { parent: ts.Symbol };\n return parent.valueDeclaration\n ? typeChecker.getTypeOfSymbolAtLocation(\n parent,\n parent.valueDeclaration\n )\n : null;\n }\n\n return typeChecker.getTypeOfSymbolAtLocation(symbol, valueDeclaration);\n }\n\n function getActionTypes(type: ts.Type): string[] {\n if (type.isUnion()) {\n const memberActionTypes: string[] = [];\n for (const memberType of type.types) {\n memberActionTypes.push(...getActionTypes(memberType));\n }\n return memberActionTypes;\n }\n\n const symbol = typeChecker.getPropertyOfType(type, 'type');\n\n if (!symbol) {\n return [];\n }\n\n const actionType = getActionType(symbol);\n\n if (!actionType) {\n return [];\n }\n\n // TODO: support \"dynamic\" types\n // e.g. const genericFoo = createAction(`${subject} FOO`); (resolves to 'string')\n if (typeChecker.typeToString(actionType) === 'string') {\n return [];\n }\n return [typeChecker.typeToString(actionType)];\n }\n\n let firstPipe = true;\n return {\n [`${createEffectExpression}:not([arguments.1]:has(Property[key.name='dispatch'][value.value=false])) CallExpression[callee.property.name='pipe'][callee.object.property.name=${actionsNames}]`](\n node\n ) {\n if (firstPipe) {\n checkNode(node);\n firstPipe = false;\n return;\n }\n },\n\n [`${createEffectExpression}:not([arguments.1]:has(Property[key.name='dispatch'][value.value=false])) CallExpression[callee.property.name='pipe']:exit`]() {\n firstPipe = true;\n },\n };\n },\n});\n"]}