2.4 KiB
2.4 KiB
Core Domain Model Rules
Follow these rules for all changes in core/.
Purpose
core/contains pure domain types for the image editor: documents, artboards, layers, assets, ids, and geometry.- Keep it framework-free, runtime-light, and reusable by renderer, commands, persistence, and tests.
Hard Rules
- Do not import React, DOM APIs, UI components, storage, networking, filesystem, command handlers, or renderer code.
- Do not add side effects, global state, caches, singletons, or environment-dependent behavior.
- Prefer exported TypeScript
types. Add runtime code only when it is pure, deterministic, and domain-generic. - Keep domain files small and focused. One concept per file; re-export public types from
core/index.ts. - Use
import type/export typefor type-only dependencies. - Preserve discriminated unions. Every
Layervariant must have a stabletypestring. - Do not weaken domain types with
any, broadstring | numberunions, optional fields, or nullable values unless the domain truly allows absence. - IDs are opaque aliases from
id.ts; do not inline plainstringID fields in models. - Do not duplicate geometry shapes outside
geometry.ts. UseVec2D,Size,Rect,Bounds,Transform,Mat2D, andCoordinateSpace. - Avoid app/workflow concerns in names and fields. Domain models describe image-editing state, not UI state.
Model Invariants
ImageDocumentownsartboardsand sharedassets.Artboardowns top-levellayersand has document-spacebounds.LayerGroup.childrenowns nested layers; only groups have children.ImageLayer.assetIdmust reference anAsset.idin the same document.BaseLayer.opacityis normalized0..1;visibleandlockedare explicit booleans.Transformstores position, scale, and rotation only; derived matrices/bounds should not be persisted on models.clippingMask.maskLayerIdreferences another layer byLayerId; do not embed mask layer objects.
Changing Models
- Before adding a field, decide whether it is core persisted state or derived/UI state. Derived/UI state does not belong here.
- When adding a new domain type, create a focused file and export it from
index.ts. - When adding a new layer kind, update the union in
layer.ts, add a discriminant, and document its required relationships. - Keep names stable and serialization-friendly; assume these types may be saved, loaded, diffed, and migrated.