# Services

Services contain your application's business logic, orchestrating data flow and executing use cases.

> **Deep Dive:** See [Services Reference](../../references/base/services.md) for advanced patterns.

## The Business Logic Layer

Services contain the core business logic of your application. They orchestrate the flow of data and execute the application's use cases. A service's primary responsibilities are:

-   **Encapsulating Business Rules**: Centralizing logic such as calculations, data validation, and process workflows.
-   **Coordinating Operations**: Using repositories to fetch and persist data, or orchestrating other services to execute complex business workflows.
-   **Reusing Business Logic**: Services can inject other services to reuse established logic, ensuring "Don't Repeat Yourself" (DRY) principles are maintained across the application.
-   **Isolating Controllers**: Keeping controllers thin by handling all the complex logic, so controllers are only responsible for handling the HTTP request and response.

### Creating a Service

To create a service, extend the `BaseService` class and inject the repositories or other services it depends on.

```typescript
import { BaseService, inject } from '@venizia/ignis';
import { ConfigurationRepository } from '../repositories';
import { UserRepository } from '../repositories';
import { LoggingService } from './logging.service'; // Example of another service
import { TConfiguration } from '../models/entities';

export class ConfigurationService extends BaseService {
  constructor(
    @inject({ key: 'repositories.ConfigurationRepository' })
    private configurationRepository: ConfigurationRepository,
    @inject({ key: 'repositories.UserRepository' })
    private userRepository: UserRepository,
    @inject({ key: 'services.LoggingService' })
    private loggingService: LoggingService, // Injecting another service for reuse
  ) {
    super({ scope: ConfigurationService.name });
  }

  async createConfigurationForUser(opts: {
    userId: string;
    data: Partial<TConfiguration>;
  }): Promise<TConfiguration> {
    // Call another service logic
    await this.loggingService.audit({ message: `Creating config for user: ${opts.userId}` });

    // Business logic: Check if the user exists
    const user = await this.userRepository.findById({ id: opts.userId });
// ...
```

### BaseService API

`BaseService` is intentionally minimal. It extends `BaseHelper` to provide scoped logging:

```typescript
export abstract class BaseService extends BaseHelper implements IService {
  constructor(opts: { scope: string }) {
    super({ scope: opts.scope });
  }
}
```

There is no built-in CRUD service -- implement business logic directly in your service methods. This keeps the service layer focused on your domain-specific operations rather than generic data access patterns (which belong in repositories).

## How Services Fit into the Architecture

Services act as the primary layer for business logic, sitting between controllers and repositories. While controllers are the typical entry point, **services can also inject and call other services**. This enables powerful logic reuse and allows you to build complex use cases by composing smaller, specialized services.

```mermaid
graph LR
    A[Client Request] --> B(Controller);
    B --> C1{Service A};
    C1 --> C2{Service B};
    C1 --> D1[Repository A];
    C2 --> D2[Repository B];
    D1 --> E((Database));
    D2 --> E;

    subgraph "Presentation Layer"
        B
    end
    subgraph "Business Logic Layer"
        C1
        C2
    end
    subgraph "Data Access Layer"
        D1
        D2
    end
    subgraph "Data Store"
        E
    end
```

This layered architecture makes your application:

-   **More Organized:** Each layer has a clear and distinct responsibility.
-   **Easier to Test:** You can test your business logic in isolation by providing mock repositories to your services, without needing a live database.
-   **More Flexible:** You can change your database or data access implementation (e.g., switch from PostgreSQL to MySQL) by only changing the repository and datasource layer, with no changes to your business logic.

## See Also

- **Related Concepts:**
  - [Controllers](/guides/core-concepts/rest-controllers) - Call services to handle requests
  - [Repositories](/guides/core-concepts/persistent/repositories) - Data access layer used by services
  - [Dependency Injection](/guides/core-concepts/dependency-injection) - Injecting dependencies into services

- **References:**
  - [BaseService API](/references/base/services) - Complete API reference
  - [Providers](/references/base/providers) - Factory pattern for runtime instantiation
  - [Logger Helper](/extensions/helpers/logger/) - Logging in services

- **Best Practices:**
  - [Architectural Patterns](/best-practices/architectural-patterns) - Service layer design
  - [Testing](/guides/tutorials/testing) - Unit testing services

- **Tutorials:**
  - [Building a CRUD API](/guides/tutorials/building-a-crud-api) - Service examples
  - [E-commerce API](/guides/tutorials/ecommerce-api) - Complex business logic
