awilix-di-patterns
Awilix dependency injection patterns for this Fastify project — auto-loading conventions, Cradle usage, partial application, type declarations.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Awilix dependency injection patterns for this Fastify project — auto-loading conventions, Cradle usage, partial application, type declarations.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
CQS (Command Query Separation) patterns — mutations for writes with events, queries for reads without side effects.
Safe Drizzle ORM migration patterns for PostgreSQL. Auto-loads on migration files. Mandatory reading before writing or editing a migration.
Drizzle ORM query patterns for this project — base repository, soft delete, NON_PASSWORD_COLUMNS, query builder conventions.
Fastify route handler patterns — TypeBox validation, DI access, schema definitions, JWT guards, error handling conventions.
E2E testing patterns using Node.js native test runner — createTestingApp, createDbHelper, factories, app.inject() for HTTP testing.
| name | awilix-di-patterns |
| description | Awilix dependency injection patterns for this Fastify project — auto-loading conventions, Cradle usage, partial application, type declarations. |
| globs | ["src/modules/**/*.ts","src/libs/**/*.service.ts","src/libs/di-container/**/*.ts"] |
| allowed-tools | Read, Write, Edit, Grep, Glob, Bash(pnpm:*) |
Files are auto-loaded by @fastify/awilix based on filename suffix:
*.repository.ts → data access layer*.queries.ts → read operations (CQS Query)*.mutations.ts → write operations (CQS Command)*.service.ts → shared servicesThe Cradle key is the camelCase version of the filename:
users.repository.ts → usersRepositoryauth-token.service.ts → authTokenServiceEvery auto-loaded file MUST export a default function that receives Cradle and returns an object:
import type { Cradle } from "@fastify/awilix";
import { partial } from "rambda";
const findOneById = async ({ usersRepository, logger }: Cradle, userId: UUID): Promise<User> => {
logger.debug(`[UsersQueries] Getting user: ${userId}`);
const user = await usersRepository.findOneById(userId);
if (!user) throw new ResourceNotFoundException(`User with id: ${userId} not found`);
return user;
};
export default function usersQueries(deps: Cradle) {
return {
findOneById: partial(findOneById, [deps]),
};
}
Key points:
Cradle is always the first parameter of internal functionsrambda.partial for dependency pre-bindingEvery module MUST have a *.types.d.ts file declaring its Cradle extensions:
import type usersMutations from "./users.mutations.ts";
import type usersQueries from "./users.queries.ts";
import type usersRepository from "./users.repository.ts";
declare module "@fastify/awilix" {
interface Cradle {
usersMutations: ReturnType<typeof usersMutations>;
usersQueries: ReturnType<typeof usersQueries>;
usersRepository: ReturnType<typeof usersRepository>;
}
}
In router handlers:
const { usersMutations, usersQueries } = app.diContainer.cradle;
In auto-loaded modules (via Cradle destructuring):
const createOne = async ({ usersRepository, encrypterService, eventBus, logger }: Cradle, input: UserCreateInput) => {
// deps are available via Cradle
};
From src/libs/di-container/container.types.d.ts:
app — FastifyInstanceconfigs — application configsdb — Drizzle PostgresJsDatabase instancejwtService — JWT signing/verificationlogger — Pino loggereventBus — EventBus for domain eventsdiContainer inside auto-loaded modules (use Cradle parameter)*.types.d.ts declaration (TypeScript won't catch missing deps)awilix.asClass — this project uses asFunction exclusively