UNPKG

roam-research-mcp

Version:
101 lines (100 loc) • 4.51 kB
import { q } from '@roam-research/roam-api-sdk'; import { BaseSearchHandler } from './types.js'; import { SearchUtils } from './utils.js'; export class BlockRefSearchHandler extends BaseSearchHandler { constructor(graph, params) { super(graph); this.params = params; } async execute() { const { block_uid, title, page_title_uid } = this.params; // Get target page UID if provided let targetPageUid; if (page_title_uid) { targetPageUid = await SearchUtils.findPageByTitleOrUid(this.graph, page_title_uid); } // Build query based on whether we're searching for references to a specific block, // a page title, or all block references within a page/graph let queryStr; let queryParams; if (title) { // Search for references to a page by title using :block/refs if (targetPageUid) { queryStr = `[:find ?block-uid ?block-str :in $ ?target-title ?page-uid :where [?target :node/title ?target-title] [?p :block/uid ?page-uid] [?b :block/page ?p] [?b :block/refs ?target] [?b :block/string ?block-str] [?b :block/uid ?block-uid]]`; queryParams = [title, targetPageUid]; } else { queryStr = `[:find ?block-uid ?block-str ?page-title :in $ ?target-title :where [?target :node/title ?target-title] [?b :block/refs ?target] [?b :block/string ?block-str] [?b :block/uid ?block-uid] [?b :block/page ?p] [?p :node/title ?page-title]]`; queryParams = [title]; } } else if (block_uid) { // Search for references to a specific block if (targetPageUid) { queryStr = `[:find ?block-uid ?block-str :in $ ?ref-uid ?page-uid :where [?p :block/uid ?page-uid] [?b :block/page ?p] [?b :block/string ?block-str] [?b :block/uid ?block-uid] [(clojure.string/includes? ?block-str ?ref-uid)]]`; queryParams = [`((${block_uid}))`, targetPageUid]; } else { queryStr = `[:find ?block-uid ?block-str ?page-title :in $ ?ref-uid :where [?b :block/string ?block-str] [?b :block/uid ?block-uid] [?b :block/page ?p] [?p :node/title ?page-title] [(clojure.string/includes? ?block-str ?ref-uid)]]`; queryParams = [`((${block_uid}))`]; } } else { // Search for any block references if (targetPageUid) { queryStr = `[:find ?block-uid ?block-str :in $ ?page-uid :where [?p :block/uid ?page-uid] [?b :block/page ?p] [?b :block/string ?block-str] [?b :block/uid ?block-uid] [(re-find #"\\(\\([^)]+\\)\\)" ?block-str)]]`; queryParams = [targetPageUid]; } else { queryStr = `[:find ?block-uid ?block-str ?page-title :where [?b :block/string ?block-str] [?b :block/uid ?block-uid] [?b :block/page ?p] [?p :node/title ?page-title] [(re-find #"\\(\\([^)]+\\)\\)" ?block-str)]]`; queryParams = []; } } const rawResults = await q(this.graph, queryStr, queryParams); // Resolve block references in content const resolvedResults = await this.resolveBlockRefs(rawResults); const searchDescription = title ? `referencing [[${title}]]` : block_uid ? `referencing block ((${block_uid}))` : 'containing block references'; return SearchUtils.formatSearchResults(resolvedResults, searchDescription, !targetPageUid); } }