/** * Trellis Schema — typed entity definitions over the ontology. * * `defineType` is the Trellis answer to Jazz's `co.map`: one definition produces * BOTH a runtime {@link SchemaDefinition} (registerable in the kernel via * `createOntology`) AND a static TypeScript type via {@link InferType}. Zod * handles leaf validation + inference; a second options bag handles the graph * semantics Zod can't express — relation cardinality, rollups, formulas, tier. * * This deliberately targets `SchemaDefinition` (the live kernel path consumed by * schema/rollup middleware), not the legacy `OntologySchema` registry — see * {@link TrellisType.toOntologySchema} for the legacy adapter. * * import { defineType, rel } from 'trellis/schema'; * import { z } from 'zod'; * * const NavItem = defineType('NavItem', { * label: z.string(), * icon: z.string().optional(), * order: z.number(), * }, { title: 'label' }); * * const NavSection = defineType('NavSection', { * label: z.string(), * order: z.number(), * collapsed: z.boolean(), * }, { title: 'label', relations: { items: rel(() => NavItem, 'many') } }); * * type Section = InferType; * // { id: string; type: 'NavSection'; label: string; order: number; * // collapsed: boolean; items: Ref[] } * * @module trellis/schema */ import { z } from 'zod'; import type { FieldSyncTier, OntologySchema, OntologyTier, PropertyType, PropertyValueSpecification, SchemaDefinition } from '../core/ontology/types.js'; /** * A reference to another entity. Unresolved it is the target's id (a `string`); * a future `resolve` option swaps it for the loaded {@link InferType} value. */ export type Ref = string & { readonly __ref?: S; }; export type RelTarget = (() => S) | string; export interface Relation { readonly target: RelTarget; readonly cardinality: C; } /** Declare a relation field. Target may be a thunk (define-order safe) or a name. */ export declare function rel(target: RelTarget, cardinality?: C): Relation; export type RelationMap = Record>; export interface ComputedField { readonly spec: Partial & { valueType: PropertyType; }; } export type ComputedMap = Record; /** Declare a rollup over a relation (e.g. count of linked items). */ export declare function rollup(cfg: NonNullable): ComputedField; /** Declare a formula field. */ export declare function formula(expr: string): ComputedField; export interface TrellisType { readonly type: Name; /** Leaf validator (does not include relations/computed). */ readonly zod: z.ZodObject; readonly relations: R; readonly computed: C; /** Kernel-facing schema, keyed by `@id` = `trellis:`. */ readonly definition: SchemaDefinition; /** Adapter to the legacy OntologyRegistry (relation resolution only). */ toOntologySchema(): OntologySchema; } export type AnyType = TrellisType; type RelValue = X extends Relation ? C extends 'many' ? Ref[] : Ref : never; export type InferType = T extends TrellisType ? { id: string; type: Name; } & z.infer> & { [K in keyof R]: RelValue; } & { readonly [K in keyof C]: number; } : never; /** Target entity schema of a relation field. */ type RelationTarget = R extends Relation ? S : never; /** * Typed `resolve` spec for {@link InferResolvedType} — mirrors runtime * {@link import('./resolve.js').ResolveSpec} but keyed to declared relations. * * `{ items: true }` — expand `items` to full entities. * `{ items: { section: true } }` — expand `items`, then each item's `section`. */ export type ResolveSpecFor = { [K in keyof T['relations'] & string]?: true | ResolveSpecFor>; }; /** Expand one relation key according to a resolve spec entry (`true` or nested). */ type ApplyResolve, Spec> = Field extends Relation ? [Spec] extends [true] ? C extends 'many' ? InferType[] : InferType : Spec extends ResolveSpecFor ? C extends 'many' ? InferResolvedType[] : InferResolvedType : RelValue : never; /** * Like {@link InferType}, but relation keys in `resolve` are expanded entity * shapes instead of `Ref` ids. Nested objects recurse (TRL-4). */ export type InferResolvedType> = T extends TrellisType ? { id: string; type: Name; } & z.infer> & { [K in keyof Rel]: K extends keyof R ? ApplyResolve : RelValue; } & { readonly [K in keyof C]: number; } : never; /** * Infer the entity array shape returned by typed live reads (`useEntities`, * `entitiesStore`) from optional read options. */ export type InferEntitiesRead = O extends { resolve: infer R; } ? R extends ResolveSpecFor ? InferResolvedType[] : InferType[] : InferType[]; /** * Infer the entity shape returned by typed single-entity reads (`useEntity`, * `entityStore`) from optional read options. */ export type InferEntityRead = O extends { resolve: infer R; } ? R extends ResolveSpecFor ? InferResolvedType | null : InferType | null : InferType | null; export interface DefineTypeOptions { /** Which leaf key is the entity's `title` property. */ title?: Extract; relations?: R; computed?: C; /** Per-field sync tier (ADR 0018). */ fieldSync?: Partial, FieldSyncTier>>; /** Defaults to 'user'. Core/system are reserved for shipped schemas. */ tier?: OntologyTier; version?: string; /** Parent type name (`subClassOf`). */ extends?: string; label?: string; } export declare function defineType, C extends ComputedMap = Record>(type: Name, shape: Z, opts?: DefineTypeOptions): TrellisType; export {}; //# sourceMappingURL=define.d.ts.map