From 56a7455e144e2193b22953f7f20daadc2a3a9330 Mon Sep 17 00:00:00 2001 From: Michael Gartner Date: Sun, 23 Mar 2025 23:42:08 -0600 Subject: [PATCH 1/8] init --- package.json | 2 +- src/types/index.ts | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index f82cc7a..a495787 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "roamjs-components", "description": "Expansive toolset, utilities, & components for developing RoamJS extensions.", - "version": "0.85.0", + "version": "1.0.0-beta.1", "main": "index.js", "types": "index.d.ts", "scripts": { diff --git a/src/types/index.ts b/src/types/index.ts index 3301e5f..184ff56 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -85,7 +85,7 @@ declare global { pull: ( selector: string, id: number | string | [string, string] - ) => PullBlock; + ) => Promise; createBlock: WriteAction; updateBlock: WriteAction; createPage: WriteAction; @@ -102,6 +102,12 @@ declare global { }; data: { addPullWatch: AddPullWatch; + async: { + q: (query: string, ...params: unknown[]) => Promise; + }; + backend: { + q: (query: string, ...params: unknown[]) => Promise; + }; block: { create: WriteAction; update: WriteAction; @@ -119,7 +125,7 @@ declare global { pull: ( selector: string, id: number | string | [string, string] - ) => PullBlock; + ) => Promise; pull_many: (pattern: string, eid: string[][]) => PullBlock[]; q: (query: string, ...params: unknown[]) => unknown[][]; removePullWatch: ( From 144a4cecd1be5c45765008627af286e91d08b133 Mon Sep 17 00:00:00 2001 From: Michael Gartner Date: Sun, 23 Mar 2025 23:44:30 -0600 Subject: [PATCH 2/8] q to backend.q --- src/queries/getAllBlockUids.ts | 10 ++++---- src/queries/getAllBlockUidsAndTexts.ts | 12 ++++++---- src/queries/getAllPageNames.ts | 10 ++++---- .../getAttributeValueByBlockAndName.ts | 23 ++++++++----------- src/queries/getBasicTreeByParentUid.ts | 14 +++++------ .../getBlockUidAndTextIncludingText.ts | 14 +++++------ src/queries/getBlockUidByTextOnPage.ts | 10 ++++---- .../getBlockUidsAndTextsReferencingPage.ts | 18 +++++++-------- src/queries/getBlockUidsByPageTitle.ts | 16 ++++++------- src/queries/getBlockUidsReferencingBlock.ts | 12 +++++----- src/queries/getBlockUidsReferencingPage.ts | 18 ++++++++------- src/queries/getBlockUidsWithParentUid.ts | 14 +++++------ src/queries/getDisplayNameByEmail.ts | 8 ++++--- src/queries/getDisplayNameByUid.ts | 8 ++++--- src/queries/getEditedUserEmailByBlockUid.ts | 10 +++++--- src/queries/getFirstChildTextByBlockUid.ts | 12 ++++++---- src/queries/getLinkedPageTitlesUnderUid.ts | 12 +++++----- src/queries/getNthChildUidByBlockUid.ts | 14 +++++------ src/queries/getOrderByBlockUid.ts | 8 ++++--- src/queries/getPageTitleByBlockUid.ts | 12 +++++----- .../getPageTitleReferencesByPageTitle.ts | 18 ++++++++------- ...etPageTitlesAndBlockUidsReferencingPage.ts | 18 +++++++-------- ...ageTitlesAndUidsDirectlyReferencingPage.ts | 18 +++++++-------- .../getPageTitlesReferencingBlockUid.ts | 14 ++++++----- .../getPageTitlesStartingWithPrefix.ts | 14 ++++++----- src/queries/getPageUidByBlockUid.ts | 12 +++++----- src/queries/getPageViewType.ts | 8 ++++--- src/queries/getParentTextByBlockUid.ts | 8 ++++--- src/queries/getParentTextByBlockUidAndTag.ts | 10 ++++---- src/queries/getParentUidByBlockUid.ts | 12 +++++----- src/queries/getParentUidsOfBlockUid.ts | 12 +++++----- src/queries/getSettingsByEmail.ts | 8 ++++--- src/queries/getShallowTreeByParentUid.ts | 14 +++++------ src/queries/isTagOnPage.ts | 14 ++++++++--- 34 files changed, 238 insertions(+), 197 deletions(-) diff --git a/src/queries/getAllBlockUids.ts b/src/queries/getAllBlockUids.ts index 2786828..8eddfc7 100644 --- a/src/queries/getAllBlockUids.ts +++ b/src/queries/getAllBlockUids.ts @@ -1,6 +1,8 @@ -const getAllBlockUids = (): string[] => - window.roamAlphaAPI - .q(`[:find ?u :where [?e :block/uid ?u] [?e :block/string]]`) - .map((f) => f[0] as string); +const getAllBlockUids = async (): Promise => + ( + await window.roamAlphaAPI.data.backend.q( + `[:find ?u :where [?e :block/uid ?u] [?e :block/string]]` + ) + ).map((f) => f[0] as string); export default getAllBlockUids; diff --git a/src/queries/getAllBlockUidsAndTexts.ts b/src/queries/getAllBlockUidsAndTexts.ts index d0738a1..3af31bd 100644 --- a/src/queries/getAllBlockUidsAndTexts.ts +++ b/src/queries/getAllBlockUidsAndTexts.ts @@ -1,6 +1,10 @@ -const getAllBlockUidsAndTexts = (): { uid: string; text: string }[] => - window.roamAlphaAPI - .q(`[:find ?u ?s :where [?e :block/uid ?u] [?e :block/string ?s]]`) - .map((f) => ({ uid: f[0] as string, text: f[1] as string })); +const getAllBlockUidsAndTexts = async (): Promise< + { uid: string; text: string }[] +> => + ( + await window.roamAlphaAPI.data.backend.q( + `[:find ?u ?s :where [?e :block/uid ?u] [?e :block/string ?s]]` + ) + ).map((f) => ({ uid: f[0] as string, text: f[1] as string })); export default getAllBlockUidsAndTexts; diff --git a/src/queries/getAllPageNames.ts b/src/queries/getAllPageNames.ts index 6443668..c3d6667 100644 --- a/src/queries/getAllPageNames.ts +++ b/src/queries/getAllPageNames.ts @@ -1,6 +1,8 @@ -const getAllPageNames = (): string[] => - window.roamAlphaAPI - .q("[:find ?s :where [?e :node/title ?s]]") - .map((b) => b[0] as string); +const getAllPageNames = async (): Promise => { + const result = await window.roamAlphaAPI.data.backend.q( + "[:find ?s :where [?e :node/title ?s]]" + ); + return result.map((b) => b[0] as string); +}; export default getAllPageNames; diff --git a/src/queries/getAttributeValueByBlockAndName.ts b/src/queries/getAttributeValueByBlockAndName.ts index e537635..bc1544c 100644 --- a/src/queries/getAttributeValueByBlockAndName.ts +++ b/src/queries/getAttributeValueByBlockAndName.ts @@ -1,23 +1,20 @@ import { PullBlock } from "../types"; import normalizePageTitle from "./normalizePageTitle"; -const getAttributeValueByBlockAndName = ({ +const getAttributeValueByBlockAndName = async ({ name, uid, }: { name: string; uid: string; -}) => - ( - ( - window.roamAlphaAPI.data.fast.q( - `[:find (pull ?b [:block/string]) :where [?a :node/title "${normalizePageTitle( - name - )}"] [?p :block/uid "${uid}"] [?b :block/refs ?a] [?b :block/parents ?p]]` - )?.[0]?.[0] as PullBlock - )?.[":block/string"] || "" - ) - .slice(name.length + 2) - .trim(); +}): Promise => { + const result = await window.roamAlphaAPI.data.backend.q( + `[:find (pull ?b [:block/string]) :where [?a :node/title "${normalizePageTitle( + name + )}"] [?p :block/uid "${uid}"] [?b :block/refs ?a] [?b :block/parents ?p]]` + ); + const blockString = (result?.[0]?.[0] as PullBlock)?.[":block/string"] || ""; + return blockString.slice(name.length + 2).trim(); +}; export default getAttributeValueByBlockAndName; diff --git a/src/queries/getBasicTreeByParentUid.ts b/src/queries/getBasicTreeByParentUid.ts index 7eed044..4cfacd6 100644 --- a/src/queries/getBasicTreeByParentUid.ts +++ b/src/queries/getBasicTreeByParentUid.ts @@ -9,13 +9,13 @@ const sortBasicNodes = (c: PullBlock[]): RoamBasicNode[] => text: node[":block/string"] || "", })); -const getBasicTreeByParentUid = (uid: string): RoamBasicNode[] => - sortBasicNodes( - window.roamAlphaAPI.data.fast - .q( - `[:find (pull ?c [:block/string :block/uid :block/order {:block/children ...}]) :where [?b :block/uid "${uid}"] [?b :block/children ?c]]` - ) - .map((a) => a[0] as PullBlock) +const getBasicTreeByParentUid = async ( + uid: string +): Promise => { + const result = await window.roamAlphaAPI.data.backend.q( + `[:find (pull ?c [:block/string :block/uid :block/order {:block/children ...}]) :where [?b :block/uid "${uid}"] [?b :block/children ?c]]` ); + return sortBasicNodes(result.map((a) => a[0] as PullBlock)); +}; export default getBasicTreeByParentUid; diff --git a/src/queries/getBlockUidAndTextIncludingText.ts b/src/queries/getBlockUidAndTextIncludingText.ts index a919edf..905669d 100644 --- a/src/queries/getBlockUidAndTextIncludingText.ts +++ b/src/queries/getBlockUidAndTextIncludingText.ts @@ -1,15 +1,15 @@ import { PullBlock } from "../types"; -const getBlockUidAndTextIncludingText = ( +const getBlockUidAndTextIncludingText = async ( t: string -): { uid: string; text: string }[] => - ( - window.roamAlphaAPI.data.fast.q( - `[:find (pull ?block [:block/uid :block/string]) :where [?block :block/string ?contents] [(clojure.string/includes? ?contents "${t}")]]` - ) as [PullBlock][] - ).map(([block]) => ({ +): Promise<{ uid: string; text: string }[]> => { + const result = (await window.roamAlphaAPI.data.backend.q( + `[:find (pull ?block [:block/uid :block/string]) :where [?block :block/string ?contents] [(clojure.string/includes? ?contents "${t}")]]` + )) as [PullBlock][]; + return result.map(([block]) => ({ uid: block[":block/uid"] || "", text: block[":block/string"] || "", })); +}; export default getBlockUidAndTextIncludingText; diff --git a/src/queries/getBlockUidByTextOnPage.ts b/src/queries/getBlockUidByTextOnPage.ts index 0bc27ab..3b907a0 100644 --- a/src/queries/getBlockUidByTextOnPage.ts +++ b/src/queries/getBlockUidByTextOnPage.ts @@ -1,12 +1,14 @@ -const getBlockUidByTextOnPage = ({ +const getBlockUidByTextOnPage = async ({ text, title, }: { text: string; title: string; -}): string => - (window.roamAlphaAPI.q( +}): Promise => { + const result = await window.roamAlphaAPI.data.backend.q( `[:find ?u :where [?b :block/page ?p] [?b :block/uid ?u] [?b :block/string "${text}"] [?p :node/title "${title}"]]` - )?.[0]?.[0] as string) || ""; + ); + return (result?.[0]?.[0] as string) || ""; +}; export default getBlockUidByTextOnPage; diff --git a/src/queries/getBlockUidsAndTextsReferencingPage.ts b/src/queries/getBlockUidsAndTextsReferencingPage.ts index de92079..e0d89d0 100644 --- a/src/queries/getBlockUidsAndTextsReferencingPage.ts +++ b/src/queries/getBlockUidsAndTextsReferencingPage.ts @@ -1,18 +1,18 @@ import { PullBlock } from "../types"; import normalizePageTitle from "./normalizePageTitle"; -const getBlockUidsAndTextsReferencingPage = ( +const getBlockUidsAndTextsReferencingPage = async ( title: string -): { uid: string; text: string }[] => - ( - window.roamAlphaAPI.data.fast.q( - `[:find (pull ?r [:block/uid :block/string]) :where [?p :node/title "${normalizePageTitle( - title - )}"] [?r :block/refs ?p]]` - ) as [PullBlock][] - ).map(([node]) => ({ +): Promise<{ uid: string; text: string }[]> => { + const result = (await window.roamAlphaAPI.data.backend.q( + `[:find (pull ?r [:block/uid :block/string]) :where [?p :node/title "${normalizePageTitle( + title + )}"] [?r :block/refs ?p]]` + )) as [PullBlock][]; + return result.map(([node]) => ({ uid: node[":block/uid"] || "", text: node[":block/string"] || "", })); +}; export default getBlockUidsAndTextsReferencingPage; diff --git a/src/queries/getBlockUidsByPageTitle.ts b/src/queries/getBlockUidsByPageTitle.ts index dec2122..747fd93 100644 --- a/src/queries/getBlockUidsByPageTitle.ts +++ b/src/queries/getBlockUidsByPageTitle.ts @@ -1,12 +1,12 @@ import normalizePageTitle from "./normalizePageTitle"; -const getBlockUidsByPageTitle = (title: string): string[] => - window.roamAlphaAPI - .q( - `[:find ?u :where [?b :block/uid ?u] [?b :block/page ?e] [?e :node/title "${normalizePageTitle( - title - )}"]]` - ) - .map((b) => b[0] as string); +const getBlockUidsByPageTitle = async (title: string): Promise => { + const result = await window.roamAlphaAPI.data.backend.q( + `[:find ?u :where [?b :block/uid ?u] [?b :block/page ?e] [?e :node/title "${normalizePageTitle( + title + )}"]]` + ); + return result.map((b) => b[0] as string); +}; export default getBlockUidsByPageTitle; diff --git a/src/queries/getBlockUidsReferencingBlock.ts b/src/queries/getBlockUidsReferencingBlock.ts index a5499a0..e8644b1 100644 --- a/src/queries/getBlockUidsReferencingBlock.ts +++ b/src/queries/getBlockUidsReferencingBlock.ts @@ -1,10 +1,10 @@ import { PullBlock } from "../types"; -const getBlockUidsReferencingBlock = (uid: string): string[] => - ( - window.roamAlphaAPI.data.fast.q( - `[:find (pull ?r [:block/uid]) :where [?b :block/uid "${uid}"] [?r :block/refs ?b]]` - ) as [PullBlock][] - ).map((s) => s[0][":block/uid"] || ""); +const getBlockUidsReferencingBlock = async (uid: string): Promise => { + const result = (await window.roamAlphaAPI.data.backend.q( + `[:find (pull ?r [:block/uid]) :where [?b :block/uid "${uid}"] [?r :block/refs ?b]]` + )) as [PullBlock][]; + return result.map((s) => s[0][":block/uid"] || ""); +}; export default getBlockUidsReferencingBlock; diff --git a/src/queries/getBlockUidsReferencingPage.ts b/src/queries/getBlockUidsReferencingPage.ts index 6ab108c..b239a44 100644 --- a/src/queries/getBlockUidsReferencingPage.ts +++ b/src/queries/getBlockUidsReferencingPage.ts @@ -1,13 +1,15 @@ import { PullBlock } from "../types"; import normalizePageTitle from "./normalizePageTitle"; -const getBlockUidsReferencingPage = (title: string): string[] => - ( - window.roamAlphaAPI.data.fast.q( - `[:find (pull ?r [:block/uid]) :where [?p :node/title "${normalizePageTitle( - title - )}"] [?r :block/refs ?p]]` - ) as [PullBlock][] - ).map((s) => s[0][":block/uid"] || ""); +const getBlockUidsReferencingPage = async ( + title: string +): Promise => { + const result = (await window.roamAlphaAPI.data.backend.q( + `[:find (pull ?r [:block/uid]) :where [?p :node/title "${normalizePageTitle( + title + )}"] [?r :block/refs ?p]]` + )) as [PullBlock][]; + return result.map((s) => s[0][":block/uid"] || ""); +}; export default getBlockUidsReferencingPage; diff --git a/src/queries/getBlockUidsWithParentUid.ts b/src/queries/getBlockUidsWithParentUid.ts index a69dd67..3414ac7 100644 --- a/src/queries/getBlockUidsWithParentUid.ts +++ b/src/queries/getBlockUidsWithParentUid.ts @@ -1,10 +1,8 @@ - - -const getBlockUidsWithParentUid = (uid: string): string[] => - window.roamAlphaAPI - .q( - `[:find ?u :where [?c :block/uid ?u] [?c :block/parents ?b] [?b :block/uid "${uid}"]]` - ) - .map((r) => r[0] as string); +const getBlockUidsWithParentUid = async (uid: string): Promise => { + const result = await window.roamAlphaAPI.data.backend.q( + `[:find ?u :where [?c :block/uid ?u] [?c :block/parents ?b] [?b :block/uid "${uid}"]]` + ); + return result.map((r) => r[0] as string); +}; export default getBlockUidsWithParentUid; diff --git a/src/queries/getDisplayNameByEmail.ts b/src/queries/getDisplayNameByEmail.ts index 17058d1..7989d46 100644 --- a/src/queries/getDisplayNameByEmail.ts +++ b/src/queries/getDisplayNameByEmail.ts @@ -1,6 +1,8 @@ -const getDisplayNameByEmail = (email: string): string => - (window.roamAlphaAPI.q( +const getDisplayNameByEmail = async (email: string): Promise => { + const result = await window.roamAlphaAPI.data.backend.q( `[:find ?name :where[?e :user/display-name ?name] [?e :user/email "${email}"]]` - )?.[0]?.[0] as string) || ""; + ); + return (result?.[0]?.[0] as string) || ""; +}; export default getDisplayNameByEmail; diff --git a/src/queries/getDisplayNameByUid.ts b/src/queries/getDisplayNameByUid.ts index 3547bf6..bcc1c9c 100644 --- a/src/queries/getDisplayNameByUid.ts +++ b/src/queries/getDisplayNameByUid.ts @@ -1,6 +1,8 @@ -const getDisplayNameByUid = (uid: string): string => - (window.roamAlphaAPI.q( +const getDisplayNameByUid = async (uid: string): Promise => { + const result = await window.roamAlphaAPI.data.backend.q( `[:find ?s :where [?e :user/uid "${uid}"] [?e :user/display-page ?p] [?p :node/title ?s]]` - )?.[0]?.[0] as string) || ""; + ); + return (result?.[0]?.[0] as string) || ""; +}; export default getDisplayNameByUid; diff --git a/src/queries/getEditedUserEmailByBlockUid.ts b/src/queries/getEditedUserEmailByBlockUid.ts index e7d198d..20294cf 100644 --- a/src/queries/getEditedUserEmailByBlockUid.ts +++ b/src/queries/getEditedUserEmailByBlockUid.ts @@ -1,6 +1,10 @@ -const getEditedUserEmailByBlockUid = (blockUid: string): string => - (window.roamAlphaAPI.q( +const getEditedUserEmailByBlockUid = async ( + blockUid: string +): Promise => { + const result = await window.roamAlphaAPI.data.backend.q( `[:find ?e :where [?u :user/email ?e] [?b :edit/user ?u] [?b :block/uid "${blockUid}"]]` - )?.[0]?.[0] as string) || ""; + ); + return (result?.[0]?.[0] as string) || ""; +}; export default getEditedUserEmailByBlockUid; diff --git a/src/queries/getFirstChildTextByBlockUid.ts b/src/queries/getFirstChildTextByBlockUid.ts index 49ae85b..e0c73b2 100644 --- a/src/queries/getFirstChildTextByBlockUid.ts +++ b/src/queries/getFirstChildTextByBlockUid.ts @@ -1,8 +1,10 @@ - - -const getFirstChildTextByBlockUid = (blockUid: string): string => - window.roamAlphaAPI.q( +const getFirstChildTextByBlockUid = async ( + blockUid: string +): Promise => { + const result = await window.roamAlphaAPI.data.backend.q( `[:find ?s :where [?c :block/string ?s] [?c :block/order 0] [?p :block/children ?c] [?p :block/uid "${blockUid}"]]` - )?.[0]?.[0] as string; + ); + return result?.[0]?.[0] as string; +}; export default getFirstChildTextByBlockUid; diff --git a/src/queries/getLinkedPageTitlesUnderUid.ts b/src/queries/getLinkedPageTitlesUnderUid.ts index 5be3d25..12af904 100644 --- a/src/queries/getLinkedPageTitlesUnderUid.ts +++ b/src/queries/getLinkedPageTitlesUnderUid.ts @@ -1,8 +1,8 @@ -const getLinkedPageTitlesUnderUid = (uid: string): string[] => - window.roamAlphaAPI - .q( - `[:find ?t :where [?r :node/title ?t] [?c :block/refs ?r] [?c :block/parents ?b] [?b :block/uid "${uid}"]]` - ) - .map((r) => r[0] as string); +const getLinkedPageTitlesUnderUid = async (uid: string): Promise => { + const result = await window.roamAlphaAPI.data.backend.q( + `[:find ?t :where [?r :node/title ?t] [?c :block/refs ?r] [?c :block/parents ?b] [?b :block/uid "${uid}"]]` + ); + return result.map((r) => r[0] as string); +}; export default getLinkedPageTitlesUnderUid; diff --git a/src/queries/getNthChildUidByBlockUid.ts b/src/queries/getNthChildUidByBlockUid.ts index 726d914..b05bc5a 100644 --- a/src/queries/getNthChildUidByBlockUid.ts +++ b/src/queries/getNthChildUidByBlockUid.ts @@ -1,16 +1,16 @@ import type { PullBlock } from "../types/native"; -const getNthChildUidByBlockUid = ({ +const getNthChildUidByBlockUid = async ({ blockUid, order, }: { blockUid: string; order: number; -}): string => - ( - window.roamAlphaAPI.data.fast.q( - `[:find (pull ?c [:block/uid]) :where [?p :block/uid "${blockUid}"] [?p :block/children ?c] [?c :block/order ${order}] ]` - )?.[0]?.[0] as PullBlock - )?.[":block/uid"] || ""; +}): Promise => { + const result = await window.roamAlphaAPI.data.backend.q( + `[:find (pull ?c [:block/uid]) :where [?p :block/uid "${blockUid}"] [?p :block/children ?c] [?c :block/order ${order}] ]` + ); + return (result?.[0]?.[0] as PullBlock)?.[":block/uid"] || ""; +}; export default getNthChildUidByBlockUid; diff --git a/src/queries/getOrderByBlockUid.ts b/src/queries/getOrderByBlockUid.ts index b186e92..f01db40 100644 --- a/src/queries/getOrderByBlockUid.ts +++ b/src/queries/getOrderByBlockUid.ts @@ -1,6 +1,8 @@ -const getOrderByBlockUid = (blockUid: string): number => - window.roamAlphaAPI.q( +const getOrderByBlockUid = async (blockUid: string): Promise => { + const result = await window.roamAlphaAPI.data.backend.q( `[:find ?o :where [?r :block/order ?o] [?r :block/uid "${blockUid}"]]` - )?.[0]?.[0] as number; + ); + return result?.[0]?.[0] as number; +}; export default getOrderByBlockUid; diff --git a/src/queries/getPageTitleByBlockUid.ts b/src/queries/getPageTitleByBlockUid.ts index ccb0b60..a70aee3 100644 --- a/src/queries/getPageTitleByBlockUid.ts +++ b/src/queries/getPageTitleByBlockUid.ts @@ -1,8 +1,8 @@ -const getPageTitleByBlockUid = (blockUid: string): string => - ( - window.roamAlphaAPI.q( - `[:find (pull ?p [:node/title]) :where [?e :block/uid "${blockUid}"] [?e :block/page ?p]]` - )?.[0]?.[0] as { title?: string } - )?.title || ""; +const getPageTitleByBlockUid = async (blockUid: string): Promise => { + const result = await window.roamAlphaAPI.data.backend.q( + `[:find (pull ?p [:node/title]) :where [?e :block/uid "${blockUid}"] [?e :block/page ?p]]` + ); + return (result?.[0]?.[0] as { title?: string })?.title || ""; +}; export default getPageTitleByBlockUid; diff --git a/src/queries/getPageTitleReferencesByPageTitle.ts b/src/queries/getPageTitleReferencesByPageTitle.ts index 5023e3c..54edf01 100644 --- a/src/queries/getPageTitleReferencesByPageTitle.ts +++ b/src/queries/getPageTitleReferencesByPageTitle.ts @@ -1,13 +1,15 @@ import { PullBlock } from "../types"; import normalizePageTitle from "./normalizePageTitle"; -const getPageTitleReferencesByPageTitle = (title: string): string[] => - ( - window.roamAlphaAPI.data.fast.q( - `[:find (pull ?b [:node/title]) :where [?r :node/title "${normalizePageTitle( - title - )}"] [?c :block/refs ?r] [?c :block/page ?b]]` - ) as [PullBlock][] - ).map((p) => p[0][":node/title"] as string); +const getPageTitleReferencesByPageTitle = async ( + title: string +): Promise => { + const result = (await window.roamAlphaAPI.data.backend.q( + `[:find (pull ?b [:node/title]) :where [?r :node/title "${normalizePageTitle( + title + )}"] [?c :block/refs ?r] [?c :block/page ?b]]` + )) as [PullBlock][]; + return result.map((p) => p[0][":node/title"] as string); +}; export default getPageTitleReferencesByPageTitle; diff --git a/src/queries/getPageTitlesAndBlockUidsReferencingPage.ts b/src/queries/getPageTitlesAndBlockUidsReferencingPage.ts index 215924a..f637f6a 100644 --- a/src/queries/getPageTitlesAndBlockUidsReferencingPage.ts +++ b/src/queries/getPageTitlesAndBlockUidsReferencingPage.ts @@ -1,18 +1,18 @@ import { PullBlock } from "../types"; import normalizePageTitle from "./normalizePageTitle"; -const getPageTitlesAndBlockUidsReferencingPage = ( +const getPageTitlesAndBlockUidsReferencingPage = async ( pageName: string -): { title: string; uid: string }[] => - ( - window.roamAlphaAPI.data.fast.q( - `[:find (pull ?pr [:node/title]) (pull ?r [:block/uid]) :where [?p :node/title "${normalizePageTitle( - pageName - )}"] [?r :block/refs ?p] [?r :block/page ?pr]]` - ) as [PullBlock, PullBlock][] - ).map(([pr, r]) => ({ +): Promise<{ title: string; uid: string }[]> => { + const result = (await window.roamAlphaAPI.data.backend.q( + `[:find (pull ?pr [:node/title]) (pull ?r [:block/uid]) :where [?p :node/title "${normalizePageTitle( + pageName + )}"] [?r :block/refs ?p] [?r :block/page ?pr]]` + )) as [PullBlock, PullBlock][]; + return result.map(([pr, r]) => ({ title: pr?.[":node/title"] || "", uid: r?.[":block/uid"] || "", })); +}; export default getPageTitlesAndBlockUidsReferencingPage; diff --git a/src/queries/getPageTitlesAndUidsDirectlyReferencingPage.ts b/src/queries/getPageTitlesAndUidsDirectlyReferencingPage.ts index 7733663..aa110f5 100644 --- a/src/queries/getPageTitlesAndUidsDirectlyReferencingPage.ts +++ b/src/queries/getPageTitlesAndUidsDirectlyReferencingPage.ts @@ -1,18 +1,18 @@ import { PullBlock } from "../types"; import normalizePageTitle from "./normalizePageTitle"; -const getPageTitlesAndUidsDirectlyReferencingPage = ( +const getPageTitlesAndUidsDirectlyReferencingPage = async ( pageName: string -): { title: string; uid: string }[] => - ( - window.roamAlphaAPI.data.fast.q( - `[:find (pull ?r [:node/title :block/uid]) :where [?p :node/title "${normalizePageTitle( - pageName - )}"] [?r :block/refs ?p]]` - ) as [PullBlock][] - ).map(([block]) => ({ +): Promise<{ title: string; uid: string }[]> => { + const result = (await window.roamAlphaAPI.data.backend.q( + `[:find (pull ?r [:node/title :block/uid]) :where [?p :node/title "${normalizePageTitle( + pageName + )}"] [?r :block/refs ?p]]` + )) as [PullBlock][]; + return result.map(([block]) => ({ title: block[":node/title"] || "", uid: block[":block/uid"] || "", })); +}; export default getPageTitlesAndUidsDirectlyReferencingPage; diff --git a/src/queries/getPageTitlesReferencingBlockUid.ts b/src/queries/getPageTitlesReferencingBlockUid.ts index 1a746b3..56eae45 100644 --- a/src/queries/getPageTitlesReferencingBlockUid.ts +++ b/src/queries/getPageTitlesReferencingBlockUid.ts @@ -1,10 +1,12 @@ import { PullBlock } from "../types"; -const getPageTitlesReferencingBlockUid = (uid: string): string[] => - ( - window.roamAlphaAPI.data.fast.q( - `[:find (pull ?p [:node/title]) :where [?r :block/uid "${uid}"] [?b :block/refs ?r] [?b :block/page ?p]]` - ) as [PullBlock][] - ).map((s) => s[0]?.[":node/title"] || ""); +const getPageTitlesReferencingBlockUid = async ( + uid: string +): Promise => { + const result = (await window.roamAlphaAPI.data.backend.q( + `[:find (pull ?p [:node/title]) :where [?r :block/uid "${uid}"] [?b :block/refs ?r] [?b :block/page ?p]]` + )) as [PullBlock][]; + return result.map((s) => s[0]?.[":node/title"] || ""); +}; export default getPageTitlesReferencingBlockUid; diff --git a/src/queries/getPageTitlesStartingWithPrefix.ts b/src/queries/getPageTitlesStartingWithPrefix.ts index d2e2449..952c313 100644 --- a/src/queries/getPageTitlesStartingWithPrefix.ts +++ b/src/queries/getPageTitlesStartingWithPrefix.ts @@ -1,8 +1,10 @@ -const getPageTitlesStartingWithPrefix = (prefix: string): string[] => - window.roamAlphaAPI - .q( - `[:find ?title :where [?b :node/title ?title] [(clojure.string/starts-with? ?title "${prefix}")]]` - ) - .map((r) => r[0] as string); +const getPageTitlesStartingWithPrefix = async ( + prefix: string +): Promise => { + const result = await window.roamAlphaAPI.data.backend.q( + `[:find ?title :where [?b :node/title ?title] [(clojure.string/starts-with? ?title "${prefix}")]]` + ); + return result.map((r) => r[0] as string); +}; export default getPageTitlesStartingWithPrefix; diff --git a/src/queries/getPageUidByBlockUid.ts b/src/queries/getPageUidByBlockUid.ts index 829170b..d50c3d4 100644 --- a/src/queries/getPageUidByBlockUid.ts +++ b/src/queries/getPageUidByBlockUid.ts @@ -1,8 +1,8 @@ -const getPageUidByBlockUid = (blockUid: string): string => - ( - window.roamAlphaAPI.q( - `[:find (pull ?p [:block/uid]) :where [?e :block/uid "${blockUid}"] [?e :block/page ?p]]` - )?.[0]?.[0] as { uid?: string } - )?.uid || ""; +const getPageUidByBlockUid = async (blockUid: string): Promise => { + const result = await window.roamAlphaAPI.data.backend.q( + `[:find (pull ?p [:block/uid]) :where [?e :block/uid "${blockUid}"] [?e :block/page ?p]]` + ); + return (result?.[0]?.[0] as { uid?: string })?.uid || ""; +}; export default getPageUidByBlockUid; diff --git a/src/queries/getPageViewType.ts b/src/queries/getPageViewType.ts index a32093b..822d421 100644 --- a/src/queries/getPageViewType.ts +++ b/src/queries/getPageViewType.ts @@ -1,11 +1,13 @@ import normalizePageTitle from "./normalizePageTitle"; import type { ViewType } from "../types"; -const getPageViewType = (title: string): ViewType => - (window.roamAlphaAPI.q( +const getPageViewType = async (title: string): Promise => { + const result = await window.roamAlphaAPI.data.backend.q( `[:find ?v :where [?e :children/view-type ?v] [?e :node/title "${normalizePageTitle( title )}"]]` - )?.[0]?.[0] as ViewType) || "bullet"; + ); + return (result?.[0]?.[0] as ViewType) || "bullet"; +}; export default getPageViewType; diff --git a/src/queries/getParentTextByBlockUid.ts b/src/queries/getParentTextByBlockUid.ts index 2d208d2..cd9d726 100644 --- a/src/queries/getParentTextByBlockUid.ts +++ b/src/queries/getParentTextByBlockUid.ts @@ -1,6 +1,8 @@ -const getParentTextByBlockUid = (blockUid: string): string => - (window.roamAlphaAPI.q( +const getParentTextByBlockUid = async (blockUid: string): Promise => { + const result = await window.roamAlphaAPI.data.backend.q( `[:find ?s :where [?e :block/uid "${blockUid}"] [?p :block/children ?e] [?p :block/string ?s]]` - )?.[0]?.[0] as string) || ""; + ); + return (result?.[0]?.[0] as string) || ""; +}; export default getParentTextByBlockUid; diff --git a/src/queries/getParentTextByBlockUidAndTag.ts b/src/queries/getParentTextByBlockUidAndTag.ts index e07cbac..bafc9bf 100644 --- a/src/queries/getParentTextByBlockUidAndTag.ts +++ b/src/queries/getParentTextByBlockUidAndTag.ts @@ -1,12 +1,14 @@ -const getParentTextByBlockUidAndTag = ({ +const getParentTextByBlockUidAndTag = async ({ blockUid, tag, }: { blockUid: string; tag: string; -}): string => - (window.roamAlphaAPI.q( +}): Promise => { + const result = await window.roamAlphaAPI.data.backend.q( `[:find ?s :where [?t :node/title "${tag}"] [?p :block/refs ?t] [?p :block/string ?s] [?b :block/parents ?p] [?b :block/uid "${blockUid}"]]` - )?.[0]?.[0] as string) || ""; + ); + return (result?.[0]?.[0] as string) || ""; +}; export default getParentTextByBlockUidAndTag; diff --git a/src/queries/getParentUidByBlockUid.ts b/src/queries/getParentUidByBlockUid.ts index 997f3a7..69e70c9 100644 --- a/src/queries/getParentUidByBlockUid.ts +++ b/src/queries/getParentUidByBlockUid.ts @@ -1,10 +1,10 @@ import type { PullBlock } from "../types/native"; -const getParentUidByBlockUid = (blockUid: string): string => - ( - window.roamAlphaAPI.data.fast.q( - `[:find (pull ?p [:block/uid]) :where [?e :block/uid "${blockUid}"] [?p :block/children ?e]]` - )?.[0]?.[0] as PullBlock - )?.[":block/uid"] || ""; +const getParentUidByBlockUid = async (blockUid: string): Promise => { + const result = await window.roamAlphaAPI.data.backend.q( + `[:find (pull ?p [:block/uid]) :where [?e :block/uid "${blockUid}"] [?p :block/children ?e]]` + ); + return (result?.[0]?.[0] as PullBlock)?.[":block/uid"] || ""; +}; export default getParentUidByBlockUid; diff --git a/src/queries/getParentUidsOfBlockUid.ts b/src/queries/getParentUidsOfBlockUid.ts index 951f782..73845c6 100644 --- a/src/queries/getParentUidsOfBlockUid.ts +++ b/src/queries/getParentUidsOfBlockUid.ts @@ -1,10 +1,10 @@ import type { PullBlock } from "../types"; -const getParentUidsOfBlockUid = (uid: string): string[] => - ( - window.roamAlphaAPI.data.fast.q( - `[:find (pull ?p [:block/uid]) :where [?b :block/uid "${uid}"] [?b :block/parents ?p] ]` - ) as [PullBlock][] - ).map((r) => r[0][":block/uid"] || ""); +const getParentUidsOfBlockUid = async (uid: string): Promise => { + const result = (await window.roamAlphaAPI.data.backend.q( + `[:find (pull ?p [:block/uid]) :where [?b :block/uid "${uid}"] [?b :block/parents ?p] ]` + )) as [PullBlock][]; + return result.map((r) => r[0][":block/uid"] || ""); +}; export default getParentUidsOfBlockUid; diff --git a/src/queries/getSettingsByEmail.ts b/src/queries/getSettingsByEmail.ts index f88d5fe..3e7f0bf 100644 --- a/src/queries/getSettingsByEmail.ts +++ b/src/queries/getSettingsByEmail.ts @@ -1,8 +1,10 @@ import type { UserSettings } from "../types"; -const getSettingsByEmail = (email: string): UserSettings => - (window.roamAlphaAPI.q( +const getSettingsByEmail = async (email: string): Promise => { + const result = await window.roamAlphaAPI.data.backend.q( `[:find ?settings :where[?e :user/settings ?settings] [?e :user/email "${email}"]]` - )?.[0]?.[0] as UserSettings) || {}; + ); + return (result?.[0]?.[0] as UserSettings) || {}; +}; export default getSettingsByEmail; diff --git a/src/queries/getShallowTreeByParentUid.ts b/src/queries/getShallowTreeByParentUid.ts index 4be10a9..ca40625 100644 --- a/src/queries/getShallowTreeByParentUid.ts +++ b/src/queries/getShallowTreeByParentUid.ts @@ -1,17 +1,17 @@ import { PullBlock } from "../types"; -const getShallowTreeByParentUid = ( +const getShallowTreeByParentUid = async ( parentUid: string -): { uid: string; text: string }[] => - ( - window.roamAlphaAPI.data.fast.q( - `[:find (pull ?c [:block/uid :block/string :block/order]) :where [?b :block/uid "${parentUid}"] [?b :block/children ?c]]` - ) as [PullBlock][] - ) +): Promise<{ uid: string; text: string }[]> => { + const result = (await window.roamAlphaAPI.data.backend.q( + `[:find (pull ?c [:block/uid :block/string :block/order]) :where [?b :block/uid "${parentUid}"] [?b :block/children ?c]]` + )) as [PullBlock][]; + return result .sort((a, b) => (a[0][":block/order"] || 0) - (b[0][":block/order"] || 0)) .map(([a]) => ({ uid: a[":block/uid"] || "", text: a[":block/string"] || "", })); +}; export default getShallowTreeByParentUid; diff --git a/src/queries/isTagOnPage.ts b/src/queries/isTagOnPage.ts index 5906050..0f36e59 100644 --- a/src/queries/isTagOnPage.ts +++ b/src/queries/isTagOnPage.ts @@ -1,12 +1,20 @@ import normalizePageTitle from "./normalizePageTitle"; -const isTagOnPage = ({ tag, title }: { tag: string; title: string }): boolean => - !!window.roamAlphaAPI.q( +const isTagOnPage = async ({ + tag, + title, +}: { + tag: string; + title: string; +}): Promise => { + const result = await window.roamAlphaAPI.data.backend.q( `[:find ?r :where [?r :node/title "${normalizePageTitle( tag )}"] [?b :block/refs ?r] [?b :block/page ?p] [?p :node/title "${normalizePageTitle( title )}"]]` - )?.[0]?.[0]; + ); + return !!result?.[0]?.[0]; +}; export default isTagOnPage; From 0691366097eeaa82b19d527acf85a0592a3e402e Mon Sep 17 00:00:00 2001 From: Michael Gartner Date: Sun, 23 Mar 2025 23:44:38 -0600 Subject: [PATCH 3/8] async pull --- src/queries/getChildrenLengthByPageUid.ts | 11 +++++++---- src/queries/getChildrenLengthByParentUid.ts | 11 +++++++---- src/queries/getCreateTimeByBlockUid.ts | 11 +++++++---- src/queries/getEditTimeByBlockUid.ts | 11 +++++++---- src/queries/getFullTreeByParentUid.ts | 12 ++++++------ src/queries/getPageTitleByPageUid.ts | 16 +++++++++------- src/queries/getPageUidByPageTitle.ts | 4 ++-- src/queries/getTextByBlockUid.ts | 14 ++++++++------ src/queries/isLiveBlock.ts | 9 +++++++-- 9 files changed, 60 insertions(+), 39 deletions(-) diff --git a/src/queries/getChildrenLengthByPageUid.ts b/src/queries/getChildrenLengthByPageUid.ts index 584a8f8..cf0f38e 100644 --- a/src/queries/getChildrenLengthByPageUid.ts +++ b/src/queries/getChildrenLengthByPageUid.ts @@ -1,7 +1,10 @@ // @deprecated - use getChildrenLengthByParentUid instead -const getChildrenLengthByPageUid = (uid: string): number => - window.roamAlphaAPI.pull("[:block/children]", [":block/uid", uid])?.[ - ":block/children" - ]?.length || 0; +const getChildrenLengthByPageUid = async (uid: string): Promise => { + const result = await window.roamAlphaAPI.data.pull("[:block/children]", [ + ":block/uid", + uid, + ]); + return result?.[":block/children"]?.length || 0; +}; export default getChildrenLengthByPageUid; diff --git a/src/queries/getChildrenLengthByParentUid.ts b/src/queries/getChildrenLengthByParentUid.ts index de61be5..a837745 100644 --- a/src/queries/getChildrenLengthByParentUid.ts +++ b/src/queries/getChildrenLengthByParentUid.ts @@ -1,6 +1,9 @@ -const getChildrenLengthByPageUid = (uid: string): number => - window.roamAlphaAPI.pull("[:block/children]", [":block/uid", uid])?.[ - ":block/children" - ]?.length || 0; +const getChildrenLengthByPageUid = async (uid: string): Promise => { + const result = await window.roamAlphaAPI.data.pull("[:block/children]", [ + ":block/uid", + uid, + ]); + return result?.[":block/children"]?.length || 0; +}; export default getChildrenLengthByPageUid; diff --git a/src/queries/getCreateTimeByBlockUid.ts b/src/queries/getCreateTimeByBlockUid.ts index 9159348..68d5595 100644 --- a/src/queries/getCreateTimeByBlockUid.ts +++ b/src/queries/getCreateTimeByBlockUid.ts @@ -1,6 +1,9 @@ -const getCreateTimeByBlockUid = (uid: string): number => - window.roamAlphaAPI.pull(`[:edit/time]`, [":block/uid", uid])?.[ - ":create/time" - ] || 0; +const getCreateTimeByBlockUid = async (uid: string): Promise => { + const result = await window.roamAlphaAPI.data.pull(`[:create/time]`, [ + ":block/uid", + uid, + ]); + return result?.[":create/time"] || 0; +}; export default getCreateTimeByBlockUid; diff --git a/src/queries/getEditTimeByBlockUid.ts b/src/queries/getEditTimeByBlockUid.ts index ecb2bab..04dcfb7 100644 --- a/src/queries/getEditTimeByBlockUid.ts +++ b/src/queries/getEditTimeByBlockUid.ts @@ -1,6 +1,9 @@ -const getEditTimeByBlockUid = (uid: string): number => - window.roamAlphaAPI.pull(`[:edit/time]`, [":block/uid", uid])?.[ - ":edit/time" - ] || 0; +const getEditTimeByBlockUid = async (uid: string): Promise => { + const result = await window.roamAlphaAPI.data.pull(`[:edit/time]`, [ + ":block/uid", + uid, + ]); + return result?.[":edit/time"] || 0; +}; export default getEditTimeByBlockUid; diff --git a/src/queries/getFullTreeByParentUid.ts b/src/queries/getFullTreeByParentUid.ts index c092771..9b3c959 100644 --- a/src/queries/getFullTreeByParentUid.ts +++ b/src/queries/getFullTreeByParentUid.ts @@ -36,10 +36,9 @@ const formatRoamNode = (n: PullBlock | null): TreeNode => { }; }; -const getFullTreeByParentUid = (uid: string): TreeNode => - formatRoamNode( - window.roamAlphaAPI.pull( - `[ +const getFullTreeByParentUid = async (uid: string): Promise => { + const result = await window.roamAlphaAPI.data.pull( + `[ :block/string :node/title :block/uid @@ -53,8 +52,9 @@ const getFullTreeByParentUid = (uid: string): TreeNode => {:block/parents [:children/view-type]} {:block/children ...} ]`, - [`:block/uid`, uid] - ) + [`:block/uid`, uid] ); + return formatRoamNode(result); +}; export default getFullTreeByParentUid; diff --git a/src/queries/getPageTitleByPageUid.ts b/src/queries/getPageTitleByPageUid.ts index dcb04ef..c0b771b 100644 --- a/src/queries/getPageTitleByPageUid.ts +++ b/src/queries/getPageTitleByPageUid.ts @@ -1,11 +1,13 @@ import { PullBlock } from "../types"; -export const getPageTitleByPageUid = (pageUid: string): string => - ( - window.roamAlphaAPI.pull(`[:node/title]`, [ - ":block/uid", - pageUid, - ]) as PullBlock - )?.[":node/title"] || ""; +export const getPageTitleByPageUid = async ( + pageUid: string +): Promise => { + const result = (await window.roamAlphaAPI.data.pull(`[:node/title]`, [ + ":block/uid", + pageUid, + ])) as PullBlock; + return result?.[":node/title"] || ""; +}; export default getPageTitleByPageUid; diff --git a/src/queries/getPageUidByPageTitle.ts b/src/queries/getPageUidByPageTitle.ts index ac04a92..616a237 100644 --- a/src/queries/getPageUidByPageTitle.ts +++ b/src/queries/getPageUidByPageTitle.ts @@ -1,7 +1,7 @@ -const getPageUidByPageTitle = (title: string): string => { +const getPageUidByPageTitle = async (title: string): Promise => { if (!title) return ""; return ( - window.roamAlphaAPI.pull("[:block/uid]", [":node/title", title])?.[ + (await window.roamAlphaAPI.pull("[:block/uid]", [":node/title", title]))?.[ ":block/uid" ] || "" ); diff --git a/src/queries/getTextByBlockUid.ts b/src/queries/getTextByBlockUid.ts index 370e5a5..239bb99 100644 --- a/src/queries/getTextByBlockUid.ts +++ b/src/queries/getTextByBlockUid.ts @@ -1,8 +1,10 @@ -const getTextByBlockUid = (uid = ""): string => - (uid && - window.roamAlphaAPI.pull("[:block/string]", [":block/uid", uid])?.[ - ":block/string" - ]) || - ""; +const getTextByBlockUid = async (uid = ""): Promise => { + if (!uid) return ""; + const result = await window.roamAlphaAPI.data.pull("[:block/string]", [ + ":block/uid", + uid, + ]); + return result?.[":block/string"] || ""; +}; export default getTextByBlockUid; diff --git a/src/queries/isLiveBlock.ts b/src/queries/isLiveBlock.ts index 2996a75..27d1cab 100644 --- a/src/queries/isLiveBlock.ts +++ b/src/queries/isLiveBlock.ts @@ -1,4 +1,9 @@ -const isLiveBlock = (uid: string) => - !!window.roamAlphaAPI.pull("[:db/id]", [":block/uid", uid]); +const isLiveBlock = async (uid: string): Promise => { + const result = await window.roamAlphaAPI.data.pull("[:db/id]", [ + ":block/uid", + uid, + ]); + return !!result; +}; export default isLiveBlock; From c1dd7766fa045fe9a636002b07f4f19bddef5cc8 Mon Sep 17 00:00:00 2001 From: Michael Gartner Date: Sun, 23 Mar 2025 23:44:45 -0600 Subject: [PATCH 4/8] misc --- src/date/parseNlpDate.ts | 35 ++++++++++++++++++-------- src/util/extensionDeprecatedWarning.ts | 8 +++--- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/src/date/parseNlpDate.ts b/src/date/parseNlpDate.ts index a538b2f..2a17752 100644 --- a/src/date/parseNlpDate.ts +++ b/src/date/parseNlpDate.ts @@ -10,20 +10,35 @@ import { Chrono, Parser } from "chrono-node"; import { ParsingComponents } from "chrono-node/dist/results"; import getCurrentUserUid from "../queries/getCurrentUserUid"; +type WeekDay = 0 | 1 | 2 | 3 | 4 | 5 | 6; + +let cachedWeekStartsOn: WeekDay | null = null; + +const getWeekStartsOn = async (): Promise => { + const weekStartsOn = ( + await window.roamAlphaAPI.pull("[:user/settings]", [ + ":user/uid", + getCurrentUserUid(), + ]) + )?.[":user/settings"]?.[":first-day-of-week"] as WeekDay; + cachedWeekStartsOn = weekStartsOn || 0; + return cachedWeekStartsOn; +}; + const startOfWeek = (date: Date) => { - const weekStartsOn = window.roamAlphaAPI.pull("[:user/settings]", [ - ":user/uid", - getCurrentUserUid(), - ])?.[":user/settings"]?.[":first-day-of-week"]; - return dateFnsStartOfWeek(date, weekStartsOn ? { weekStartsOn } : undefined); + if (cachedWeekStartsOn === null) { + getWeekStartsOn().catch(console.error); + return dateFnsStartOfWeek(date); + } + return dateFnsStartOfWeek(date, { weekStartsOn: cachedWeekStartsOn }); }; const endOfWeek = (date: Date) => { - const weekStartsOn = window.roamAlphaAPI.pull("[:user/settings]", [ - ":user/uid", - getCurrentUserUid(), - ])?.[":user/settings"]?.[":first-day-of-week"]; - return dateFnsEndOfWeek(date, weekStartsOn ? { weekStartsOn } : undefined); + if (cachedWeekStartsOn === null) { + getWeekStartsOn().catch(console.error); + return dateFnsEndOfWeek(date); + } + return dateFnsEndOfWeek(date, { weekStartsOn: cachedWeekStartsOn }); }; const ORDINAL_WORD_DICTIONARY: { [word: string]: number } = { diff --git a/src/util/extensionDeprecatedWarning.ts b/src/util/extensionDeprecatedWarning.ts index 4f1619b..8367003 100644 --- a/src/util/extensionDeprecatedWarning.ts +++ b/src/util/extensionDeprecatedWarning.ts @@ -15,17 +15,17 @@ const extensionDeprecatedWarning = async ({ extensionId: string; reason: string; }): Promise => { - const configUid = getPageUidByPageTitle(extensionId); - const config = getBasicTreeByParentUid(configUid); + const configUid = await getPageUidByPageTitle(extensionId); + const config = await getBasicTreeByParentUid(configUid); const donotShowAgainUid = getSubTree({ tree: config, key: "Do not show again", }).uid; if (!donotShowAgainUid) { const blocks = ( - window.roamAlphaAPI.data.fast.q( + (await window.roamAlphaAPI.data.backend.q( `[:find (pull ?roamjs [:block/uid]) :where [?block :block/string ?contents] [(clojure.string/includes? ?contents "https://roamjs.com/${extensionId}")] [?roamjs :block/children ?block]]` - ) as [PullBlock][] + )) as [PullBlock][] ).map(([block]) => block[":block/uid"] || ""); renderSimpleAlert({ content: `RoamJS will soon be deprecating and then removing the ${idToTitle( From cba83c94282a4a7b119bef1463bff6d4d3dbf161 Mon Sep 17 00:00:00 2001 From: Michael Gartner Date: Sun, 23 Mar 2025 23:44:48 -0600 Subject: [PATCH 5/8] components --- src/components/BlockInput.tsx | 21 ++++++++++--- src/components/FormDialog.tsx | 56 ++++++++++++++++++++++------------- 2 files changed, 52 insertions(+), 25 deletions(-) diff --git a/src/components/BlockInput.tsx b/src/components/BlockInput.tsx index 7e49e8c..dc74ea9 100644 --- a/src/components/BlockInput.tsx +++ b/src/components/BlockInput.tsx @@ -5,7 +5,13 @@ import { MenuItem, InputGroup, } from "@blueprintjs/core"; -import React, { useCallback, useMemo, useRef, useState } from "react"; +import React, { + useCallback, + useMemo, + useRef, + useState, + useEffect, +} from "react"; import getAllBlockUidsAndTexts from "../queries/getAllBlockUidsAndTexts"; import useArrowKeyDown from "../hooks/useArrowKeyDown"; @@ -29,16 +35,23 @@ const BlockInput = ({ setValue: (q: string, uid?: string) => void; onBlur?: (v: string) => void; onConfirm?: () => void; - getAllBlocks?: () => { text: string; uid: string }[]; + getAllBlocks?: () => Promise<{ text: string; uid: string }[]>; autoFocus?: boolean; }): React.ReactElement => { const [isOpen, setIsOpen] = useState(false); + const [allBlocks, setAllBlocks] = useState<{ text: string; uid: string }[]>( + [] + ); const open = useCallback(() => setIsOpen(true), [setIsOpen]); const close = useCallback(() => setIsOpen(false), [setIsOpen]); - const allBlocks = useMemo(getAllBlocks, []); + + useEffect(() => { + getAllBlocks().then(setAllBlocks); + }, [getAllBlocks]); + const items = useMemo( () => (value && isOpen ? searchBlocksByString(value, allBlocks) : []), - [value, allBlocks] + [value, allBlocks, isOpen] ); const menuRef = useRef(null); const inputRef = useRef(null); diff --git a/src/components/FormDialog.tsx b/src/components/FormDialog.tsx index bfe984a..5095de0 100644 --- a/src/components/FormDialog.tsx +++ b/src/components/FormDialog.tsx @@ -25,7 +25,7 @@ import MenuItemSelect from "./MenuItemSelect"; import PageInput from "./PageInput"; import nanoid from "nanoid"; import { getUids } from "../dom"; -import { InputTextNode, PullBlock } from "../types"; +import { InputTextNode } from "../types"; import getFullTreeByParentUid from "../queries/getFullTreeByParentUid"; import createPage from "../writes/createPage"; import { createBlock } from "../writes"; @@ -135,8 +135,11 @@ const EmbedInput = ({ }); if (autoFocus) realFocus(); }); - // In the future, we can return the whole tree of data from `parentUid` - onChange(() => getFullTreeByParentUid(parentUid).children); + const updateTreeData = async () => { + const tree = await getFullTreeByParentUid(parentUid); + onChange(() => tree.children); + }; + updateTreeData(); return () => { window.roamAlphaAPI.deletePage({ page: { uid: parentUid } }); }; @@ -166,15 +169,15 @@ const EmbedInput = ({ className="rounded-md bg-white font-normal mt-1 bp3-input h-32 overflow-scroll roamjs-form-embed py-2 px-4" tabIndex={0} onFocus={realFocus} - onKeyDown={(e) => { + onKeyDown={async (e) => { if (e.key !== "Tab") return; const { blockUid } = getUids(e.target as HTMLTextAreaElement); if (!blockUid) return; const { [":block/order"]: order, [":block/parents"]: parents } = - window.roamAlphaAPI.pull( + await window.roamAlphaAPI.pull( "[:block/order {:block/parents [:block/uid]}]", [":block/uid", blockUid] - ) as PullBlock; + ); if ( !( order === 0 && @@ -209,6 +212,22 @@ const EmbedInput = ({ ); }; +const AsyncBlockInput = ({ + value, + setValue, + autoFocus, +}: { + value: string; + setValue: (text: string, uid?: string) => Promise; + autoFocus: boolean; +}) => { + const [text, setText] = useState(value); + useEffect(() => { + getTextByBlockUid(value).then(setText); + }, [value]); + return ; +}; + const FormDialog = >({ title, content, @@ -393,21 +412,16 @@ const FormDialog = >({ {...getFieldAttributes(name, meta)} > {meta.label} - - setValue( - window.roamAlphaAPI.pull("[:db/id]", [ - ":block/uid", - uid || "", - ]) - ? uid - : text - ) - } + { + if (!uid) return setValue(text); + const result = await window.roamAlphaAPI.pull("[:db/id]", [ + ":block/uid", + uid, + ]); + setValue(result ? uid : text); + }} autoFocus={index === 0} /> From 558d6802e0c30774707500a6d5b655c5c8d04d41 Mon Sep 17 00:00:00 2001 From: Michael Gartner Date: Mon, 7 Apr 2025 16:58:56 -0600 Subject: [PATCH 6/8] Refactor components to use async/await --- src/components/ConfigPage.tsx | 62 ++++++++++++------- .../ConfigPanels/MultiChildPanel.tsx | 17 +++-- src/components/ConfigPanels/OauthPanel.tsx | 39 +++++++----- .../ConfigPanels/useSingleChildValue.tsx | 31 +++++++--- src/components/ExternalLogin.tsx | 61 ++++++++++-------- src/components/OauthSelect.tsx | 27 +++++--- src/components/PageInput.tsx | 18 +++++- src/dom/addBlockCommand.ts | 10 +-- src/dom/createPageObserver.ts | 12 ++-- src/dom/getBlockUidFromTarget.ts | 6 +- src/dom/getDropUidOffset.ts | 6 +- src/dom/getReferenceBlockUid.ts | 6 +- src/dom/getRoamUrlByPage.ts | 4 +- src/dom/resolveRefs.ts | 41 ++++++++---- src/queries/getFirstChildUidByBlockUid.ts | 4 +- src/util/addInputSetting.ts | 4 +- 16 files changed, 226 insertions(+), 122 deletions(-) diff --git a/src/components/ConfigPage.tsx b/src/components/ConfigPage.tsx index a8eb603..843890d 100644 --- a/src/components/ConfigPage.tsx +++ b/src/components/ConfigPage.tsx @@ -1,5 +1,11 @@ import { Card, Tab, Tabs } from "@blueprintjs/core"; -import React, { useCallback, useMemo, useRef, useState } from "react"; +import React, { + useCallback, + useMemo, + useRef, + useState, + useEffect, +} from "react"; import ReactDOM from "react-dom"; import createHTMLObserver from "../dom/createHTMLObserver"; import createBlock from "../writes/createBlock"; @@ -11,7 +17,7 @@ import localStorageGet from "../util/localStorageGet"; import idToTitle from "../util/idToTitle"; import type { Field, UnionField } from "./ConfigPanels/types"; import { Brand } from "./ConfigPanels/getBrandColors"; -import { InputTextNode } from "../types"; +import { InputTextNode, RoamBasicNode } from "../types"; export type ConfigTab = { id: string; @@ -61,12 +67,25 @@ const FieldTabs = ({ }); return newUid; }, [pageUid, uid, id, toggleable]); - const childUids = Object.fromEntries( - getShallowTreeByParentUid(parentUid).map(({ text, uid }) => [ - text.toLowerCase().trim(), - uid, - ]) - ); + + const [childUids, setChildUids] = useState>({}); + + useEffect(() => { + const loadChildUids = async () => { + try { + const tree = await getShallowTreeByParentUid(parentUid); + setChildUids( + Object.fromEntries( + tree.map(({ text, uid }) => [text.toLowerCase().trim(), uid]) + ) + ); + } catch (error) { + console.error("Failed to load child UIDs:", error); + } + }; + loadChildUids(); + }, [parentUid]); + const [selectedTabId, setSelectedTabId] = useState( fields.length && typeof toggleable !== "string" ? fields[0].title @@ -121,11 +140,16 @@ const ConfigPage = ({ ? config.tabs.filter((t) => t.fields.length || t.toggleable) : [{ fields: config, id: "home" }]; const [selectedTabId, setSelectedTabId] = useState(userTabs[0]?.id); + const [tree, setTree] = useState([]); + + useEffect(() => { + getBasicTreeByParentUid(pageUid).then(setTree); + }, [pageUid]); + const onTabsChange = useCallback( (tabId: string) => setSelectedTabId(tabId), [setSelectedTabId] ); - const tree = getBasicTreeByParentUid(pageUid); // first character trimmed intentionally for the `v` below const titleRef = useRef(null); @@ -248,10 +272,10 @@ const createConfigPage = ({ }); }; -export const render = ({ +export const render = async ({ h, title, - pageUid = getPageUidByPageTitle(title), + pageUid, config, }: { h: HTMLHeadingElement; @@ -259,7 +283,7 @@ export const render = ({ pageUid?: string; config: Config; }) => { - const uid = getPageUidByPageTitle(title); + const uid = pageUid || (await getPageUidByPageTitle(title)); const attribute = `data-roamjs-${uid}`; const containerParent = h.parentElement?.parentElement; if (containerParent && !containerParent.hasAttribute(attribute)) { @@ -272,7 +296,7 @@ export const render = ({ h.parentElement?.nextElementSibling || null ); ReactDOM.render( - , + , parent ); } @@ -286,11 +310,12 @@ export const createConfigObserver = async ({ config: Config; }): Promise<{ pageUid: string; observer?: MutationObserver }> => { const pageUid = - getPageUidByPageTitle(title) || + (await getPageUidByPageTitle(title)) || (await createConfigPage({ title, config, })); + if ("tabs" in config ? !!config.tabs.length : !!config.length) { const observer = createHTMLObserver({ className: "rm-title-display", @@ -307,14 +332,9 @@ export const createConfigObserver = async ({ } }, }); - return { - pageUid, - observer, - }; + return { pageUid, observer }; } - return { - pageUid, - }; + return { pageUid }; }; export default ConfigPage; diff --git a/src/components/ConfigPanels/MultiChildPanel.tsx b/src/components/ConfigPanels/MultiChildPanel.tsx index 148b5fc..2b7f6f4 100644 --- a/src/components/ConfigPanels/MultiChildPanel.tsx +++ b/src/components/ConfigPanels/MultiChildPanel.tsx @@ -1,5 +1,5 @@ import { Button, Label } from "@blueprintjs/core"; -import React, { useState } from "react"; +import React, { useState, useEffect } from "react"; import getShallowTreeByParentUid from "../../queries/getShallowTreeByParentUid"; import idToTitle from "../../util/idToTitle"; import Description from "../Description"; @@ -22,10 +22,19 @@ const MultiChildPanel: FieldPanel< InputComponent, }) => { const [uid, setUid] = useState(initialUid); - const [texts, setTexts] = useState(() => - uid ? getShallowTreeByParentUid(uid) : [] - ); + const [texts, setTexts] = useState<{ text: string; uid: string }[]>([]); const [value, setValue] = useState(""); + + useEffect(() => { + const loadTexts = async () => { + if (uid) { + const items = await getShallowTreeByParentUid(uid); + setTexts(items); + } + }; + loadTexts(); + }, [uid]); + return ( <>