@@ -6,11 +6,11 @@ import { listMothershipChats } from '@/lib/copilot/chat/list-mothership-chats'
66import { isChatEnabled } from '@/lib/core/config/env-flags'
77import { getUserProfile } from '@/lib/users/queries'
88import { listWorkflowsForUser } from '@/lib/workflows/queries'
9- import { listWorkspaceFilesWithShares } from '@/lib/workspace-files/queries'
109import { getWorkspaceHostContextForViewer } from '@/lib/workspaces/host-context'
1110import { listWorkspacesForViewer } from '@/lib/workspaces/list'
1211import { getWorkspacePermissionsForAuthorizedViewer } from '@/lib/workspaces/permissions/utils'
1312import { prefetchResourceFolders } from '@/app/workspace/[workspaceId]/lib/prefetch-resource-folders'
13+ import { seedWorkspaceFiles } from '@/app/workspace/[workspaceId]/lib/seed-workspace-files'
1414import {
1515 MOTHERSHIP_CHAT_LIST_STALE_TIME ,
1616 mapChat ,
@@ -25,7 +25,6 @@ import { workflowKeys } from '@/hooks/queries/utils/workflow-keys'
2525import { mapWorkflow , WORKFLOW_LIST_STALE_TIME } from '@/hooks/queries/utils/workflow-list-query'
2626import { normalizeWorkspacesResponse } from '@/hooks/queries/utils/workspace-list-query'
2727import { WORKSPACE_PERMISSIONS_STALE_TIME , workspaceKeys } from '@/hooks/queries/workspace'
28- import { workspaceFilesKeys } from '@/hooks/queries/workspace-files'
2928import {
3029 WORKSPACE_HOST_CONTEXT_STALE_TIME ,
3130 workspaceHostKeys ,
@@ -92,46 +91,6 @@ async function seedWorkspaceList(
9291 }
9392}
9493
95- /**
96- * How many files the layout is willing to inline into the document. Seeded on EVERY
97- * workspace route, so at ~500 bytes of JSON per file this budgets the entry at ~150 KB.
98- *
99- * A workspace above the budget seeds NOTHING rather than a prefix: the sidebar filters
100- * this list client-side, so a truncated seed would silently hide files.
101- */
102- export const WORKSPACE_FILE_SEED_MAX = 300
103-
104- /**
105- * Seeds the workspace's file list, which sidebar chrome registers on EVERY workspace
106- * route. It must be seeded HERE, not by the Files pages: `HydrationBoundary` defers a
107- * query the cache has already seen to a `useEffect`, which SSR never runs.
108- *
109- * Seeded rather than prefetched so it can decline to create an entry at all above
110- * {@link WORKSPACE_FILE_SEED_MAX} — `prefetchQuery` always creates one, and a partial
111- * entry would be read as the whole list. Parsed through the route's response contract.
112- */
113- async function seedWorkspaceFiles ( queryClient : QueryClient , workspaceId : string ) : Promise < void > {
114- try {
115- const files = await listWorkspaceFilesWithShares ( workspaceId , 'active' , {
116- maxRows : WORKSPACE_FILE_SEED_MAX ,
117- /**
118- * A failed read must reach the catch below, not degrade to an empty list: seeding
119- * `[]` would cache "this workspace has no files" as authoritative for the entry's
120- * lifetime, which is worse than seeding nothing and letting the client fetch.
121- */
122- throwOnError : true ,
123- } )
124- if ( ! files ) return
125- queryClient . setQueryData ( workspaceFilesKeys . list ( workspaceId , 'active' ) , files )
126- } catch ( error ) {
127- /** Optimization only: the client fetch reaches the route instead. Logged so drift between
128- * this read and the contract's response schema doesn't degrade silently into a waterfall. */
129- logger . warn ( 'Workspace file list seed failed; client will fetch' , {
130- error : getErrorMessage ( error ) ,
131- } )
132- }
133- }
134-
13594/**
13695 * Prefetches the sidebar's workflow, chat, folder, workspace-permissions,
13796 * workspace, and viewer-profile reads for a workspace and stores them under the
@@ -190,6 +149,14 @@ export async function prefetchWorkspaceSidebar(
190149 ]
191150 : [ ] ) ,
192151 prefetchResourceFolders ( queryClient , workspaceId , 'workflow' , userId ) ,
152+ /**
153+ * Seeded from the layout, not from the pages that render the list. `enabled: false` stops the
154+ * sidebar's query from FETCHING but not from registering: `useQuery` builds its observer
155+ * unconditionally, and the observer's constructor calls `queryCache.build()`, which adds the
156+ * key. `HydrationBoundary` then defers an already-registered query to a `useEffect` SSR never
157+ * runs — so only the first boundary to touch the key can reach the server render, and that is
158+ * this one.
159+ */
193160 seedWorkspaceFiles ( queryClient , workspaceId ) ,
194161 queryClient . prefetchQuery ( {
195162 queryKey : workspaceKeys . permissions ( workspaceId ) ,
0 commit comments