# Parameter Decoration

The Database Decorators package provides the `Model` decorator for injecting data model instances into API controller methods. This decorator integrates with the `@antelopejs/interface-api` package's parameter provider system.

## The Model Decorator

The `Model` decorator injects a cached model instance. It can be used as either a parameter decorator or a property decorator.

### Static Instance ID

Pass a fixed instance ID to bind the model to a specific schema instance:

```typescript
import { Controller, Get } from "@antelopejs/interface-api";
import { Model } from "@antelopejs/interface-database-decorators";
import { UserModel } from "./user.model";

class UsersController extends Controller("/users") {
  @Get()
  async listUsers(@Model(UserModel, "main") userModel: InstanceType<typeof UserModel>) {
    return await userModel.getAll();
  }
}
```

### Dynamic Instance ID

Pass a callback function to determine the instance ID at request time. The callback receives the request context:

```typescript
import { Controller, Get, Parameter } from "@antelopejs/interface-api";
import { Model } from "@antelopejs/interface-database-decorators";
import { UserModel } from "./user.model";

class MultitenantController extends Controller("/tenants") {
  @Get("/:tenantId/users")
  async getTenantUsers(
    @Parameter("tenantId") tenantId: string,
    @Model(UserModel, (ctx) => `tenant-${ctx.params.tenantId}`) userModel: InstanceType<typeof UserModel>,
  ) {
    return await userModel.getAll();
  }
}
```

## Property Decoration

The `Model` decorator also works as a property decorator. The model is initialized when the controller handles a request:

```typescript
import { Controller, Get, Parameter } from "@antelopejs/interface-api";
import { Model } from "@antelopejs/interface-database-decorators";
import { UserModel } from "./models";

class UsersController extends Controller("/users") {
  @Model(UserModel, "main")
  private userModel!: InstanceType<typeof UserModel>;

  @Get()
  async listUsers() {
    return await this.userModel.getAll();
  }

  @Get("/:id")
  async getUser(@Parameter("id") id: string) {
    return await this.userModel.get(id);
  }
}
```

## Model Caching

The `Model` decorator uses `GetModel` internally, which caches model instances by class and instance ID. Multiple decorators referencing the same model class and instance ID share a single instance:

```typescript
import { GetModel } from "@antelopejs/interface-database-decorators";

// These return the same instance
const model1 = GetModel(UserModel, "main");
const model2 = GetModel(UserModel, "main");

// This returns a different instance
const model3 = GetModel(UserModel, "other");
```

## Combine with API Decorators

Model decorators compose naturally with other API decorators for building complete CRUD controllers:

```typescript
import { Controller, Get, Post, Put, Delete, RawBody, Parameter } from "@antelopejs/interface-api";
import { Model } from "@antelopejs/interface-database-decorators";
import { UserModel } from "./user.model";

class UsersController extends Controller("/users") {
  @Get()
  async list(@Model(UserModel, "main") model: InstanceType<typeof UserModel>) {
    return await model.getAll();
  }

  @Get("/:id")
  async get(
    @Parameter("id") id: string,
    @Model(UserModel, "main") model: InstanceType<typeof UserModel>,
  ) {
    return await model.get(id);
  }

  @Post()
  async create(
    @RawBody() body: Buffer,
    @Model(UserModel, "main") model: InstanceType<typeof UserModel>,
  ) {
    const data = JSON.parse(body.toString());
    return await model.insert(data);
  }

  @Put("/:id")
  async update(
    @Parameter("id") id: string,
    @RawBody() body: Buffer,
    @Model(UserModel, "main") model: InstanceType<typeof UserModel>,
  ) {
    const data = JSON.parse(body.toString());
    return await model.update(id, data);
  }

  @Delete("/:id")
  async remove(
    @Parameter("id") id: string,
    @Model(UserModel, "main") model: InstanceType<typeof UserModel>,
  ) {
    return await model.delete(id);
  }
}
```

## Custom Parameter Providers

For more complex injection logic, create custom parameter providers using the core API:

```typescript
import { SetParameterProvider } from "@antelopejs/interface-api";
import { GetModel } from "@antelopejs/interface-database-decorators";
import { MakeParameterAndPropertyDecorator } from "@antelopejs/interface-core/decorators";

const CustomModel = MakeParameterAndPropertyDecorator(
  (target, key, index, modelClass, resolver) => {
    SetParameterProvider(target, key, index, (ctx) => {
      const instanceId = resolver(ctx);
      return GetModel(modelClass, instanceId);
    });
  },
);
```
