@huukhanhnguyen/model / schema/registry
schema/registry
ArgDef
ArgDef = {
attributes?:Record<string,unknown>;default?:string;key:string;max?:string;min?:string;step?:string;type:string; }
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.
attributes?
optionalattributes?:Record<string,unknown>
default?
optionaldefault?:string
key
key:
string
max?
optionalmax?:string
min?
optionalmin?:string
step?
optionalstep?:string
type
type:
string
ChainState
ChainState =
ObjectData|undefined
Mid-chain value: one *Data document. Empty stream is undefined.
ComputeArgs
ComputeArgs =
Record<string,unknown>
Evaluated + coerced arg values, keyed by ArgDef.key.
ComputeContext
ComputeContext = {
annotationStyles?:AnnotationStyle[];flat:boolean;imageUrlOf?: (name) =>string;materials?:Material[];sampleTexture?: (key) =>unknown;store?:StoreHost;textStyles?:TextStyle[]; }
store— session asset registry (fonts/materials/images/models), immutable during eval.
annotationStyles?
optionalannotationStyles?:AnnotationStyle[]
flat
flat:
boolean
True when the calling node evaluates in a 2D context: the owning chain is declared flat (ModelJSON.flat / Component.flat — a step can never declare itself flat), or it sits in a "flat" lane (a sheet's ad hoc operations — see schema/model.ts's FLAT_LANE_METHODS). Enforcement (flat vocabulary gate, point-arg z=0, per-step force-flatten) is engine-owned in DataNode; methods may read this to keep their own output planar. Always false for value nodes.
imageUrlOf?
optionalimageUrlOf?: (name) =>string
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) — imageData's name arg.
Parameters
name
string
Returns
string
materials?
optionalmaterials?:Material[]
The model's materials[] lane.
sampleTexture?
optionalsampleTexture?: (key) =>unknown
Resolve a textures-lane chain to its evaluated ImageBuffer (displace).
Parameters
key
string
Returns
unknown
store?
optionalstore?:StoreHost
textStyles?
optionaltextStyles?:TextStyle[]
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.
DataDefinition
DataDefinition =
OperationDefinitionBase& {compute?: (input,args,context) =>ChainState|Promise<ChainState>;create?: (args,context) =>ChainState|Promise<ChainState>;foldRole:"producer"|"transform"; }
FoldRole
FoldRole =
"binding"|"producer"|"transform"|"step"
How a method participates in evaluation — orthogonal to the value type: a binding returns "length", a producer returns "objectData[]", a material step returns "material"; the fold role is what the engine dispatches on.
FunctionNamespaces
FunctionNamespaces =
Record<string,Record<string, (...args) =>unknown>>
OperationDefinition
OperationDefinition =
ValueDefinition|DataDefinition|StepDefinition
OperationDefinitionBase
OperationDefinitionBase = {
_hooks?:NodeHooks;args?:ArgDef[];attributes?:Record<string,unknown>;defaultKey:string;foldRole:FoldRole;method:string;return:TypeName; }
method— dispatch + uniqueness key, globally unique across the WHOLE registry.defaultKey— friendly base for auto-generated node keys ("arc"→ arc1, arc2…).return— TypeName from the type table (list form with[]when yielding a list).foldRole— binding | producer | transform | step (see module doc).attributes— opaque frontend metadata; never read by the engine for graph law.
_hooks?
optional_hooks?:NodeHooks
Lifecycle observers attached to the DECLARATION — composed onto every node built from this definition (see nodes/hooks.ts). Never serialized; a definition is a runtime registry object, not document JSON.
args?
optionalargs?:ArgDef[]
attributes?
optionalattributes?:Record<string,unknown>
defaultKey
defaultKey:
string
foldRole
foldRole:
FoldRole
method
method:
string
return
return:
TypeName
RegistryInput
RegistryInput = {
builtinMaterials?:Material[];builtinParameterMethods?:Record<string,string>;builtinParameters?:string[];catalogParameters?:string[];namespaces?:FunctionNamespaces;nodes?:OperationDefinition[];types?:TypeDef[]; }
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.
builtinMaterials?
optionalbuiltinMaterials?:Material[]
builtinParameterMethods?
optionalbuiltinParameterMethods?:Record<string,string>
builtinParameters?
optionalbuiltinParameters?:string[]
catalogParameters?
optionalcatalogParameters?:string[]
namespaces?
optionalnamespaces?:FunctionNamespaces
nodes?
optionalnodes?:OperationDefinition[]
types?
optionaltypes?:TypeDef[]
StepDefinition
StepDefinition =
OperationDefinitionBase& {foldRole:"step"; }
Linear-lane step (materials/layers/styles/textStyles/annotationStyles/ cameras/views/animations/tables/textures, plus objects[] properties[]). No data-fold create/compute — the lane's own evaluator is the sole consumer.
TypeName
TypeName =
string
A TYPE_REGISTRY name, optionally with a list suffix (objectData[], length[]). INPUT arg types and OUTPUT returns share this vocabulary.
ValueDefinition
ValueDefinition =
OperationDefinitionBase& {compute?: (args,context) =>unknown|Promise<unknown>;foldRole:"binding"; }