Model - Nodes
API reference for the default ParaShape node registry (@huukhanhnguyen/model/nodes).
A registry maps method strings ("rectangle", "curveExtrude", …) to create/compute implementations. Model.fromJSON requires a registry.
This page is the registry's TYPES. For what is IN the registry — every method, its args, defaults and meanings — see the method tables, one page per lane, listed on the Guide.
API reference
Signatures are generated from the live package .d.ts - not hand-written.
Fn
type
type Fn
// = (...args: unknown[]) => unknownFUNCTION_REGISTRY
const
const FUNCTION_REGISTRY: FunctionRegistryEntry[]FunctionArgEntry
type
Function Registry — raw catalog data for PascalCase namespace functions (Point, Vector, NurbsCurve, …) available inside expressions. Type-checked via satisfies FunctionRegistryEntry[]. Replaces schema/functions.json — same data, TypeScript-native.
type FunctionArgEntry
// = {
type: string;
desc: string;
}FunctionRegistryEntry
type
type FunctionRegistryEntry
// = {
namespace: string;
method: string;
label: string;
args: Record<string, FunctionArgEntry>;
returns: string;
tooltip: string;
/** Injected per evaluation (closes over model state) instead of being
* bound from a compute module — see functionRegistry/wiring.ts, which
* skips these, and nodes/ExpressionNode.ts's `_buildContext`, which
* supplies them. Declared here so the catalog stays the WHOLE
* expression surface for docs / the AI grammar / autocomplete. */
runtime?: true;
}NODE_REGISTRY
const
const NODE_REGISTRY: NodeRegistryEntry[]NodeArgEntry
type
THE authored arg definition — one arg of a vocabulary/catalog method entry, with its display metadata as TYPED fields. This is the single shape the lane vocabularies (vocabulary/laneMethods.ts, vocabulary/cameras.ts) and the hand-written catalog entries (nodesRegistry/catalog.ts barrel) declare args with. Deliberately NOT the runtime contract: the registry's ArgDef (schema/registry.ts) carries display metadata in an opaque attributes bag instead — wiring.toArgDef packs label/tooltip/options/description into it, so the two layers can never drift.
type NodeArgEntry
// = {
key: string;
/** A TYPE_REGISTRY name (list suffix allowed, e.g. "string[]"). A union
* form (`color | vector`) reads "either shape is accepted". */
type: string;
default?: string;
min?: string;
max?: string;
step?: string;
label?: string;
tooltip?: string;
options?: string[];
description?: string;
/** Texture lane only: the text compiles PER PIXEL as `(u, v, t, k)`. */
formula?: true;
}nodeNamespaces
const
Computation namespaces — the PascalCase expression substrate (Point., Vector., NurbsCurve., Surface., Face., Plane., Axis.*). Registered via RegistryInput.namespaces (no module-load side effects).
Mirrors nodesRegistry/: catalog.ts is the SSOT (what exists), this file WIRES it (where each entry's implementation comes from).
const nodeNamespaces: FunctionNamespacesnodeRegistry
const
node registry wiring — transforms the raw catalog (catalog.ts, display metadata) into engine OperationDefinitions with compute functions wired to the standalone compute substrate (@huukhanhnguyen/model/compute).
v21 wiring shapes (stream state = Entity[]):
- producer (old generator) →
create: fn(...orderedArgs) → Entity[]; the ENGINE concats [...input, ...created] - transform/prop → mapCompute: maps ALL entities INCLUDING nested groups (a transform composes onto a group's placement; a prop stamps the wrapper = per-copy)
- geometry transform → applyGeometry(input, entityOp(fn, args, types)) — nested blocks pass through untouched
The engine's own CORE_NODES already provide the builtins (scalar values, clone, blockExplode/looseToBlock/makeBlock) — those catalog entries are display-only here and get filtered. The container form is grammar, not a method (v21) — no entry, no definition.
const nodeRegistry: RegistryInputNodeRegistryEntry
type
type NodeRegistryEntry
// = {
nodeType: "parameter" | "generator" | "modifier" | "document" | "camera" | "layer" | "material" | "style" | "textStyle" | "annotationStyle" | "view" | "skeleton" | "animation" | "table" | "texture";
namespace?: string;
method?: string;
/** Declared return type, when the wiring cannot infer it. A PRODUCER's
* return is the type of what it CREATES (its own tail), not the stream
* after it — see registry/contract.ts. Absent = wiring derives it
* (`entity[]` for transforms, the compute's own domain for producers). */
return?: string;
/** Friendly short identifier base for auto-generated node keys ("arc" for
* every arc generator, "array" for every array*) — the key a new
* node gets is `defaultKey` + a model-wide-unique increment. The full
* human name stays in `label`. */
defaultKey?: string;
label?: string;
/** Icon lookup key (packages/ui's NodeIcons.ts svg tables) when it differs
* from `method` — e.g. a renamed method reusing an old icon. Absent =
* UI falls back to `method` itself as the key. */
icon?: string;
shape?: "map" | "multiply" | "reduce" | "structural";
role?: "transform" | "prop";
tooltip?: string;
args?: NodeArgEntry[];
}