domain-objects
Version:
A simple, convenient way to represent domain objects, leverage domain knowledge, and add runtime validation in your code base.
33 lines (32 loc) • 1.81 kB
TypeScript
import type { SchemaOptions } from '../instantiation/validate/validate';
/**
* .what = the static-metadata view of a domain object class, by the statics `.contract` /
* `.contract.ref` read off the class — never an instance
* .why =
* - typed structurally (not as `typeof DomainObject`) so concrete dobj subclass constructors are
* assignable; `typeof DomainObject` has a generic `<T>` construct signature that subclass
* constructors do not satisfy
* - `primary`/`unique` live on DomainEntity/DomainLiteral, `nested` on DomainObject; all optional
* - one shared shape so `getContract` and `getContractRef` cannot silently drift (a new static
* added to one view but not the other) — the same hand-sync hazard that caused a real bug once
* .note = broader than the canonical `DomainObjectConstructor` (which omits these key statics);
* both readers read statics only and never instantiate, so neither needs the `new()`/`build`
* members of that type
* .note = `nested` is `Record<string, any>` (not a precise dobj-class type): the value is a nested
* dobj *constructor* (or an array of choices), whose type does not fit a static-view shape
* cleanly — matches `DomainObject.nested`'s own imprecise type
* .note = `alias` is optional and read only by `getContract` (it stamps it into `x-domain-object`);
* `getContractRef` never reads it (a ref is `{ of, by }`) and simply leaves it untouched. one
* shared shape keeps the two readers from drift — a static added here reaches both.
*/
export type DomainObjectClass = {
name: string;
schema?: SchemaOptions<any>;
primary?: readonly string[];
unique?: readonly string[];
nested?: Record<string, any>;
alias?: string | {
plural?: string;
singular?: string;
};
};