ts-ddd-entity
Create, review, or guide Domain Entity implementation in a TypeScript + DDD codebase.
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-entity
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-entity
What's inside
- Skill name
ts-ddd-entity- Description
- Create, review, or guide Domain Entity implementation in a TypeScript + DDD codebase. Use when: the request touches `*.entity.ts` files under `apps/api/src/<bc>/domain/entities/` or their tests under `apps/api/test/<bc>/domain/entities/`; modeling business rules with `Entity` from `@acme/shared` (dual API `create`/`tryCreate`, `Result` / `Result.combine` validation); validating FK refs with `Id.required` or own id with `Id.tryCreate`; enforcing enum-backed closed-set fields (status / kind / layout / provider / palette) from `@acme/<bc>-contracts` instead of string literals; validating nested entities or arrays element-by-element; adding state transitions via `cloneWith` (leaf entity) or named domain methods like `publish`, `addSection`, `deactivate` that mutate `_field` + `touch()` (aggregate root); exposing typed getters or `toSnapshot()` for persistence boundaries.
- License
- MIT
- Metadata
- version: 0.1.0
- Instructions
- 78 lines in SKILL.md · view on GitHub
Before installing
- Ships executable scripts
Files (10)
- CHANGELOG.md
- LICENSE
- README.md
- SKILL.md
- README.es-ES.md · docs/i18n/
- README.pt-BR.md · docs/i18n/
- product.entity.test.ts · examples/
- product.entity.ts · examples/
- package.json
- entity-pattern.md · references/
SKILL.md (first lines)
# TypeScript DDD Entity
**MANDATORY — READ ENTIRE FILE**: Before any implementation step, read
[`references/entity-pattern.md`](references/entity-pattern.md) completely.
**Do NOT load** other DDD skills (use-case, repository, dto) unless explicitly requested.
---
## Before You Start
Before writing a single line, answer:
- **Bounded context**: which BC owns this entity? File lands at `apps/api/src/<bc>/domain/entities/<name>.entity.ts` and is re-exported by that folder's `index.ts` barrel.
- **Identity**: is `id` optional on create (use `Id.tryCreate` / let the `Entity` base auto-generate via `Id.create(props.id!)`) or a required foreign relation (validate with `Id.required`)?
- **Closed-set fields**: every status / kind / layout / provider / palette / discriminator must come from a **string-backed TS enum** in `libs/contracts/<bc>/src/interfaces/` or `libs/shared` — never inline string literals or `as const` tuples.
- **Invariants**: which VO (`Slug`, `PaletteKey`, `ImageRefValue`, …) validates each field? Are there arrays of IDs or nested entities (e.g. `Section[]` inside `Celebration`)?
- **State transitions**: does behavior require a domain method? Use `cloneWith` for immutable swap-and-revalidate, or mutate `_field` + `this.touch()` for entities that own a mutable collection (see `Celebration`).
- **Constructor visibility**: `private` for leaf entities; `protected` only when subclasses need access.
---
## Core Rules
- Extend `Entity<Type, Props>` from `@acme/shared`; keep constructor `private` or `protected`.
- Import enums and tagged unions from `@acme/<bc>-contracts` (e.g. `@acme/celebrations-contracts`). Never redefine wire types in the entity file.
- Expose dual API: `tryCreate(props): Result<T>` (returns Result, **canonical**) and `create(props): T` (delegates to `tryCreate` + `throwIfFailed`).
- Validate every field via VOs / type guards + collect errors (either `Result.combine([...])` or a manual `errors: string[]` accumulator — both patterns exist in this codebase; use `Result.combine` when all checks return `Result<T>`).
- Always store **normalized** values. Spread `vo.instance.value` for scalars; for sibling entities, prefer building from `Section.tryCreate(sp)` and keeping the array as `Section[]` in a private field while keeping `SectionProps[]` in `props` for serialization.
- Getters expose domain values; `this.props` is never accessed from outside the entity class.
- `cloneWith(overrides)` deep-merges and re-runs `tryCreate` automatically — never call `tryCreate` by hand from a domain method when `cloneWith` suffices.
## Enum Rule (HARD)
Every closed set is a **string-backed TS enum** in the contracts package. Pattern:
```ts
export enum CelebrationStatusEnum {
DRAFT = "draft",
PUBLISHED = "published",
}
export const CELEBRATION_STATUSES = Object.values(CelebrationStatusEnum);
export type CelebrationStatus = (typeof CelebrationStatusEnum)[keyof typeof CelebrationStatusEnum];
export function isCelebrationStatus(v: unknown): v is CelebrationStatus {
return typeof v === "string" && CELEBRATION_STATUSES.includes(v as CelebrationStatus);
}
```
Inside the entity:
- Validate with the type guard (`isCelebrationStatus(props.status)` → push `"INVALID_CELEBRATION_STATUS"` on failure).
- Store the value typed as the union (`CelebrationStatus`), emit it from a getter.
- Compare with the enum member: `this._status === CelebrationStatusEnum.PUBLISHED`. **Never** `=== "published"`.
- Singleton / limit catalogs reference enum members: `const SINGLETON_KINDS = [SectionKindEnum.HERO, SectionKindEnum.GALLERY, SectionKindEnum.SIGNATURE] as const`.
## Base Class Behaviour You Must Know
`Entity`'s protected constructor calls `Id.create(props.id!, { attribute: "id" })` and stores the normalized id, plus initializes `createdAt`/`updatedAt`/`deletedAt` if absent. Therefore:
- Do **not** set `createdAt`, `updatedAt`, `deletedAt` inside `tryCreate`. Use `this.props.updatedAt = new Date()` via a private `touch()` for mutations.
- `cloneWith` uses `structuredClone` on `props` before deep-merging, so nested objects are safe from caller mutation.
## NEVER
- **NEVER** use a raw string literal where an enum member exists (`"published"` → `CelebrationStatusEnum.PUBLISHED`).
- **NEVER** store raw VO input in `props` — always normalize via `vo.instance.value`.
- **NEVER** add a public setter — mutate state through a named domain method.
- **NEVER** skip validating array elements — loop and either push into a manual `errors[]` or `Result.combine` per-element results.
- **NEVER** put a domain invariant in the use case if it must hold for the entity from any caller.
- **NEVER** expose `this.props` to callers outside the entity — use typed getters or a deliberate `toSnapshot()` method.
- **NEVER** import from `@ddd/shared` (legacy alias). The shared lib is `@acme/shared`.
## References
See [`references/entity-pattern.md`](references/entity-pattern.md) for: real paths, canonical `tryCreate` snippet, enum-driven validation, array / nested-entity pattern, `cloneWith` vs mutable-collection mutation, test layout under `apps/api/test/`, and the pitfalls table.
See also [`examples/product.entity.ts`](examples/product.entity.ts) and [`examples/product.entity.test.ts`](examples/product.entity.test.ts) for a self-contained reference entity with an enum-driven status field.From llodev/skills, MIT.
More from llodev/skills
- 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-domain-service
llodev
Create, review, or guide pure Domain Service implementation 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-dto
llodev
Create, review, or guide Data Transfer Objects in a TypeScript + DDD monorepo.
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-controller
llodev
Create, review, or guide HTTP controllers in a TypeScript + DDD api.
SkillBFreshness: B★ 2Claude Code +9 - 0.563score
ts-ddd-domain-service
llodev
Create, review, or guide pure Domain Service implementation in a TypeScript + DDD monorepo.
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-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-entity skill. Agent Mart. https://agentmart.dev/skills/llodev-ts-ddd-entity (last updated 2026-10-24)