fix(sidebar): prefetch folders and workspace permissions on cold load#5426
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
PR SummaryMedium Risk Overview
Exported Reviewed by Cursor Bugbot for commit 2a10b88. Configure here. |
Greptile SummaryThis PR fixes a cold-load flash in the sidebar where workflows appeared in a flat list briefly before jumping into the folder-grouped view, and where workspace-gated actions (like "New workflow") momentarily toggled after mount. It adds server-side prefetches for both the active folder list and workspace permissions, placing them alongside the already-prefetched workflow and chat lists.
Confidence Score: 5/5Safe to merge — the changes are additive prefetch calls and straightforward extractions of existing inline logic into shared helpers. The folder and permissions prefetch functions are backed by the same Drizzle queries the existing API routes use; the refactored GET permissions handler preserves the exact same access-control conditions and response shape as the original; and the exported stale-time constants keep the prefetch and client hooks in lock-step. No behavioral regressions were found. No files require special attention. Important Files Changed
Sequence Diagram%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant RSC as RSC Page (server)
participant PF as prefetchWorkspaceSidebar
participant DB as Database
RSC->>PF: prefetchWorkspaceSidebar(queryClient, workspaceId, userId)
PF->>DB: checkWorkspaceAccess (getWorkspaceWithOwner + getEffectiveWorkspacePermission)
DB-->>PF: access result
alt user cannot access workspace
PF-->>RSC: return (skip silently)
else user has access
par workflows
PF->>DB: listWorkflowsForUser
DB-->>PF: workflow rows → mapWorkflow[]
and chats
PF->>DB: listMothershipChats
DB-->>PF: chat rows → mapChat[]
and folders (NEW)
PF->>DB: listFoldersForWorkspace (active)
DB-->>PF: folder rows → FolderApi[] → mapFolder[]
and permissions (NEW)
PF->>DB: getWorkspacePermissionsForViewer
note over PF,DB: getWorkspaceWithOwner + getEffectiveWorkspacePermission + getUsersWithPermissions
DB-->>PF: WorkspacePermissionsForViewer
end
PF->>PF: queryClient.setQueryData for all 4 caches
PF-->>RSC: return (caches populated)
end
RSC->>RSC: dehydrate(queryClient) → HydrationBoundary
note over RSC: Client receives pre-populated cache — no flash
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant RSC as RSC Page (server)
participant PF as prefetchWorkspaceSidebar
participant DB as Database
RSC->>PF: prefetchWorkspaceSidebar(queryClient, workspaceId, userId)
PF->>DB: checkWorkspaceAccess (getWorkspaceWithOwner + getEffectiveWorkspacePermission)
DB-->>PF: access result
alt user cannot access workspace
PF-->>RSC: return (skip silently)
else user has access
par workflows
PF->>DB: listWorkflowsForUser
DB-->>PF: workflow rows → mapWorkflow[]
and chats
PF->>DB: listMothershipChats
DB-->>PF: chat rows → mapChat[]
and folders (NEW)
PF->>DB: listFoldersForWorkspace (active)
DB-->>PF: folder rows → FolderApi[] → mapFolder[]
and permissions (NEW)
PF->>DB: getWorkspacePermissionsForViewer
note over PF,DB: getWorkspaceWithOwner + getEffectiveWorkspacePermission + getUsersWithPermissions
DB-->>PF: WorkspacePermissionsForViewer
end
PF->>PF: queryClient.setQueryData for all 4 caches
PF-->>RSC: return (caches populated)
end
RSC->>RSC: dehydrate(queryClient) → HydrationBoundary
note over RSC: Client receives pre-populated cache — no flash
Reviews (2): Last reviewed commit: "fix(folders): reference FOLDER_LIST_STAL..." | Re-trigger Greptile |
…h repo convention
…plicating literal
|
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 2a10b88. Configure here.
…nstant (#5427) * refactor(react-query): hoist every staleTime into a named exported constant Adds a repo-wide convention (documented in .claude/rules/sim-queries.md, CLAUDE.md, and the react-query-best-practices skill/command) that every staleTime value must come from a named exported constant instead of an inline numeric literal. This prevents a server-side prefetch and its client hook from independently duplicating the same duration and drifting out of sync, which Greptile caught on PR #5426. Applies the convention across all of hooks/queries/** and their prefetch.ts consumers. * refactor(react-query): use FOLDER_LIST_STALE_TIME in folders.ts hooks useFolders and useFolderMap still used inline 60 * 1000 despite folders.ts already exporting FOLDER_LIST_STALE_TIME — the same prefetch-drift gap this refactor closes everywhere else. Same value, no behavior change.
…olders-permissions # Conflicts: # apps/sim/hooks/queries/workspace.ts
Summary
useFoldersresolved client-sidefolderKeys.list) toprefetchWorkspaceSidebar, backed by a newlistFoldersForWorkspaceserver-side query mirroring the existingGET /api/folderslogicworkspaceKeys.permissions) —WorkspaceHeader's permission-gated actions (e.g. "New workflow") were flipping shortly after mount for the same reason. Extracted the shared logic intogetWorkspacePermissionsForViewerinlib/workspaces/permissions/utils.tsso the route and the prefetch use one implementation instead of twoworkspaceKeys.list) — its route does invite-policy evaluation, org plan lookups, and first-run default-workspace creation side effects, not just a DB read. Duplicating that into the prefetch path would be a much larger, separate changeType of Change
Testing
bunx tsc --noEmitcleanbun run check:client-boundary,bun run check:react-queryboth passbunx biome checkclean on touched files/api/foldersand/api/workspaces/[id]/permissions(40 tests) pass unmodified against the refactored handlerChecklist