Catalog Domain
The catalog domain provides product and category management for TypeScript backends. It handles product creation, publishing lifecycle, variant management with SKU validation, pricing, and category hierarchies.
Install
Section titled “Install”npx @backcap/cli add catalogDomain Model
Section titled “Domain Model”Product Entity
Section titled “Product Entity”The Product entity is the aggregate root. It owns its variants and enforces business rules (no duplicate SKUs, state machine transitions).
import { Product } from "./domains/catalog/domain/entities/product.entity";
const result = Product.create({ id: crypto.randomUUID(), name: "Wireless Headphones", description: "Premium wireless headphones with noise cancellation", basePriceCents: 9999,});
if (result.isOk()) { const product = result.unwrap(); console.log(product.status.value); // "draft" console.log(product.basePrice.cents); // 9999}| Field | Type | Description |
|---|---|---|
id | string | Unique identifier (UUID) |
name | string | Product name |
description | string | Product description |
status | ProductStatus | draft, active, or archived |
basePrice | Money | Base price in integer cents |
categoryId | string | null | Optional category reference |
variants | ProductVariant[] | Product variants |
State Machine
Section titled “State Machine”Products follow a strict state machine:
- draft → active via
product.publish() - active → archived via
product.archive() - No reverse transitions
ProductVariant Entity
Section titled “ProductVariant Entity”import { ProductVariant } from "./domains/catalog/domain/entities/product-variant.entity";
const variant = ProductVariant.create({ id: crypto.randomUUID(), productId: "prod-123", sku: "WH-BLK-L", priceCents: 10999, attributes: { color: "black", size: "L" },});Category Entity
Section titled “Category Entity”Categories support hierarchy via flat parentId references.
import { Category } from "./domains/catalog/domain/entities/category.entity";
const category = Category.create({ id: crypto.randomUUID(), name: "Electronics", slug: "electronics", parentId: null, // root category});Value Objects
Section titled “Value Objects”| VO | Description |
|---|---|
SKU | Validated alphanumeric format (3-50 chars), auto-uppercased |
Money | Integer cents with ISO 4217 currency, add(), subtract(), multiply() |
ProductStatus | Enum: draft, active, archived with state machine |
Use Cases
Section titled “Use Cases”| Use Case | Description |
|---|---|
CreateProduct | Create a new draft product |
PublishProduct | Transition product from draft to active |
AddVariant | Add a variant with SKU validation |
UpdatePrice | Update product base price |
ListProducts | List all products |
GetProduct | Get a single product by ID |
CreateCategory | Create a category with unique slug |
ListByCategory | List products in a category |
Contract
Section titled “Contract”import { createCatalogService } from "./domains/catalog/contracts";import type { ICatalogService } from "./domains/catalog/contracts";
const catalog: ICatalogService = createCatalogService({ productRepository, categoryRepository,});
// Create a productconst result = await catalog.createProduct({ name: "Widget", description: "A great widget", basePriceCents: 1999,});