Model - Registry
API reference for src/schema/registry, src/conventions/registry, src/registry/Registry, src/validate/registry on @huukhanhnguyen/model, reachable from ..
See the Guide for the ModelJSON / evaluate pipeline.
API reference
Signatures are generated from the live package .d.ts - not hand-written.
ArgDef
type
The RUNTIME arg definition — the registry contract for OperationDefinition.args. The AUTHORED/catalog arg shape (typed label/tooltip/options/description fields) is NodeArgEntry (schema/nodesRegistry.ts); nodesRegistry/wiring.ts's toArgDef packs those into the opaque attributes bag below, so the two layers never drift.
type ArgDef
// = {
key: string;
type: string;
default?: string;
min?: string;
max?: string;
step?: string;
attributes?: Record<string, unknown>;
}ChainState
type
type ChainState
// = Entity[]ComputeArgs
type
Evaluated + coerced arg values, keyed by ArgDef.key.
type ComputeArgs
// = Record<string, unknown>ComputeContext
type
store— session asset registry (fonts/materials/images/models), immutable during eval.definitions— model definition registry (id → shared geometry) for resolving nested blocks.
type ComputeContext
// = {
store?: StoreHost;
definitions?: DefinitionMap;
/** True when the calling node evaluates in a 2D context: the node itself
* (or an ancestor container) is declared `flat: true`, or it sits in a
* "flat" lane (a sheet's ad hoc operations / flat component content —
* see schema/model.ts's FLAT_LANE_METHODS). Enforcement (flat
* vocabulary gate, point-arg z=0, per-step force-flatten) is
* engine-owned in EntitiesNode; methods may read this to keep their
* own output planar. Always false for value nodes. */
flat: boolean;
/** The model's materials[] lane. */
materials?: Material[];
/** The model's textStyles[] / annotationStyles[] lanes, RESOLVED. A
* drafting mark builds its drawn form at evaluate time, which is when the
* style has to be known — see nodesRegistry/wiring.ts's
* STYLE_AWARE_METHODS. A name matching neither a record here nor the
* builtin "standard" throws rather than drawing something arbitrary. */
textStyles?: TextStyle[];
annotationStyles?: AnnotationStyle[];
/** Resolve a textures-lane chain to its evaluated ImageBuffer (displace). */
sampleTexture?: (key: string) => unknown;
/** Resolve a url-method parameter KEY to its literal url (falls back to
* the ref itself when no parameter matches, so a direct https:/data: URI
* passes through unchanged) — imageEntity's `name` arg. */
imageUrlOf?: (name: string) => string;
}ConventionRegistry
class
class ConventionRegistryMembers: all, get, register
createRegistry
function
Merge the engine's own builtins + the given RegistryInput into a validated Registry. registry.nodes (OperationDefinition[]) is itself the serializable view docs/UI menus render from — nothing to strip, create/compute are just unused function properties for a consumer that only reads attributes/args.
createRegistry(input?: RegistryInput): RegistryEntityDefinition
type
type EntityDefinition
// = OperationDefinitionBase & { foldRole: "producer" | "transform"; /** PRODUCER form — the engine concats [...input, ...create(args, context)]. */ create?: (args: ComputeArgs, context: ComputeContext) => ChainState | Promise<ChainState>FoldRole
type
How a method participates in evaluation — orthogonal to the value type: a binding returns "length", a producer returns "entity[]", a material step returns "material"; the fold role is what the engine dispatches on.
type FoldRole
// = "binding" | "producer" | "transform" | "step"FunctionNamespaces
type
type FunctionNamespaces
// = Record<string, Record<string, (...args: unknown[]) => unknown>>mergeConventions
function
Build a registry from a base set plus any pack sets, later wins per lane — the same last-writer merge createRegistry uses for nodes.
mergeConventions(...sets: Convention[][]): ConventionRegistryOperationDefinition
type
type OperationDefinition
// = ValueDefinition | EntityDefinition | StepDefinitionRegistry
class
Registry — the merged, validated view over the engine's own builtins plus one flat RegistryInput. Built ONCE per composition via createRegistry(input) and passed to Model.fromJSON(json, { registry }); there is no module-global mutable registry. Two registries can coexist in one process.
v21 — ONE table of OperationDefinitions, keyed by globally-unique method. The container form has no method and never appears here.
class RegistryMembers: argDefs, argKeys, argTypes, defaultKeyOf, entity, has, isReservedKey, methods, operation, typeOf, value
registryErrors
function
registryErrors(model: ModelJSON, registry: Registry): RegistryError[]RegistryInput
type
The flat input createRegistry(input) merges onto the engine's own builtins. List order = display/catalog order (there is deliberately no order metadata).
namespaces— PascalCase expression namespaces (Point., Vector., …). Names become reserved (node keys cannot shadow them).types— extra value types. These are INERT: display + coerce hook only — they never join the core dimension lattice (unit inference).builtinParameters— reserved parameter keys auto-seeded per model (e.g. lengthX/lengthY/lengthZ).builtinParameterMethods— for eachbuiltinParameters/catalogParameterskey, the value method required to legitimately claim it (e.g.{ lengthX: "length", lengthY: "length" }). A builtin key absent here is reserved outright: no node may ever take it.catalogParameters— reserved app-layer identity parameter keys (host-injected; core ships the mechanism empty — no domain vocabulary) (manufacturer/sku/price/currency/productUrl). Reserved exactly likebuiltinParameters(a key is claimable only by a value node whose method matchesbuiltinParameterMethods) but deliberately NOT part of that set:builtinParametersdoubles as the auto-seed list AND the host-facing filter (the viewer element, the /embed postMessage SDK and the ConfiguratorPanel all hidebuiltinParametersfrom their parameter lists), and catalog params must STAY VISIBLE — a shop needs price/currency inparashape:ready/parashape:changeand in the evaluate API output. Never auto-seeded: a model without catalog metadata simply omits them.builtinMaterials— named material records a node set's own generators stamp by name (e.g. thetreenode's bark/leaf textures) but that don't live in any document'smaterials[]lane. Merged UNDER the doc lane by the engine's material collector (Model.ts'scollectMaterials) — a doc record with the same name always overrides a builtin one.
type RegistryInput
// = {
nodes?: OperationDefinition[];
namespaces?: FunctionNamespaces;
types?: TypeDef[];
builtinParameters?: string[];
builtinParameterMethods?: Record<string, string>;
catalogParameters?: string[];
builtinMaterials?: Material[];
}StepDefinition
type
Linear-lane step (docs/views/materials/layers/styles/helpers/lights/cameras). No entity-fold create/compute — the lane's own evaluator is the sole consumer.
type StepDefinition
// = OperationDefinitionBase & { foldRole: "step"; }TypeName
type
A TYPE_REGISTRY name, optionally with a list suffix (entity[], length[]). INPUT arg types and OUTPUT returns share this vocabulary.
type TypeName
// = stringValueDefinition
type
type ValueDefinition
// = OperationDefinitionBase & { foldRole: "binding"; /** Optional value-build hook for a registry-declared resource lookup; * scalar parameters omit it — their value is the evaluated primary arg. */ compute?: (args: ComputeArgs, context: ComputeContext) => unknown | Promise<unknown>