Skip to content

Conversation

@reynaldichernando
Copy link
Contributor

@reynaldichernando reynaldichernando commented Feb 11, 2026

workers:

  • simplify listKvValues logic, i notice we aren't using the pagination, so we should just use the simple version of the function
  • simplify deleteKvByPattern, we somehow are doing extra manual pattern logic (?) which is not needed, since the listKvValues already accepts pattern
  • removed me from router param and just use it directly, this is a global param, and not router (like user), plus its going to be always available
  • simplify /api/projects/list, some logic are just unnecessary
  • simplify /api/projects/get, removed the kvGetProject wrapper, as we don't need this, the puter.kv.get is already a one liner
  • fix /api/projects/save, adding minor comment + returning the sharedBy so it doesn't show as unknown when clicking share in the frontend
  • simplify /api/hosting/reset, hosting lives in user context, so there's no point clearing it in the workers context, since it doesn't exist in the first place

frontend:

  • fix shared by unknown, by properly passing the props into Visualizer component

notes:

  • for the public key, initially i thought we would need to filter all user's public project, but turns out we don't have that feature
  • i think we can leave the public key logic as is, because it will enable these in the future
    • allow for filtering by user id
    • prevent duplicate id, because currently we just have timestamp as the id
  • (open for comments)

Summary by CodeRabbit

  • New Features
    • Projects now track and display information about who shared them across the application.

@vercel
Copy link

vercel bot commented Feb 11, 2026

@reynaldichernando is attempting to deploy a commit to the JS Mastery Pro Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link

coderabbitai bot commented Feb 11, 2026

📝 Walkthrough

Walkthrough

This PR adds a sharedBy field to track project contributors throughout the application state and rendering, while refactoring the Puter worker module to remove helper abstractions (USER_PREFIX, getUserPuter, getMePuter) and consolidate API endpoints to use direct puter context references.

Changes

Cohort / File(s) Summary
Shared-By State Propagation
app/routes/_index.tsx, app/routes/visualizer.$id.tsx, type.d.ts
Added optional sharedBy field to track who shared a project. Field is propagated through navigation state and included in the VisualizerLocationState interface.
Puter Worker Refactoring
lib/puter.worker.js
Removed USER_PREFIX constant and helper functions (getUserPuter, getMePuter, listKvValues, listAllKvValues, kvGetProject). Updated getUserId signature to accept userPuter directly. Reworked /api/projects/list, /api/projects/get, /api/projects/save, /api/projects/clear, and /api/hosting/clear endpoints to use direct user.puter and me.puter references with simplified authentication and error handling. Updated route handler parameter destructuring and findPublicKeyByProjectId to use mePuter.kv.list.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Poem

🐰 A project now remembers who shared the deed,
While workers shed their helpers—a cleaner creed!
Direct puter paths now light the way,
Simplicity reigns, come what may! ✨

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Refactor workers' is vague and overly broad, using a generic term that doesn't convey the specific changes made in the changeset. Use a more specific title that highlights the primary change, such as 'Simplify Puter helper functions and project API endpoints' or 'Remove wrapper helpers and refactor worker authentication'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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

Comment @coderabbitai help to get the list of available commands and usage tips.

@reynaldichernando
Copy link
Contributor Author

additional notes:

  • simplify getUserParam, don't need to wrap this since implementation is just one liner
  • remove user mapping logic, since we always store the sharedBy upon save, we don't need to do any hydrating
  • remove listKvValues, since this is also just a one liner, we can implement it directly in the code
    • plus in some instance, like the delete keys, we only need the keys, and not values
  • simplify deleteKvByPattern, directly get the keys
  • simplify /api/projects/list, remove hydrate logic and set logic (its always going to be unique)
  • improve readability /api/projects/get
  • improve readbility /api/projects/save, and remove unnecessary logic for verifying owner id (its guaranteed whoever doing the action is the user itself)
  • add try catch to list, get, save APIs
  • cleanup helper route

@reynaldichernando reynaldichernando marked this pull request as ready for review February 11, 2026 08:46
Copy link

@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: 3

🤖 Fix all issues with AI agents
In `@lib/puter.worker.js`:
- Around line 179-196: The /api/projects/clear route handler
(router.post("/api/projects/clear")) is missing a try/catch like the other
endpoints, so wrap the async handler body in a try block and move the existing
logic (checking user.puter, computing userDeleted via deleteKvByPattern and
publicDeleted via deleteKvByPattern, returning jsonOk) into it; add a catch that
logs or handles the error and returns jsonError(500, "Internal server error")
(or include err.message) so any exception from deleteKvByPattern is handled
consistently with /api/projects/list, /api/projects/get, and /api/projects/save.
- Around line 185-190: The deletion pattern for public projects is too broad:
change the call to deleteKvByPattern(mePuter.kv, `${PUBLIC_PREFIX}*`) so it only
targets the current user's public entries (e.g., `${PUBLIC_PREFIX}${userId}_*`);
update the code in the block that uses userPuter, mePuter, deleteKvByPattern,
and PUBLIC_PREFIX to build a scopedPattern using the current userId (ensuring
userId is present/validated) and pass that scopedPattern to deleteKvByPattern so
only the caller's public projects are removed.
- Around line 79-117: The route handler in router.get("/api/projects/get")
incorrectly checks scope === "private", making the private-project branch
unreachable because the frontend sends scope="user" for private projects; update
the condition in that handler to check scope === "user" so the user/private
lookup using userPuter.kv.get(PROJECT_PREFIX + id) runs when appropriate (ensure
the variables mePuter, userPuter, id, scope and the PRIVATE branch logic remain
unchanged).
🧹 Nitpick comments (1)
lib/puter.worker.js (1)

138-156: Redundant auth.getUser() call in the public save path.

getUserId(userPuter) at line 138 already calls userPuter.auth.getUser(). Then line 155 calls userPuter.auth.getUser() again to get the username. Consider reusing the result to avoid a duplicate network round-trip.

♻️ Proposed refactor to avoid duplicate call
-    const userId = await getUserId(userPuter);
-    if (!userId) return jsonError(401, "User id required");
+    const userInfo = await userPuter.auth.getUser();
+    const userId = userInfo?.uuid || null;
+    if (!userId) return jsonError(401, "User id required");

     if (scope === "private") {
       // PRIVATE PROJECT
       ...
     } else {
       // PUBLIC PROJECT
       const publicKey = getPublicKey(userId, project.id);

-      const userInfo = await userPuter.auth.getUser();
       let username = userInfo?.username || userInfo?.name || null;

Comment on lines +79 to 117
router.get("/api/projects/get", async ({ request, user }) => {
try {
const mePuter = me.puter;
const userPuter = user.puter;

if (!id) return jsonError(400, "Project id required");
if (!userPuter) return jsonError(401, "Authentication required");

if (scope === "public") {
const mePuter = getMePuter(me);
if (!mePuter) return jsonError(500, "Missing deployer Puter context.");
const url = new URL(request.url);
const id = url.searchParams.get("id");
const scope = url.searchParams.get("scope") || "user";
const ownerId = url.searchParams.get("ownerId");

const publicKey = ownerId
? getPublicKey(ownerId, id)
: await findPublicKeyByProjectId(mePuter, id);
if (!id) return jsonError(400, "Project id required");

if (!publicKey) return jsonError(404, "Project not found");
if (scope === "private") {
// PRIVATE PROJECT
const key = `${PROJECT_PREFIX}${id}`;
const project = await userPuter.kv.get(key);
if (!project) return jsonError(404, "Project not found");

const project = await kvGetProject(mePuter.kv, publicKey);
if (!project) return jsonError(404, "Project not found");
return { project };
} else {
// PUBLIC PROJECT
const publicKey = ownerId
? getPublicKey(ownerId, id)
: await findPublicKeyByProjectId(mePuter, id);
if (!publicKey) return jsonError(404, "Project not found");

return { project };
}
const project = await mePuter.kv.get(publicKey);
if (!project) return jsonError(404, "Project not found");

const userPuter = getUserPuter(user);
if (!userPuter) return jsonError(401, "Authentication required");

const key = `${PROJECT_PREFIX}${id}`;
const project = await kvGetProject(userPuter.kv, key);
if (!project) return jsonError(404, "Project not found");
return { project };
return { project };
}
} catch (error) {
return jsonError(500, "Failed to get project", {
message: error?.message || "Unknown error",
});
}
});
Copy link

@coderabbitai coderabbitai bot Feb 11, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

rg -n -A 10 'getProjectById' --type=ts --type=js

Repository: JavaScript-Mastery-Pro/roomify

Length of output: 1905


🏁 Script executed:

sed -n '106,130p' lib/puter.action.ts

Repository: JavaScript-Mastery-Pro/roomify

Length of output: 743


Scope mismatch prevents private projects from being retrieved.

The frontend (visualizer.$id.tsx line 38) sends scope="user" for private projects and scope="public" for public projects via getProjectById (confirmed in lib/puter.action.ts line 125: &scope=${scope}). However, the backend endpoint at line 93 checks if (scope === "private"), which will never be true. This means the private project branch (lines 94–99) is unreachable, and all private project requests incorrectly fall through to the public lookup, causing them to fail.

Change line 93 from if (scope === "private") to if (scope === "user").

🤖 Prompt for AI Agents
In `@lib/puter.worker.js` around lines 79 - 117, The route handler in
router.get("/api/projects/get") incorrectly checks scope === "private", making
the private-project branch unreachable because the frontend sends scope="user"
for private projects; update the condition in that handler to check scope ===
"user" so the user/private lookup using userPuter.kv.get(PROJECT_PREFIX + id)
runs when appropriate (ensure the variables mePuter, userPuter, id, scope and
the PRIVATE branch logic remain unchanged).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

hmm, this might be true, although its a bit weird we have 2 different flags to determine private and public

like in our save, we have visibility private and public, while in get, we have public and user? @sujatagunale what do you think, should we just unify it?

Copy link

Choose a reason for hiding this comment

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

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

i'll let you decide on this 🙏

@sujatagunale sujatagunale merged commit 82c1408 into JavaScript-Mastery-Pro:main Feb 11, 2026
1 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants