-
Notifications
You must be signed in to change notification settings - Fork 4
ENG-1011 Create Function to Record Relation Triples in Roam #534
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ENG-1011 Create Function to Record Relation Triples in Roam #534
Conversation
|
This pull request has been ignored for the connected project Preview Branches by Supabase. |
|
@CodeRabbit review |
✅ Actions performedReview triggered.
|
📝 WalkthroughWalkthroughIntroduces a new utility module that enables creation of reified blocks and relations within a Roam discourse graph system. The module provides functions to create parameterized blocks under a destination and conditionally establish reified relations between source and destination blocks when a user setting is enabled. Changes
Sequence Diagram(s)sequenceDiagram
participant Caller
participant createReifiedRelation
participant getSetting
participant createReifiedBlock
participant getRelationPageUid
participant Cache
participant roamAPI as Roam API<br/>(lookup/create page)
Caller->>createReifiedRelation: createReifiedRelation(sourceUid, relationBlockUid, destinationUid)
createReifiedRelation->>getSetting: getSetting("use-reified-relations")
alt Setting enabled
getSetting-->>createReifiedRelation: true
createReifiedRelation->>getRelationPageUid: getRelationPageUid()
getRelationPageUid->>Cache: Check cached uid
alt Cache hit
Cache-->>getRelationPageUid: cached uid
else Cache miss
getRelationPageUid->>roamAPI: getPageUidByPageTitle("roam/js/discourse-graph/relations")
alt Page found
roamAPI-->>getRelationPageUid: uid
else Page not found
getRelationPageUid->>roamAPI: createPage(title)
roamAPI-->>getRelationPageUid: new uid
end
getRelationPageUid->>Cache: Store uid
end
getRelationPageUid-->>createReifiedRelation: relationPageUid
createReifiedRelation->>createReifiedBlock: createReifiedBlock(relationPageUid, relationBlockUid, {sourceUid, destinationUid})
createReifiedBlock->>roamAPI: createBlock, setBlockProps
roamAPI-->>createReifiedBlock: new block uid
createReifiedBlock-->>createReifiedRelation: uid
createReifiedRelation-->>Caller: uid
else Setting disabled
getSetting-->>createReifiedRelation: false
createReifiedRelation-->>Caller: undefined
end
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes
Pre-merge checks✅ Passed checks (2 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (2)
apps/roam/src/utils/createReifiedBlock.ts (2)
14-21: Add error handling for block creation.The block creation logic is correct, but there's no error handling if
createBlockfails. Consider wrapping in try-catch or allowing the error to propagate with proper context.
7-11: Consider using named parameters for improved clarity.The function has 3 parameters. Per coding guidelines, consider using object destructuring for better readability and maintainability.
-export const createReifiedBlock = async ( - destinationBlockUid: string, - schemaUid: string, - parameterUids: Record<string, string>, -): Promise<string> => { +export const createReifiedBlock = async ({ + destinationBlockUid, + schemaUid, + parameterUids, +}: { + destinationBlockUid: string; + schemaUid: string; + parameterUids: Record<string, string>; +}): Promise<string> => {Note: This would require updating call sites as well.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
apps/roam/src/utils/createReifiedBlock.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/main.mdc)
**/*.{ts,tsx}: Prefertypeoverinterface
Use explicit return types for functions
Avoidanytypes when possible
Files:
apps/roam/src/utils/createReifiedBlock.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursor/rules/main.mdc)
**/*.{ts,tsx,js,jsx}: Prefer arrow functions over regular function declarations
Use named parameters (object destructuring) when a function has more than 2 parameters
Use Prettier with the project's configuration
Maintain consistent naming conventions: PascalCase for components and types
Maintain consistent naming conventions: camelCase for variables and functions
Maintain consistent naming conventions: UPPERCASE for constants
Files:
apps/roam/src/utils/createReifiedBlock.ts
apps/roam/**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/roam.mdc)
apps/roam/**/*.{js,jsx,ts,tsx}: Use BlueprintJS 3 components and Tailwind CSS for platform-native UI in the Roam Research extension
Use the roamAlphaApi documentation from https://roamresearch.com/#/app/developer-documentation/page/tIaOPdXCj when working with the Roam API
Use Roam Depot/Extension API documentation from https://roamresearch.com/#/app/developer-documentation/page/y31lhjIqU when working with the Roam Extension API
Files:
apps/roam/src/utils/createReifiedBlock.ts
🔇 Additional comments (3)
apps/roam/src/utils/createReifiedBlock.ts (3)
1-5: LGTM!The imports are properly structured and use appropriate paths.
47-63: Original review comment is incorrect.The
getSettingfunction is synchronous (returnsT, notPromise<T>), so line 52 is correct as written. There is no issue with the condition check at line 53—authorizedwill be a boolean value, not a Promise.The concern about getSetting being async and causing an "always truthy Promise" condition does not apply here.
Likely an incorrect or invalid review comment.
22-30: (A) – I need the official Roam API docs to verify ifroamAlphaAPI.data.block.updateis async.
| export const createReifiedBlock = async ( | ||
| destinationBlockUid: string, | ||
| schemaUid: string, | ||
| parameterUids: Record<string, string>, | ||
| ): Promise<string> => { | ||
| // TODO/Question: Should we try to ensure uniqueness? | ||
| const newUid = window.roamAlphaAPI.util.generateUID(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Address the TODO and add safety check for roamAlphaAPI.
Two concerns:
- The TODO about ensuring uniqueness should be resolved or tracked properly.
window.roamAlphaAPImight be undefined if the API is not loaded, which would cause a runtime error.
Consider adding a guard:
+ if (!window.roamAlphaAPI?.util) {
+ throw new Error("Roam API not available");
+ }
const newUid = window.roamAlphaAPI.util.generateUID();Would you like me to open an issue to track the uniqueness TODO?
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| export const createReifiedBlock = async ( | |
| destinationBlockUid: string, | |
| schemaUid: string, | |
| parameterUids: Record<string, string>, | |
| ): Promise<string> => { | |
| // TODO/Question: Should we try to ensure uniqueness? | |
| const newUid = window.roamAlphaAPI.util.generateUID(); | |
| export const createReifiedBlock = async ( | |
| destinationBlockUid: string, | |
| schemaUid: string, | |
| parameterUids: Record<string, string>, | |
| ): Promise<string> => { | |
| // TODO/Question: Should we try to ensure uniqueness? | |
| if (!window.roamAlphaAPI?.util) { | |
| throw new Error("Roam API not available"); | |
| } | |
| const newUid = window.roamAlphaAPI.util.generateUID(); |
🤖 Prompt for AI Agents
In apps/roam/src/utils/createReifiedBlock.ts around lines 7–13, resolve the TODO
and guard against a missing Roam API: first check that window.roamAlphaAPI
exists and throw or return a clear error if not, then remove the bare TODO and
implement a UID-uniqueness loop that generates a UID, checks for an existing
entity with that UID via the Roam API (e.g., a pull/query or a util lookup),
retrying up to a small maxAttempts (e.g., 5–10) before failing with an explicit
error; if you cannot guarantee uniqueness beyond retries, replace the TODO with
a comment referencing an opened issue and create that issue to track stronger
uniqueness guarantees.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
none of this package will be activated without roamAlphaAPI, not a concern.
I think if there is an error in this code, I will let it percolate.
I was hesitant on TODO scope creep, but decided it's in scope.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@maparent, understood! I appreciate the clarification:
- The roamAlphaAPI check isn't necessary given the package activation guarantees
- You'll address the uniqueness TODO as part of this PR since it's in scope
- Error propagation approach is clear
Thanks for the context on the architectural constraints! 👍
🧠 Learnings used
Learnt from: maparent
Repo: DiscourseGraphs/discourse-graph PR: 534
File: apps/roam/src/utils/createReifiedBlock.ts:40-48
Timestamp: 2025-11-05T21:57:14.886Z
Learning: In the discourse-graph repository, the function `getPageUidByPageTitle` from `roamjs-components/queries/getPageUidByPageTitle` is a synchronous function that returns a string directly (the page UID or an empty string if not found), not a Promise. It should be called without `await`.
Learnt from: CR
Repo: DiscourseGraphs/discourse-graph PR: 0
File: .cursor/rules/roam.mdc:0-0
Timestamp: 2025-07-19T22:34:23.619Z
Learning: Applies to apps/roam/**/*.{js,jsx,ts,tsx} : Use the roamAlphaApi documentation from https://roamresearch.com/#/app/developer-documentation/page/tIaOPdXCj when working with the Roam API
Learnt from: maparent
Repo: DiscourseGraphs/discourse-graph PR: 220
File: apps/roam/src/utils/conceptConversion.ts:11-40
Timestamp: 2025-06-23T11:49:45.457Z
Learning: In the DiscourseGraphs/discourse-graph codebase, direct access to `window.roamAlphaAPI` is the established pattern throughout the codebase. The team prefers to maintain this pattern consistently rather than making piecemeal changes, and plans to address dependency injection as a global refactor when scheduled.
|
@CodeRabbit review last commit |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: Length of output: 740 🏁 Script executed: Length of output: 8264 🏁 Script executed: Length of output: 5820 @maparent Thank you for the commit! I've reviewed commit 7de68d8 ("ensure relation uniqueness"). Here's my analysis: ✅ Positive Changes
🔍 Issues & Suggestions1. Inefficient UID Generation (Line 49)const newUid = window.roamAlphaAPI.util.generateUID();
// TODO: Check that the parameterUids keys correspond to the schema
const data = {
...parameterUids,
hasSchema: schemaUid,
};
const exists = await checkForReifiedBlock(data);
if (exists !== null) return exists;The const data = {
...parameterUids,
hasSchema: schemaUid,
};
const exists = await checkForReifiedBlock(data);
if (exists !== null) return exists;
const newUid = window.roamAlphaAPI.util.generateUID();2. Confusing Return Type in
|
|
@CodeRabbit review last commit |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: Length of output: 4337 @maparent Thank you for the update! I've reviewed commit 9c34b27 ("separate cases for clean signatures"). Excellent refactoring! 🎉 ✅ Major ImprovementsYou've addressed all the key issues from my previous review:
🌟 Nice Additions
📝 Minor Observations
setBlockProps(newUid, {
// eslint-disable-next-line @typescript-eslint/naming-convention
"discourse-graph": data,
});If
🎯 Overall AssessmentThis is a well-executed refactoring that significantly improves code clarity and addresses the feedback from the previous review. The separation of concerns between strict and non-strict queries makes the API much more intuitive. Great work! 👍 |
|
@CodeRabbit: setBlockProps does not need await. I am leaving the todo intentionally. Thanks for pushing me on api clarity. |
|
Tip For best results, initiate chat on the files or code changes. @maparent, thank you for the clarifications! I've noted that Best of luck with the rest of the PR! 🚀 (ᵔᴥᵔ) ♪ ✏️ Learnings added
|
9c34b27 to
793c4f9
Compare
mdroidian
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Before doing a full review, could you please add the required loom video
Done When
Behavior is verified via a loom video by manually invoking the function and confirming correct output structure.
|
A stub calling function would be helpful for review, maybe add it to |
sid597
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A video of expected input and output would be useful, not sure if I reproduced it right
793c4f9 to
3ba906e
Compare
3ba906e to
58ba2ea
Compare
|
Here is the loom video as requested in the task. I thought those were only for UX PRs? |
Videos are required by default for UX PRs, but most PRs would benefit from including one as well. That said, if a task explicitly requests a video, the point is moot. |
|
Of course, just asking why the video was requested in this specific task. |
|
@maparent is this one ready for review now? If so, please change the status from |
b702dff to
21d5b80
Compare
58ba2ea to
2a756f3
Compare
mdroidian
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approved to not block, but quite a few things I am unclear on based on the task.
230066a to
acd32d5
Compare

https://linear.app/discourse-graphs/issue/ENG-1011/create-function-to-record-relation-triples-in-roam
Summary by CodeRabbit