Best Practices for Structuring Angular Services

Learn how to create modular and maintainable Angular services that promote code reuse and separation of concerns.

0 likes
49 views

Rule Content

{
  "title": "Best Practices for Structuring Angular Services",
  "description": "Learn how to create modular and maintainable Angular services that promote code reuse and separation of concerns.",
  "category": "Angular Cursor Rules",
  "rules": [
    {
      "id": "angular-service-single-responsibility",
      "description": "Ensure each Angular service adheres to the Single Responsibility Principle by focusing on a specific functionality or domain area.",
      "severity": "warning",
      "pattern": {
        "type": "class",
        "annotations": ["Injectable"],
        "body": {
          "type": "method",
          "count": {
            "max": 5
          }
        }
      },
      "message": "This service contains multiple methods, which may indicate it is handling more than one responsibility. Consider splitting it into separate services."
    },
    {
      "id": "angular-service-dependency-injection",
      "description": "Utilize Angular's dependency injection system to manage service dependencies, avoiding manual instantiation.",
      "severity": "error",
      "pattern": {
        "type": "class",
        "annotations": ["Injectable"],
        "body": {
          "type": "method",
          "body": {
            "type": "new",
            "class": ".*Service"
          }
        }
      },
      "message": "Avoid manually instantiating services within other services. Use Angular's dependency injection to manage service dependencies."
    },
    {
      "id": "angular-service-provided-in-root",
      "description": "Provide services at the root level using the 'providedIn' property to ensure a single instance throughout the application.",
      "severity": "info",
      "pattern": {
        "type": "class",
        "annotations": ["Injectable"],
        "metadata": {
          "providedIn": {
            "not": "root"
          }
        }
      },
      "message": "Consider providing this service at the root level by setting 'providedIn: \"root\"' to ensure a singleton instance across the application."
    },
    {
      "id": "angular-service-avoid-logic-in-components",
      "description": "Encapsulate business logic within services rather than components to promote reusability and maintainability.",
      "severity": "warning",
      "pattern": {
        "type": "class",
        "annotations": ["Component"],
        "body": {
          "type": "method",
          "body": {
            "type": "call",
            "function": {
              "not": "this\\..*Service\\..*"
            }
          }
        }
      },
      "message": "This component contains business logic that could be moved to a service for better separation of concerns."
    },
    {
      "id": "angular-service-use-async-pipe",
      "description": "Use the async pipe in templates to handle observable subscriptions, reducing the need for manual subscription management.",
      "severity": "info",
      "pattern": {
        "type": "template",
        "content": {
          "not": "\\|\\s*async"
        }
      },
      "message": "Consider using the async pipe to handle observable subscriptions directly in the template, which simplifies code and prevents memory leaks."
    }
  ]
}