ts-ddd-domain-service
Create, review, or guide pure Domain Service implementation in a TypeScript + DDD monorepo.
Skill by llodev
Install
Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.
npx agentmarket install skill/llodev-ts-ddd-domain-service
Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.
Get the weekly diff
The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.
About
Use cases: backend, testing
Reviews
Write a reviewNo reviews yet. Installed it? Reviews come from verified installers only. How reviews work
Permissions
What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.
- Tools
- No tools found
- Secrets
- None asked for
- Install scripts
- None found
- Runs as
- Node.js package
Network hosts it talks to 1
codeload.github.com· found in install command
Files it touches
~/.claude/skills/ts-ddd-domain-service
What's inside
- Skill name
ts-ddd-domain-service- Description
- Create, review, or guide pure Domain Service implementation in a TypeScript + DDD monorepo. Use when the request involves `*.service.ts` files inside `apps/api/src/<bc>/domain/services/`, domain policies, pure calculations/rules across multiple entities/VOs, naming patterns (`*Policy`, `*Calculator`, `*Resolver`, `*Specification`), branching on closed-set enums (status / kind / role) from `@acme/celebrations-contracts`, or tests in `apps/api/test/<bc>/domain/services/`. Scope is the *pure* domain layer; for orchestrators that need a repository or other I/O (e.g. `SlugAllocator`), see the sibling `application/services/` section at the end.
- License
- MIT
- Metadata
- version: 0.1.0
- Instructions
- 95 lines in SKILL.md · view on GitHub
Before installing
- Ships executable scripts
Files (11)
- CHANGELOG.md
- LICENSE
- README.md
- SKILL.md
- README.es-ES.md · docs/i18n/
- README.pt-BR.md · docs/i18n/
- permission-policy.service.test.ts · examples/
- permission-policy.service.ts · examples/
- stock-calculator.service.ts · examples/
- package.json
- domain-service-pattern.md · references/
SKILL.md (first lines)
# TypeScript DDD Domain Service
**MANDATORY — READ ENTIRE FILE**: Before any implementation step, read
[`references/domain-service-pattern.md`](references/domain-service-pattern.md) completely.
**Do NOT load** other DDD skills (entity, use-case, repository) unless explicitly requested.
This skill covers **pure** domain services that live in
`apps/api/src/<bc>/domain/services/`. They never see a repository, NestJS,
Firestore, HTTP, Zod, or any DTO. They take entities/VOs/primitives as
arguments and return a `Result` or a plain domain value.
> If the rule needs I/O (load by slug, retry against the database,
> call an external API), it is an **application service**, not a domain
> service — jump straight to the "When you need I/O" section below.
---
## Before You Start
Before writing a single method, answer:
- **Ownership**: does the rule use only one entity's own data? → put it as an entity method + `cloneWith` (see `Celebration.publish`), not a service.
- **Cross-aggregate?**: does it combine 2+ entities/VOs without a clear owner? → Domain Service.
- **I/O needed?**: does the rule require a repository, query, Firestore, or external call? → Application Service in `application/services/` (DI + `@Injectable`), not Domain Service.
- **Already exists?**: is the rule already captured in a VO (`Slug`, `PaletteKey`) or entity method (`addSection`, `publish`)? → do not duplicate.
- **Closed-set branch?**: if you compare a status/kind/role against a literal string, stop — use the enum from `@acme/celebrations-contracts` (see "Branching on closed sets" in the reference).
---
## Domain Service vs Use Case vs Application Service
> For the **Entity Method** criteria (single-aggregate invariants — when the rule belongs inside `*.entity.ts` rather than in any service), see the `ts-ddd-entity` skill references. This skill owns the boundary **between** the three service-shaped homes below.
| Situation | Where to put it | Why |
| --------------------------------------------------------- | ------------------------------------------------- | ----------------------------------------------------- |
| Rule combines 2+ entities/VOs with no clear owner, no I/O | **Domain Service** (`domain/services/`) | No single entity owns the rule; pure → no DI needed |
| Rule is pure but only used in one flow | Inline in Use Case | YAGNI — extract to service only when reused |
| Rule needs I/O (repository, query, Firestore, HTTP) | Use Case **or** Application Service | Domain layer must stay pure |
| Multi-step I/O flow that doesn't fit `UseCase<IN, OUT>` | **Application Service** (`application/services/`) | `SlugAllocator`-style: needs DI, retries, repo access |
| Rule is a boolean policy over a collection | Domain Service (`*Policy`) | Stateless check over multiple objects |
---
## Core Rules
- File lives in `apps/api/src/<bc>/domain/services/<name>.service.ts` — never under `application/`, `infra/`, `presentation/`, or `libs/contracts/**`.
- Each leaf folder has an `index.ts` barrel — re-export every new service from `apps/api/src/<bc>/domain/services/index.ts`.
- Pure and deterministic: same input always produces same output, no `Date.now()`/`Math.random()` inside the rule (inject if needed).
- Imports allowed: `@acme/shared` (`Result`, `Entity`, VOs), `@acme/<bc>-contracts` (enums + interfaces), other entities/VOs in the same BC. Nothing else.
- **No** `@nestjs/*`, `@Injectable`, constructor injection, `firebase-admin`, Zod, DTOs, or framework decorators in this file.
- Receives domain objects (entities, VOs, primitives) — returns `Result<T>` or a plain domain value.
- Name by rule intent: `*Policy`, `*Calculator`, `*Resolver`, `*Specification`.
- Default to a class with `static` methods for stateless calculations; instance methods only when the service genuinely holds configuration that varies per call site.
- Compare closed-set fields against enum members (`CelebrationStatusEnum.PUBLISHED`), never raw strings. Iterate catalogs via `Object.values(XxxEnum)`.
- On failure use `Result.fail("DOMAIN_ERROR_CODE")` (UPPER_SNAKE). Aggregate multi-error validation with `Result.combine([...])` or by pushing into an `errors[]` array — same pattern as `Celebration.tryCreate`.
- Bubble up failures from inner VOs/entities via `result.withFail` instead of re-wrapping.
## NEVER
- **NEVER** inject a repository, query, or Firestore client into a Domain Service — I/O belongs in a Use Case or Application Service.
- **NEVER** import `@nestjs/*`, `firebase-admin`, `next`, `react`, or any framework here — that contamination is what the layer exists to prevent.
- **NEVER** duplicate logic already in an entity method or VO — if `Celebration` exposes `publish()`, the service calls it instead of re-implementing the transition.
- **NEVER** put orchestration decisions (which repository to call next, which event to emit, retry loops) in a Domain Service — that is application concern.
- **NEVER** return `null`/`undefined`/`throw` to signal failure — return `Result.fail("CODE")` so callers handle errors uniformly.
- **NEVER** branch on a raw string literal for status/kind/role/palette — import the enum from `@acme/celebrations-contracts` (or the relevant BC contracts).
- **NEVER** call the function `execute` here — `execute` is reserved for `UseCase<IN, OUT>`. Name the method after the rule (`check`, `calculate`, `resolve`, `isSatisfiedBy`).
- **NEVER** call `Date.now()`, `Math.random()`, `crypto.randomUUID()`, `performance.now()`, `new Date()` (without an argument), or any other non-deterministic primitive inside a domain service — pure means **deterministic given inputs**. Pass a clock/random/id-generator as a parameter (or generate the value in the use case before calling the service). **Why**: non-determinism makes tests flaky, breaks property-based testing, and hides the real input set the rule depends on — the service silently couples to wall-clock time instead of taking it as data.
## When you need I/O — use an Application Service
If your "service" needs a repository, retries against the database, or
external calls, it is **not** a Domain Service. Put it in
`apps/api/src/<bc>/application/services/<name>.service.ts`, mark it
`@Injectable()`, inject ports via DI tokens, and still return `Result`.
Canonical reference in this repo:
`apps/api/src/celebrations/application/services/slug-allocator.service.ts`
(allocates a unique `Slug` by retrying against `CelebrationRepository`).
See the final section of [`references/domain-service-pattern.md`](references/domain-service-pattern.md)
for the contrast.
## Verification
After writing or editing a service, run:
```bash
pnpm --filter api typecheck && pnpm --filter api test
```
(or `make check-api`). Test files live in `apps/api/test/<bc>/domain/services/<name>.test.ts`.
## References
See [`references/domain-service-pattern.md`](references/domain-service-pattern.md) for: file paths, canonical snippets (`*Policy` and `*Calculator`), the closed-set enum rule, test strategy, the implementation checklist, and the application-service contrast.From llodev/skills, MIT.
More from llodev/skills
- 0.563score
ts-ddd-entity
llodev
Create, review, or guide Domain Entity implementation in a TypeScript + DDD codebase.
SkillBFreshness: B★ 2Claude Code +9 - 0.563score
ts-ddd-dto
llodev
Create, review, or guide Data Transfer Objects in a TypeScript + DDD monorepo.
SkillBFreshness: B★ 2Claude Code +9 - 0.563score
ts-ddd-use-case
llodev
Create, review, or guide use case (application service) implementation in a TypeScript + DDD codebase.
SkillBFreshness: B★ 2Claude Code +9 - 0.563score
ts-ddd-controller
llodev
Create, review, or guide HTTP controllers in a TypeScript + DDD api.
SkillBFreshness: B★ 2Claude Code +9 - 0.563score
ts-ddd-repository
llodev
Create, review, or guide repository contracts and implementations in a TypeScript + DDD codebase.
SkillBFreshness: B★ 2Claude Code +9 - 0.563score
ts-ddd-value-object
llodev
Create, review, or guide Value Object implementation in a TypeScript + DDD codebase.
SkillBFreshness: B★ 2Claude Code +9 - 0.563score
ts-query-cqrs
llodev
Create, review, or guide read-side queries in a TypeScript + DDD CQRS codebase.
SkillBFreshness: B★ 2Claude Code +9 - 0.558score
django-schema-design
llodev
Design robust Django database schemas with model best practices, migration patterns, and primary key strategy (incremental, UUID, UUIDv7).
SkillBFreshness: B★ 2Claude Code +9 - 0.558score
pm-tasks-asana
llodev
Asana adapter for the @llodev/pm-tasks-* family.
SkillBFreshness: B★ 2Claude Code +9 - 0.558score
pm-tasks-core
llodev
Core extraction + vocabulary for the @llodev/pm-tasks-* family.
SkillBFreshness: B★ 2Claude Code +9 - 0.558score
pm-tasks-trello
llodev
Trello adapter for the @llodev/pm-tasks-* family.
SkillBFreshness: B★ 2Claude Code +9 - 0.554score
pm-tasks-linear
llodev
Linear adapter for the @llodev/pm-tasks-* family.
SkillBFreshness: B★ 2Claude Code +9
Signals
- Stars
- 2
- Forks
- 0
- Open issues
- 0
- Last commit (this folder)
- Jul 17, 2026 (3 months ago)
- Last release
- Aug 21, 2026 (2 months ago)
From GitHub (fetched Oct 24, 2026).
Details
- Version
- 0.1.0
- License
- MIT
- Repository
- github.com/llodev/skills
- Website
- www.npmjs.com/org/llodev
- First seen
- Oct 24, 2026
- Last checked
- Oct 24, 2026
- Source
- GitHubgithub-graphql
More from llodev
- 0.563score
ts-ddd-value-object
llodev
Create, review, or guide Value Object implementation in a TypeScript + DDD codebase.
SkillBFreshness: B★ 2Claude Code +9 - 0.563score
ts-ddd-controller
llodev
Create, review, or guide HTTP controllers in a TypeScript + DDD api.
SkillBFreshness: B★ 2Claude Code +9 - 0.563score
ts-ddd-dto
llodev
Create, review, or guide Data Transfer Objects in a TypeScript + DDD monorepo.
SkillBFreshness: B★ 2Claude Code +9 - 0.563score
ts-ddd-entity
llodev
Create, review, or guide Domain Entity implementation in a TypeScript + DDD codebase.
SkillBFreshness: B★ 2Claude Code +9 - 0.563score
ts-ddd-repository
llodev
Create, review, or guide repository contracts and implementations in a TypeScript + DDD codebase.
SkillBFreshness: B★ 2Claude Code +9 - 0.563score
ts-ddd-use-case
llodev
Create, review, or guide use case (application service) implementation in a TypeScript + DDD codebase.
SkillBFreshness: B★ 2Claude Code +9
Cite this page
ts-ddd-domain-service skill. Agent Mart. https://agentmart.dev/skills/llodev-ts-ddd-domain-service (last updated 2026-10-24)