Skip to content

Conversation

@maparent
Copy link
Collaborator

@maparent maparent commented Jun 25, 2025

Obtain a password from the roam props of the plugin settings, intended to use for the supabase anonymous user for the space.
Create it and store it otherwise.
Added an utility function to set Props.

Note that I'm basing it on 520, not because I need to yet, but because my next task will use both of those together, and unless the merges come really fast I'll be paralyzed.

Summary by CodeRabbit

  • New Features

    • Introduced the ability to set and update block properties within Roam.
    • Added automatic management and retrieval of a "space password" for enhanced workspace security.
  • Refactor

    • Improved separation between data retrieval and normalization for block properties, making property handling more modular and maintainable.

@linear
Copy link

linear bot commented Jun 25, 2025

@maparent
Copy link
Collaborator Author

@CodeRabbit review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jun 25, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jun 25, 2025

📝 Walkthrough

Walkthrough

The changes introduce new utilities for managing block properties in Roam, including functions to retrieve raw and normalized block properties, and a new module to set and denormalize block properties. Additionally, the Supabase context is updated to include a "space password," which is retrieved or generated and stored in block properties.

Changes

File(s) Change Summary
apps/roam/src/utils/getBlockProps.ts Added getRawBlockProps for direct property retrieval; refactored getBlockProps to use it and normalize results.
apps/roam/src/utils/setBlockProps.ts Introduced new module with setBlockProps, deNormalizeProps, and testSetBlockProps for setting and denormalizing block properties.
apps/roam/src/utils/supabaseContext.ts Added spacePassword property to context; retrieves or generates password and stores in block properties.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant BlockAPI as Roam Block API

    Client->>BlockAPI: getRawBlockProps(uid)
    BlockAPI-->>Client: rawProps
    Client->>Client: normalizeProps(rawProps)
    Client-->>Client: getBlockProps returns normalizedProps
Loading
sequenceDiagram
    participant Client
    participant BlockAPI as Roam Block API

    Client->>BlockAPI: getRawBlockProps(uid)
    BlockAPI-->>Client: baseProps
    Client->>Client: deNormalizeProps(newProps)
    Client->>Client: merge baseProps with deNormalized newProps
    Client->>BlockAPI: update block properties
    BlockAPI-->>Client: updatedProps
    Client-->>Client: setBlockProps returns updatedProps
Loading
sequenceDiagram
    participant Client
    participant BlockAPI as Roam Block API

    Client->>BlockAPI: getBlockProps(configPageUid)
    BlockAPI-->>Client: configProps
    alt password exists
        Client-->>Client: use existing password
    else password missing
        Client->>Client: generate random UUID
        Client->>BlockAPI: setBlockProps(configPageUid, {"space-user-password": uuid})
    end
    Client-->>Client: include spacePassword in SupabaseContext
Loading

Possibly related PRs


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.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
apps/roam/src/utils/setBlockProps.ts (1)

27-38: Consider adding error handling for invalid UIDs.

The function correctly merges properties and updates the block, but it doesn't validate whether the UID exists before attempting the update.

Consider adding basic validation:

const setBlockProps = (uid: string, newProps: Record<string, json>) => {
+  if (!uid) {
+    console.warn("setBlockProps: Invalid UID provided");
+    return null;
+  }
  const baseProps = getRawBlockProps(uid);
  if (typeof baseProps === "object" && !Array.isArray(baseProps)) {
    const props = {
      ...(baseProps || {}),
      ...(deNormalizeProps(newProps) as Record<string, json>),
    } as Record<string, json>;
-    window.roamAlphaAPI.data.block.update({ block: { uid, props } });
+    try {
+      window.roamAlphaAPI.data.block.update({ block: { uid, props } });
+    } catch (error) {
+      console.error(`Failed to update block properties for UID ${uid}:`, error);
+      throw error;
+    }
    return props;
  }
  return baseProps;
};
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9cf8334 and 0e6ff35.

📒 Files selected for processing (3)
  • apps/roam/src/utils/getBlockProps.ts (1 hunks)
  • apps/roam/src/utils/setBlockProps.ts (1 hunks)
  • apps/roam/src/utils/supabaseContext.ts (3 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
apps/roam/src/utils/supabaseContext.ts (2)
packages/database/types.gen.ts (1)
  • Database (9-814)
apps/roam/src/utils/renderNodeConfigPage.ts (1)
  • DISCOURSE_CONFIG_PAGE_TITLE (28-28)
apps/roam/src/utils/setBlockProps.ts (1)
apps/roam/src/utils/getBlockProps.ts (2)
  • json (1-7)
  • getRawBlockProps (27-30)
🔇 Additional comments (4)
apps/roam/src/utils/getBlockProps.ts (1)

27-33: LGTM! Clean separation of concerns.

The refactoring successfully separates raw data retrieval from normalization while maintaining backward compatibility. This design enables other modules to access raw properties when needed.

apps/roam/src/utils/supabaseContext.ts (1)

12-12: Verify crypto.randomUUID() browser support.

The crypto.randomUUID() method requires modern browser support and secure contexts (HTTPS). Ensure this aligns with your target browser compatibility.

What is the browser support for crypto.randomUUID() and does it require HTTPS?
apps/roam/src/utils/setBlockProps.ts (2)

9-25: LGTM! Correct inverse operation of normalization.

The deNormalizeProps function correctly reverses the normalization process by adding colons to keys, handling nested objects and arrays recursively. The implementation mirrors the logic in normalizeProps.


40-46: LGTM! Useful testing utility.

The testSetBlockProps function provides a convenient way to set properties using page titles, properly handling the case where the page doesn't exist.

Comment on lines +35 to +45
const getOrCreateSpacePassword = () => {
const props = getBlockProps(settingsConfigPageUid);
const existing: string | unknown = props["space-user-password"];
if (existing && typeof existing === "string") return existing;
// use a uuid as password, at least cryptographically safe
const password = crypto.randomUUID();
setBlockProps(settingsConfigPageUid, {
"space-user-password": password,
});
return password;
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Improve type safety and consider error handling.

The function has a couple of areas for improvement:

  1. Type narrowing: The existing variable is typed as string | unknown but the code only handles the string case explicitly.
  2. Error handling: No error handling for the setBlockProps operation, which could fail silently.

Consider this improvement:

const getOrCreateSpacePassword = () => {
  const props = getBlockProps(settingsConfigPageUid);
-  const existing: string | unknown = props["space-user-password"];
-  if (existing && typeof existing === "string") return existing;
+  const existing = props["space-user-password"];
+  if (typeof existing === "string" && existing.length > 0) return existing;
  // use a uuid as password, at least cryptographically safe
  const password = crypto.randomUUID();
-  setBlockProps(settingsConfigPageUid, {
-    "space-user-password": password,
-  });
+  try {
+    setBlockProps(settingsConfigPageUid, {
+      "space-user-password": password,
+    });
+  } catch (error) {
+    console.error("Failed to store space password:", error);
+    // Consider whether to throw or handle gracefully
+  }
  return password;
};
📝 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.

Suggested change
const getOrCreateSpacePassword = () => {
const props = getBlockProps(settingsConfigPageUid);
const existing: string | unknown = props["space-user-password"];
if (existing && typeof existing === "string") return existing;
// use a uuid as password, at least cryptographically safe
const password = crypto.randomUUID();
setBlockProps(settingsConfigPageUid, {
"space-user-password": password,
});
return password;
};
const getOrCreateSpacePassword = () => {
const props = getBlockProps(settingsConfigPageUid);
const existing = props["space-user-password"];
if (typeof existing === "string" && existing.length > 0) return existing;
// use a uuid as password, at least cryptographically safe
const password = crypto.randomUUID();
try {
setBlockProps(settingsConfigPageUid, {
"space-user-password": password,
});
} catch (error) {
console.error("Failed to store space password:", error);
// Consider whether to throw or handle gracefully
}
return password;
};
🤖 Prompt for AI Agents
In apps/roam/src/utils/supabaseContext.ts around lines 35 to 45, improve type
safety by refining the type of the `existing` variable to exclude `unknown` and
explicitly handle non-string cases or absence of the property. Add error
handling around the `setBlockProps` call by wrapping it in a try-catch block to
catch and handle potential failures, such as logging the error or rethrowing it,
to prevent silent failures.

@maparent
Copy link
Collaborator Author

@CodeRabbit the existence of this uid is an invariant

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jun 25, 2025

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

@maparent I need to examine the code to understand which specific UID you're referring to as an invariant. Let me look at the implementation details.


🏁 Script executed:

#!/bin/bash
# Examine the supabaseContext.ts file to understand the UID reference
cat apps/roam/src/utils/supabaseContext.ts

Length of output: 4522


@maparent Thank you for clarifying! I can see you're referring to the settingsConfigPageUid obtained from getPageUidByPageTitle(DISCOURSE_CONFIG_PAGE_TITLE).

You're stating that the configuration page will always exist in the system, which explains why the code can safely use this UID directly in getBlockProps() and setBlockProps() without defensive null checks. This is an important system design assumption.

  (\   /)
 ( ._. )
o_("_")("_")

Thoughtful rabbit taking notes


✏️ Learnings added
Learnt from: maparent
URL: https://github.com/DiscourseGraphs/discourse-graph/pull/245

Timestamp: 2025-06-25T22:56:17.467Z
Learning: In the Roam discourse-graph system, the existence of the configuration page (identified by DISCOURSE_CONFIG_PAGE_TITLE) and its corresponding UID is a system invariant. The code can safely assume this page will always exist, so defensive null checks are not needed when using `getPageUidByPageTitle(DISCOURSE_CONFIG_PAGE_TITLE)`.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

@maparent maparent marked this pull request as ready for review June 25, 2025 23:08
@maparent maparent requested a review from mdroidian June 25, 2025 23:08
@maparent maparent force-pushed the ENG-520-supabase-in-frontend branch from 9cf8334 to 6cfbec9 Compare June 26, 2025 01:37
@maparent maparent force-pushed the ENG-418-create-and-store-roam-space-password branch from 0e6ff35 to 07cf6d2 Compare June 26, 2025 01:37
@maparent maparent force-pushed the ENG-520-supabase-in-frontend branch from 6cfbec9 to 93b7c94 Compare June 26, 2025 02:22
@maparent maparent force-pushed the ENG-418-create-and-store-roam-space-password branch from 07cf6d2 to 89162a9 Compare June 26, 2025 02:22
Copy link
Contributor

@mdroidian mdroidian left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I won't block this, but I'm not sure deNormalizeProps is required

@maparent maparent force-pushed the ENG-418-create-and-store-roam-space-password branch from 89162a9 to 3bd13a0 Compare June 26, 2025 03:55
Base automatically changed from ENG-520-supabase-in-frontend to main June 26, 2025 04:04
@maparent maparent force-pushed the ENG-418-create-and-store-roam-space-password branch from 3bd13a0 to 67ecd10 Compare June 26, 2025 12:29
Create it (as a UUID, which is cryptographicallly safe) and store it otherwise.
Added an utility function to set Props.
@maparent maparent force-pushed the ENG-418-create-and-store-roam-space-password branch from 67ecd10 to 12b91a4 Compare June 26, 2025 12:37
@maparent maparent merged commit b3a0b19 into main Jun 26, 2025
4 checks passed
@github-project-automation github-project-automation bot moved this to Done in General Jun 26, 2025
@maparent maparent deleted the ENG-418-create-and-store-roam-space-password branch June 26, 2025 12:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

No open projects
Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants