Skip to content
Shapemetry

@huukhanhnguyen/model / nodes/NodeCollection

nodes/NodeCollection

NodeCollection

Extends

Type Parameters

T

T extends BaseNode = BaseNode

Constructors

Constructor

new NodeCollection<T>(owner): NodeCollection<T>

Parameters

owner

unknown

Returns

NodeCollection<T>

Overrides

BaseCollection.constructor

elements

elements: T[] = []

Inherited from

BaseCollection.elements

id

id: string

Inherited from

BaseCollection.id

owner

owner: any

Inherited from

BaseCollection.owner

Accessors

model

Get Signature

get model(): any

Returns

any

Inherited from

BaseCollection.model

registry

Get Signature

get registry(): Registry | undefined

The merged node registry, resolved through the owner chain (the root collection's owner is the ModelScope carrying it). Detached collections (a node not yet added) resolve nothing — the fromJSON path threads the registry explicitly instead.

Returns

Registry | undefined

Methods

_bulkAdd()

protected _bulkAdd(entries): void

Bulk attach (load path) must invalidate the same structure-keyed caches the per-item "add" listener does — keyedNodes and the shared expression context key off _structureVersion, and a load IS a structural change.

Parameters

entries

T[]

Returns

void

Overrides

BaseCollection._bulkAdd

_dispose()

_dispose(): void

Returns

void

Inherited from

BaseCollection._dispose

_takenKeys()

protected _takenKeys(): Set<string>

Every key/name currently held by this collection's elements.

Returns

Set<string>

Inherited from

BaseCollection._takenKeys

add()

add(entry, index?): void

Parameters

entry

T

index?

number = ...

Returns

void

Inherited from

BaseCollection.add

addContainer()

addContainer(key?): ContainerNode

Create and add an empty Group; returns the new node.

Parameters

key?

string

Returns

ContainerNode

addEntry()

addEntry(method, key?): ParameterNode

Parameters

method

string

key?

string

Returns

ParameterNode

addListener()

addListener(event, listener): () => void

Parameters

event

string

listener

Listener

Returns

() => void

Inherited from

BaseCollection.addListener

addOperation()

addOperation(method, argsMap?, key?): DataNode

Create and add a data operation bound to the given registry method. Auto-assigns a model-wide-unique key from the registry's defaultKey ("array1", "fillet2", …) so the result is referenceable immediately.

Parameters

method

string

argsMap?

Record<string, string> = {}

key?

string

Returns

DataNode

createFromJSON()

createFromJSON(json, registryParam?, lane?): T | null

Deserialize a single Operation | Group (operation | Group form) into the appropriate typed node instance, or null if unrecognized. lane = which model section the node sits in — value methods build ParameterNode (header), data methods build DataNode.

Parameters

json

Operation | Group

registryParam?

Registry

lane?

ModelLane = "scene"

Returns

T | null

evaluate()

evaluate(): void

Returns

void

findById()

findById(id?): T | undefined

Parameters

id?

string

Returns

T | undefined

Inherited from

BaseCollection.findById

fromJSON()

fromJSON(items, registry?, lane?): void

Load a body/header list. Steps that arrive WITHOUT a key get one here, after the whole list is linked — createFromJSON deliberately leaves it unset (a nested child's tree isn't complete yet, so generateKey() there could collide with an ancestor it can't see), and this is the first point where generateKey() sees every existing key.

Every lane goes through this one call, which is the point: the backfill used to live in Model.fromJSON and therefore ran for the ROOT operations and nothing else. A keyless step inside a sheets[]/ components[] body stayed keyless forever, so nothing downstream could name the node that drew a placement. That is what left every AI-authored sheet undraggable on the sheet canvas (a host skips a keyless node): not a canvas bug, a missing key.

Parameters

items

(Operation | Group)[]

registry?

Registry

lane?

ModelLane = "scene"

Returns

void

generateKey()

generateKey(baseName): string

Parameters

baseName

string

Returns

string

getLength()

getLength(listener?): number

Parameters

listener?

Listener

Returns

number

Inherited from

BaseCollection.getLength

getMapKey()

getMapKey(): Record<string, BaseNode>

Returns

Record<string, BaseNode>

keyedNodes()

keyedNodes(): KeyedNodeEntry[]

Every operation/Group/parameter node reachable by key — top-level plus every nested Group's children, recursively — cached per structure version (see constructor). Replaces re-walking the whole tree on every single expression recompute (ExpressionNode._buildContext used to do this unconditionally, once per dirty expression).

Returns

KeyedNodeEntry[]

keyExists()

keyExists(key, except?): boolean

True when key is used by any node in the model other than except.

Parameters

key

string

except?

BaseNode

Returns

boolean

move()

move(entry, newIndex): void

Parameters

entry

T

newIndex

number

Returns

void

Inherited from

BaseCollection.move

notify()

notify(event, ...args): void

Parameters

event

string

args

...unknown[]

Returns

void

Inherited from

BaseCollection.notify

remove()

remove(entry): void

Parameters

entry

T

Returns

void

Inherited from

BaseCollection.remove

removeListener()

removeListener(event, listener): void

Parameters

event

string

listener

Listener

Returns

void

Inherited from

BaseCollection.removeListener

renameReferences()

renameReferences(oldKey, newKey): void

Rewrite every expression in the model that references oldKey as an identifier to newKey — called after a successful setKey() so a rename doesn't silently break every formula that referenced the old name. Each rewritten node's setInput() cascades its own dirty flag; this re-evaluates once at the end (a single batch, not one pull per rewritten expression).

Parameters

oldKey

string

newKey

string

Returns

void

rootNodes()

rootNodes(): NodeCollection

The model's ROOT node collection. Keys are referenced from expressions model-wide, so key generation/rename checks must see EVERY node — not just this subtree (a Group's child colliding with a root node would make the reference ambiguous). Falls back to this collection when detached.

Returns

NodeCollection

set()

set(elements): void

Parameters

elements

T[]

Returns

void

Inherited from

BaseCollection.set

sharedEvalContext()

sharedEvalContext(): EvalContext

Shared expression eval scope for every ExpressionNode under this tree. Cached per structure version (same invalidation as keyedNodes). Node getters call dependOn so dependency edges register only while an expression is on the evaluation stack — not when UI previews call buildContext() outside evaluate.

Returns

EvalContext

toJSON()

toJSON(): (Record<string, unknown> | BaseObjectJSON)[]

Returns

(Record<string, unknown> | BaseObjectJSON)[]

Inherited from

BaseCollection.toJSON

traverse()

traverse(fn): void

Walk every node in the collection (including nested children) and call fn on each.

Parameters

fn

(node) => void

Returns

void

uniqueKey()

uniqueKey(keyname): string

Parameters

keyname

string

Returns

string

Inherited from

BaseCollection.uniqueKey

uniqueKeyFrom()

protected static uniqueKeyFrom(taken, keyname): string

keyname, then keyname1, keyname2, … — first not in taken.

Parameters

taken

Set<string>

keyname

string

Returns

string

Inherited from

BaseCollection.uniqueKeyFrom

Last updated: 📖 7 min readEdit on GitHub