roam-research-mcp
Version:
MCP server and CLI for Roam Research
43 lines (42 loc) • 1.97 kB
JavaScript
import { q } from '@roam-research/roam-api-sdk';
const childrenQuery = `[:find ?parentUid ?childUid ?childString ?childOrder ?childHeading
:in $ [?parentUid ...]
:where [?parent :block/uid ?parentUid]
[?parent :block/children ?child]
[?child :block/uid ?childUid]
[?child :block/string ?childString]
[?child :block/order ?childOrder]
[(get-else $ ?child :block/heading 0) ?childHeading]]`;
/**
* Recursively fetch children for a set of parent UIDs up to maxDepth levels deep.
* Returns a map of parent UID → sorted array of child RoamBlocks (with their children attached).
*/
export async function fetchChildrenByDepth(graph, parentUids, maxDepth, currentDepth = 0) {
if (currentDepth >= maxDepth || parentUids.length === 0)
return {};
const results = await q(graph, childrenQuery, [parentUids]);
if (!results || results.length === 0)
return {};
const childrenByParent = {};
const allChildUids = [];
for (const [parentUid, childUid, childString, childOrder, childHeading] of results) {
if (!childrenByParent[parentUid])
childrenByParent[parentUid] = [];
childrenByParent[parentUid].push({
uid: childUid,
string: childString,
order: childOrder,
heading: childHeading || undefined,
children: [],
});
allChildUids.push(childUid);
}
const grandChildren = await fetchChildrenByDepth(graph, allChildUids, maxDepth, currentDepth + 1);
for (const parentUid in childrenByParent) {
for (const child of childrenByParent[parentUid]) {
child.children = grandChildren[child.uid] || [];
}
childrenByParent[parentUid].sort((a, b) => a.order - b.order);
}
return childrenByParent;
}