forFeature
Bind a service to its table, and override per-entity configuration.
DrizzleCrudModule.forFeature(entities) is called inside each feature module. It binds one or more services to their tables and constructs them with the correct merged configuration.
Signature
DrizzleCrudModule.forFeature(entities: CrudFeature[]): DynamicModuleWhere CrudFeature is:
interface CrudFeature {
service: typeof SqlBaseCrudService;
table: any; // Drizzle table
config?: Partial<SqlCrudConfig>; // per-entity overrides
}Basic usage
import { Module } from '@nestjs/common';
import { DrizzleCrudModule } from 'nestjs-drizzle-crud';
import { users } from '../db/schema';
import { UsersController } from './users.controller';
import { UsersService } from './users.service';
@Module({
imports: [
DrizzleCrudModule.forFeature([
{ service: UsersService, table: users },
]),
],
controllers: [UsersController],
providers: [UsersService],
})
export class UsersModule {}The module registers UsersService as a provider, passing it a fully-built SqlCrudConfig derived from the global forRoot defaults + any per-entity overrides you supply here.
Per-entity overrides
Anything in config overrides the project defaults for that entity. The shape is SqlCrudConfig minus db and dialect (those are injected by forFeature).
DrizzleCrudModule.forFeature([
{
service: PostsService,
table: posts,
config: {
primaryKey: 'id',
primaryKeyType: 'serial',
softDelete: { enabled: true, column: 'deleted_at' },
// Default ORDER BY for findAll() when the caller passes no sortBy.
defaultSort: [
{ column: 'position', order: 'asc' },
{ column: 'created_at', order: 'desc' }, // tiebreaker
],
relations: {
author: { table: users, localKey: 'author_id', references: 'id' },
},
},
},
])What you can override
| Field | Effect |
|---|---|
primaryKey | Column name for the primary key (default 'id'). |
primaryKeyType | 'serial' | 'bigserial' | 'int' | 'bigint' | 'uuid'. See Primary keys. |
softDelete | { enabled: boolean; column: string }. Override the default deleted_at column name. |
timestamps | { createdAt: string; updatedAt: string }. Override the default created_at / updated_at column names. |
pagination | { defaultLimit: number; maxLimit: number }. Per-entity override of the global defaults.pagination. |
defaultSort | Ordered column list for findAll() when no sortBy is passed. |
sql | Per-entity dialect tuning. |
relations | Many-to-one relations, keyed by relation name. See Relations. |
Multiple entities in one feature module
DrizzleCrudModule.forFeature([
{ service: UsersService, table: users },
{ service: PostsService, table: posts },
{ service: CommentsService, table: comments, config: { /* ... */ } },
])Each service is registered as its own provider and is independently constructed.
@CrudService decorator
You can also attach per-entity config to the service class itself with the @CrudService decorator. The forFeature config field still wins when both are set — the merge order is global defaults → decorator metadata → forFeature config.
import { CrudService } from 'nestjs-drizzle-crud';
@CrudService({
primaryKeyType: 'uuid',
softDelete: { enabled: true, column: 'deleted_at' },
})
export class TagsService extends SqlBaseCrudService<Tag> {}The decorator is mostly a convenience for keeping the config next to the service definition. Use forFeature config for config that's data-driven or varies per feature module.
Verifying the merged config
The fully-built config for each entity is available in the DRIZZLE_CRUD_CONFIG DI token. Inject it in tests to verify the merge worked:
import { Inject } from '@nestjs/common';
import { DRIZZLE_CRUD_CONFIG } from 'nestjs-drizzle-crud';
@Injectable()
export class ConfigInspector {
constructor(@Inject(DRIZZLE_CRUD_CONFIG) public readonly cfg: any) {}
}The injected DRIZZLE_CRUD_CONFIG is the normalized global config (the
result of applying defaults). It does not include the per-entity
overrides. To inspect a single entity's resolved config, use
DRIZZLE_DB + read it off the constructed service instance.