> ## 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.

# Cookbook

> Copy-paste recipes for common consumer implementations.

# Cookbook

Use this page when you want complete, practical recipes instead of reading the API page by page.

## Recipe 1: SQL User CRUD API

Use this when you want a standard REST API on SQL with generated model, service, and controller layers.

```bash theme={null}
eloquent make:model User --with-migration
eloquent make:service User
eloquent make:controller User
eloquent make:migration --all
eloquent migrate:run --all-migrations
```

Model:

```ts theme={null}
import { column } from "@alpha.consultings/eloquent-orm.js";
import { SqlModel, type ModelInstance } from "@alpha.consultings/eloquent-orm.js/Model";

type UserAttrs = {
  id?: number;
  name?: string;
  email?: string;
  created_at?: string | Date | null;
  updated_at?: string | Date | null;
};

export class User extends SqlModel<UserAttrs> {
  static tableName = "users";
  static connectionName = process.env.DB_CONNECTION ?? "sqlite";
  static schema = {
    id: column("increments", undefined, { primary: true }),
    name: column("string", 255),
    email: column("string", 255, { unique: true }),
    created_at: column("timestamp", undefined, { useTz: true }),
    updated_at: column("timestamp", undefined, { useTz: true }),
  };

  constructor() {
    super("users", process.env.DB_CONNECTION ?? "sqlite");
  }
}

export interface User extends ModelInstance<UserAttrs> {}
```

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 create(data: Record<string, unknown>) {
    return User.create(data);
  }

  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);
  }
}
```

Routes:

```ts theme={null}
import express from "express";
import { UserController } from "./app/controllers/UserController";

const app = express();
app.use(express.json());

const controller = new UserController();
app.get("/users", controller.index.bind(controller));
app.get("/users/:id", controller.show.bind(controller));
app.post("/users", controller.store.bind(controller));
app.put("/users/:id", controller.update.bind(controller));
app.delete("/users/:id", controller.destroy.bind(controller));
```

## Recipe 2: Blog API with Relations

Use this when you want a realistic relational example quickly.

```bash theme={null}
eloquent make:scenario blog --test --controllers --services --run --force
```

Typical relation definitions:

```ts theme={null}
posts: relation("hasMany", "Post", { foreignKey: "user_id" })
author: relation("belongsTo", "User", { foreignKey: "user_id" })
favorites: relation("belongsToMany", "Post", {
  pivotTable: "post_user_pivot",
  pivotLocalKey: "user_id",
  pivotForeignKey: "post_id",
})
comments: relation("morphMany", "Comment", { morphName: "commentable" })
commentable: relation("morphTo", "Commentable", { morphName: "commentable" })
```

Service query example:

```ts theme={null}
async feed(limit = 20) {
  return Post.where("published", true)
    .orderBy("created_at", "desc")
    .limit(limit)
    .get();
}
```

## Recipe 3: Mongo Document API

Use this when the app is document-first.

```bash theme={null}
eloquent make:model GeoLocation --mongo
eloquent make:service GeoLocation
eloquent make:controller GeoLocation
```

```ts theme={null}
import { column } from "@alpha.consultings/eloquent-orm.js";
import { MongoModel, type ModelInstance } from "@alpha.consultings/eloquent-orm.js/Model";

type GeoLocationAttrs = {
  id?: number;
  name?: string;
  latitude?: number;
  longitude?: number;
};

export class GeoLocation extends MongoModel<GeoLocationAttrs> {
  static tableName = "geolocations";
  static connectionName = "mongo";
  static schema = {
    id: column("increments", undefined, { primary: true }),
    name: column("string", 255),
    latitude: column("float"),
    longitude: column("float"),
  };

  constructor() {
    super("geolocations", "mongo");
  }
}

export interface GeoLocation extends ModelInstance<GeoLocationAttrs> {}
```

Keep the service and controller surface the same as SQL. Let the model base decide driver behavior.

## Recipe 4: Soft Delete Admin Restore Flow

Use this when records should be recoverable from an admin screen.
For PostgreSQL-focused apps, keep the soft-delete column explicit and timezone-aware.

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

Schema:

```ts theme={null}
deleted_at: column("softDeletes", undefined, { useTz: true })
```

Service:

```ts theme={null}
async trashed() {
  const model = new User() as User & { onlyTrashed?: () => Promise<unknown[]> };
  return model.onlyTrashed?.() ?? [];
}

async restore(id: number | string) {
  const user = await User.find(id);
  if (!user) {
    return;
  }
  await user.restore();
}
```

Routes:

```ts theme={null}
app.get("/admin/users/trashed", async (_req, res) => {
  res.json(await service.trashed());
});

app.patch("/admin/users/:id/restore", controller.restore.bind(controller));
```

## Recipe 5: Cache-First Dashboard Service

Use this when read endpoints are expensive and you need deterministic invalidation.

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

setupCache();

export class DashboardService {
  async overview() {
    const key = "dashboard:overview:v1";
    const cached = await CacheManager.get(key);
    if (cached) return cached;

    const payload = {
      users: await User.where("is_active", true).get(),
      posts: await Post.orderBy("created_at", "desc").limit(10).get(),
    };

    await CacheManager.set(key, payload, 60);
    return payload;
  }

  async publishPost(id: number | string) {
    await Post.updateById(id, { published: true });
    await CacheManager.delete("dashboard:overview:v1");
  }
}
```

## Recipe 6: Test-Only Application Surface

Use this when app and test artifacts must be isolated.

```bash theme={null}
eloquent make:model User --test
eloquent make:service User --test
eloquent make:controller User --test
eloquent make:registry --test
eloquent make:migration --all --test
eloquent migrate:run --test --all-migrations
eloquent db:seed --test --class BlogScenarioSeeder
```

Generated paths:

* `src/test/database/models`
* `src/test/services`
* `src/test/controllers`

## Recipe 7: Mixin-Driven Service Layer

Use this when runtime behavior should go beyond plain CRUD.

Practical mixin scenarios:

* soft delete and restore
* eager loading
* serialization
* casts
* scopes
* lifecycle hooks
* pivot attach, detach, and sync
* service-boundary caching

See [Mixin Scenarios](../orm/mixin-scenarios).

## Next detailed guides

* [Common Scenarios](./common-scenarios)
* [Controllers](./controllers)
* [Services](./services)
* [Models](../api/models)
* [Mixin Scenarios](../orm/mixin-scenarios)
