Skip to content
Shapemetry

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[]) => unknown

FUNCTION_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: FunctionNamespaces

nodeRegistry

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: RegistryInput

NodeRegistryEntry

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[];
}
Last updated: 📖 2 min readEdit on GitHub