Skip to main content
Version: 0.1.0

Node Operations

CRUD operations, tree traversal, and relationships.

NodeOperations

Access node operations through a workspace:

const ws = db.workspace('content');
const nodes = ws.nodes();

create()

create(options: NodeCreateOptions): Promise<Node>
interface NodeCreateOptions {
type: string;
path: string;
properties?: Record<string, any>;
content?: any;
}

createDeep()

Create a node, auto-creating any missing ancestor folders along path. Ancestors are created as parentNodeType (defaults to raisin:Folder).

createDeep(options: NodeCreateDeepOptions): Promise<Node>
interface NodeCreateDeepOptions extends NodeCreateOptions {
parentNodeType?: string; // default: "raisin:Folder"
}

upsertDeep()

Create-or-update a node by path (in place if it already exists), auto-creating any missing ancestor folders.

upsertDeep(options: NodeCreateDeepOptions): Promise<Node>

get()

Get a node by ID.

get(id: string): Promise<Node | null>

getByPath()

Get a node by its path.

getByPath(path: string): Promise<Node | null>

update()

update(id: string, options: NodeUpdateOptions): Promise<Node>

delete()

delete(id: string): Promise<boolean>

query()

query(options: NodeQueryOptions): Promise<Node[]>

queryByType()

queryByType(nodeType: string, limit?: number): Promise<Node[]>

queryByProperty()

queryByProperty(name: string, value: any, limit?: number): Promise<Node[]>

History & Audit

history()

List a node's revision history (git-style "file history"), newest first. This is the structural MVCC version history and is always available for every node, regardless of the NodeType auditable flag.

history(id: string, options?: { limit?: number }): Promise<RevisionEntry[]>
historyByPath(path: string, options?: { limit?: number }): Promise<RevisionEntry[]>

interface RevisionEntry {
revision: string; // HLC revision, usable with atRevision()
updated_at?: string; // ISO 8601
updated_by?: string; // user id that authored this revision
deleted: boolean; // true if the node was deleted at this revision
}
const ws = db.workspace('content');

// List the last 50 revisions of a node
const revisions = await ws.nodes().history(nodeId, { limit: 50 });

// Fetch the full snapshot of a historical version
for (const rev of revisions) {
const snapshot = await ws.atRevision(rev.revision).nodes().get(nodeId);
}

auditLog()

Query a node's audit-log entries. Audit logs are only produced for NodeTypes marked auditable: true, and capture who/what/when for each operation. This is distinct from history() (the always-on structural revision history).

auditLog(id: string): Promise<AuditLogEntry[]>
auditLogByPath(path: string): Promise<AuditLogEntry[]>

interface AuditLogEntry {
id: string;
node_id: string;
path: string;
workspace: string;
user_id?: string; // who performed the action
action: string; // "Create" | "Update" | "Delete" | "Publish" | ...
timestamp: string; // ISO 8601
details?: string;
}

Both history() and auditLog() are authorized through row-level security — you can only read history/audit for nodes you can read.


Tree Operations

listChildren()

listChildren(parentPath: string): Promise<Node[]>

getChildren()

getChildren(parentId: string, limit?: number): Promise<Node[]>

getChildrenByPath()

getChildrenByPath(parentPath: string, limit?: number): Promise<Node[]>

getTree()

Returns a nested tree structure rooted at the given path.

getTree(rootPath: string, maxDepth?: number): Promise<Node>

getTreeFlat()

Returns a flat array of all nodes in the subtree.

getTreeFlat(rootPath: string, maxDepth?: number): Promise<Node[]>

move()

move(fromPath: string, toParentPath: string): Promise<Node>

rename()

rename(nodePath: string, newName: string): Promise<Node>

copy()

Shallow copy (node only, no children).

copy(fromPath: string, toParentPath: string, newName?: string): Promise<Node>

copyTree()

Deep copy (node and all descendants).

copyTree(fromPath: string, toParentPath: string, newName?: string): Promise<Node>

Ordering

Sibling nodes have an explicit order (see Child Ordering). Order is per-branch and is carried automatically when a branch is merged.

reorder()

Set the order key for a node.

reorder(nodePath: string, orderKey: string): Promise<Node>

moveChildBefore()

Move a child before a reference sibling.

moveChildBefore(
parentPath: string,
childPath: string,
referencePath: string
): Promise<Node>

moveChildAfter()

Move a child after a reference sibling.

moveChildAfter(
parentPath: string,
childPath: string,
referencePath: string
): Promise<Node>

applyChildOrder()

Replay a parent's child order from another branch onto the current branch.

applyChildOrder(parentPath: string, sourceBranch: string): Promise<void>

Reorders the parent's children on the current branch to match their order on sourceBranch. Only children that exist under the parent on both branches are moved.

Use this when promoting content by copying nodes between branches (e.g. a mainpublish publishing flow): copying a node carries its content but not its sibling order. A full branch merge already carries order, so it does not need this call.

// On the `publish` branch, match the child order of /menu from `main`
await db.onBranch('publish')
.workspace('content')
.nodes()
.applyChildOrder('/menu', 'main');

Relationships

addRelation()

addRelation(
nodePath: string,
relationType: string,
targetNodePath: string,
options?: { weight?: number; targetWorkspace?: string }
): Promise<boolean>

removeRelation()

removeRelation(nodePath: string, targetPath: string): Promise<boolean>

getRelationships()

getRelationships(nodePath: string): Promise<NodeRelationships>

Returns:

interface NodeRelationships {
outgoing: Relation[];
incoming: Relation[];
}