agentsclimarketplace

Ts ddd controller

Skill llodev/skills/skills/ts-ddd-controller

Collection of Agent Skills for Claude Code, Cursor, Codex, Windsurf, and any agent that speaks the open Skills spec. Ships via npm + plugin + skills add.

Install
npx -y skills add llodev/skills --skill ts-ddd-controller

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Create, review, or guide HTTP controllers in a TypeScript + DDD api. Use when the request involves `*.controller.ts` under `apps/api/src/<bc>/presentation/controllers/`, route definition, `ApiKeyGuard` on mutations, `ZodValidationPipe` against `@acme/<bc>-contracts` schemas, use case orchestration, mapping `Result` to HTTP via `mapResultToHttp`, signed-URL enrichment through a response mapper, HTTP status conventions (200/201/204), or controller tests using `@nestjs/testing` + `supertest` with an in-memory repository.

SKILL.md

6.1 KB, as published. Nobody here has run it

TypeScript DDD Controller

MANDATORY — READ ENTIRE FILE: before writing or reviewing any controller, read references/controller-pattern.md completely.

Then load the framework reference:

  • NestJS 11 (this repo) → also read references/nestjs.md completely.
  • Other frameworks (Express, Fastify, Hono…) are not yet documented; apply the principles from controller-pattern.md.

Do NOT load sibling DDD skills (ts-ddd-entity, ts-ddd-use-case, ts-ddd-repository, ts-ddd-dto, ts-ddd-value-object) unless the request explicitly asks for them.


When to trigger this skill

  • File path matches apps/api/src/<bc>/presentation/controllers/*.controller.ts.
  • Request mentions @Controller, @Get/@Post/@Put/@Delete, @UseGuards(ApiKeyGuard), ZodValidationPipe, mapResultToHttp, or a response mapper.
  • Adding/changing routes for a bounded context (e.g. celebrations).
  • Wiring controllers into a <bc>.module.ts.
  • Writing a controller test under apps/api/test/<bc>/presentation/controllers/*.controller.test.ts.

Where controllers live

apps/api/src/<bc>/
  presentation/
    controllers/<name>.controller.ts
    guards/api-key.guard.ts
    mappers/<name>-response.mapper.ts
    index.ts                  ← barrel per leaf folder
  application/
    usecases/                 ← injected here
  <bc>.module.ts              ← registers controllers, mappers, guard, use cases

Every leaf folder exports through an index.ts barrel. Imports across layers use the path aliases @<bc>/* (e.g. @celebrations/application/usecases) and @shared/* (apps/api/src/shared/*); inside the same folder use relative paths. Cross-package types come from @acme/<bc>-contracts and @acme/shared — never @ddd/shared or any older name.

Before You Start

Answer these before writing a handler:

  • Contract: status + payload? (200 payload, 201 CREATED, 204 NO_CONTENT, 200 for explicit OK on actions like /publish).
  • Mutation?: If yes, @UseGuards(ApiKeyGuard) is required (writes are 401 without x-api-key, 503 MUTATIONS_DISABLED when API_WRITE_KEY is unset — see references/controller-pattern.md).
  • Wire shape: Which Zod schema in the contracts package validates @Body / @Param? Don't redefine wire types locally.
  • Failure mapping: Is the error code already in apps/api/src/shared/http/error-codes.ts? If new, add it there with the right HTTP status before throwing it from a use case.
  • Response shape: Does the entity need enrichment (signed Storage URLs, ISO dates)? Then go through the response mapper, not raw entity props.

Core Rules

  • Controllers are thin translators between HTTP and the application layer. No business logic, no domain conditionals, no repository calls.
  • Inject use cases and mappers via the constructor — never new UseCase(...).
  • Validate at the boundary with ZodValidationPipe(schema) over schemas exported by the BC's contracts package.
  • Map Result → HTTP with mapResultToHttp(result, ok => …) from @shared/http. Don't throw NestJS exceptions directly from controller handlers.
  • Mutations carry @UseGuards(ApiKeyGuard). Reads stay public.
  • Enrich entity → response DTO inside a dedicated mapper (e.g. CelebrationResponseMapper) — that's where signed URLs, date serialization, and tagged-union variant handling live.

NEVER

  • NEVER apply @UseGuards(ApiKeyGuard) at the class level. Why: it 401s every read. The canonical CelebrationsController mixes public reads (GET /celebrations, GET /celebrations/:slug) with per-method-guarded writes; a class-level guard breaks that mix and silently breaks the public web client. Always attach @UseGuards(ApiKeyGuard) to each mutating handler individually.
  • NEVER throw a NestJS HttpException (or its subclasses like BadRequestException / NotFoundException) directly from a controller. Why: the error-code catalog in apps/api/src/shared/http/error-codes.ts is the single source of truth for code → HTTP status mapping. Throwing inline forks that mapping, defeats the Result pattern in use cases, and produces envelopes that don't match HttpExceptionFilter. Always pipe Result failures through mapResultToHttp.
  • NEVER put domain logic, branching, or repository access inside a controller method.
  • NEVER instantiate use cases or mappers with new — breaks DI and tests.
  • NEVER remove ApiKeyGuard on a write to "fix" a 503; the 503 is the intentional MUTATIONS_DISABLED contract when API_WRITE_KEY is unset.
  • NEVER redefine wire-shape interfaces in the controller; import the DTO type + Zod schema from @acme/<bc>-contracts.
  • NEVER leak entity internals (e.g. Date objects, raw storagePath without signed URL) into the response — funnel through the mapper.

References

  • references/controller-pattern.md — repo-grounded: folder layout, ZodValidationPipe, ApiKeyGuard semantics, mapResultToHttp, response mapper, test strategy (enum members in fixtures).
  • references/nestjs.md — NestJS 11 patterns actually used here: DI symbol tokens (FIREBASE_APP), @Inject(SYMBOL), @Global() modules (FirebaseModule, AppConfigModule), Zod-validated ConfigModule.forRoot, @nestjs/testing + supertest test bed.
  • examples/product.controller.nestjs.ts — runnable-style mirror of CelebrationsController.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.