> ## Documentation Index
> Fetch the complete documentation index at: https://alphaconsultings.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Services

> Generated service CRUD flow and mixin-aware runtime patterns.

# Service Usage Guide

Services are the main application boundary for CRUD, relation loading, soft-delete restore flows, and cache behavior.

## Generate a service

```bash theme={null}
eloquent make:service User
eloquent make:service User --test
```

## Generated methods

* `all()`
* `find(id)`
* `create(data)`
* `createMany(rows)`
* `update(id, data)`
* `delete(id)`
* `restore(id)`

## Extend the generated service

```ts theme={null}
import { User } from "../models/User";

export class UserService {
  async all() {
    return new User().all();
  }

  async find(id: number | string) {
    return User.find(id);
  }

  async findByEmail(email: string) {
    return User.findOneBy("email", email);
  }

  async recentActive(limit = 20) {
    return User.where("is_active", true)
      .orderBy("created_at", "desc")
      .limit(limit)
      .get();
  }

  async findWithPosts(id: number | string) {
    const user = await User.find(id);
    if (!user) return null;
    await (user as { load?: (...relations: string[]) => Promise<unknown> }).load?.("posts");
    return user;
  }

  async create(data: Record<string, unknown>) {
    return User.create(data);
  }

  async createMany(rows: Record<string, unknown>[]) {
    return User.createMany(rows);
  }

  async update(id: number | string, data: Record<string, unknown>) {
    const user = await User.find(id);
    if (!user) return null;
    user.update(data);
    await user.save();
    return user;
  }

  async delete(id: number | string) {
    return User.deleteById(id);
  }

  async restore(id: number | string) {
    return User.restoreById(id);
  }

  async deactivateMany(ids: Array<number | string>) {
    await User.updateMany(ids, { status: "inactive" });
  }
}
```

Eager-loading note:

* `load()` and `with()` require explicit relation methods on the model instance
* schema relation metadata alone is not enough for eager-loading calls

## Mixin-aware service patterns

### SoftDeletesMixin

* `restore(id)` via `User.restoreById(id)` or loaded-instance restore flows
* `withTrashed()`
* `onlyTrashed()`
* `forceDelete(id)`

Keep these flows in the service so controllers stay HTTP-only.

### EagerLoadingMixin

Load relations in service methods, then return hydrated records.

Example model method:

```ts theme={null}
posts() {
  return this.hasMany(Post as any, "user_id");
}
```

### SerializeMixin

If you use hidden/appended fields, return `toObject()` from the service for API-safe payloads.

### CastsMixin

Define casts in the model. Service reads then consume already-normalized values.

### ScopeMixin

Global scopes affect `all()` and `find()` automatically. Current behavior is in-memory post-fetch filtering.

### HooksMixin

Services do not call hooks manually. Model hooks fire through `User.create(...)`, loaded-instance `update(...); save()`, and delete paths.

### PivotHelperMixin

Use `attach`, `detach`, and `sync` from services for many-to-many workflows.

### Cache

For consumer-facing code, prefer `CacheManager` at the service boundary:

```ts theme={null}
import { CacheManager, setupCache } from "@alpha.consultings/eloquent-orm.js";

setupCache();
```

Wrap read methods with cache lookups and invalidate keys after writes.

## Driver note

The service surface stays the same for SQL and Mongo models. Keep ids as `number | string` and let model choice control driver behavior.
