@@ -12,7 +12,7 @@ const {
1212 mockListFoldersForWorkspace,
1313 mockListInternalKnowledgeBases,
1414 mockListPinnedItemsForUser,
15- mockListTables ,
15+ mockPrefetchInternalJson ,
1616 mockListWorkspaceFileFolders,
1717 mockListWorkspaceFilesWithShares,
1818} = vi . hoisted ( ( ) => ( {
@@ -23,7 +23,7 @@ const {
2323 mockListFoldersForWorkspace : vi . fn ( ) ,
2424 mockListInternalKnowledgeBases : vi . fn ( ) ,
2525 mockListPinnedItemsForUser : vi . fn ( ) ,
26- mockListTables : vi . fn ( ) ,
26+ mockPrefetchInternalJson : vi . fn ( ) ,
2727 mockListWorkspaceFileFolders : vi . fn ( ) ,
2828 mockListWorkspaceFilesWithShares : vi . fn ( ) ,
2929} ) )
@@ -46,22 +46,8 @@ vi.mock('@/lib/pinned-items/queries', () => ({
4646vi . mock ( '@/lib/workspaces/permissions/utils' , ( ) => ( {
4747 getWorkspaceMemberProfiles : mockGetWorkspaceMemberProfiles ,
4848} ) )
49- /**
50- * The barrel is mocked rather than `@/lib/table/wire`, so the prefetch's real
51- * `toTableListItem` projection runs and the wire-shape assertions below are
52- * meaningful rather than mocked away.
53- */
54- vi . mock ( '@/lib/table' , ( ) => ( {
55- listTables : mockListTables ,
56- } ) )
57- /**
58- * `typeMetadataOf` is the one leaf of the real wire projection that reaches the
59- * column-type registry, and through it every type module's icon and editor. Stub
60- * that leaf only, so `toTableListItem`'s timestamp, `metadata`, and job
61- * normalization stay under test rather than being mocked away wholesale.
62- */
63- vi . mock ( '@/lib/table/column-types' , ( ) => ( {
64- typeMetadataOf : ( ) => ( { } ) ,
49+ vi . mock ( '@/app/workspace/[workspaceId]/lib/prefetch-internal-fetch' , ( ) => ( {
50+ prefetchInternalJson : mockPrefetchInternalJson ,
6551} ) )
6652vi . mock ( '@/lib/api/server/routes' , ( ) => ( {
6753 internalSessionAuth : { authenticate : mockAuthenticate } ,
@@ -104,7 +90,7 @@ describe('workspace list prefetches', () => {
10490 mockListWorkspaceFileFolders . mockResolvedValue ( [ ] )
10591 mockListPinnedItemsForUser . mockResolvedValue ( [ ] )
10692 mockGetWorkspaceMemberProfiles . mockResolvedValue ( [ ] )
107- mockListTables . mockResolvedValue ( [ ] )
93+ mockPrefetchInternalJson . mockResolvedValue ( { data : { tables : [ ] } } )
10894 mockAuthenticate . mockResolvedValue ( { kind : 'session' , userId : USER_ID , sessionId : 'sess-1' } )
10995 mockListInternalKnowledgeBases . mockResolvedValue ( { knowledgeBases : [ ] } )
11096 mockKnowledgePresenterList . mockReturnValue ( { success : true , data : [ ] } )
@@ -197,73 +183,24 @@ describe('workspace list prefetches', () => {
197183 } )
198184
199185 describe ( 'prefetchTables' , ( ) => {
200- const TABLE_ROW = {
201- id : 't-1' ,
202- name : 'people' ,
203- description : null ,
204- schema : { columns : [ { id : 'c1' , name : 'name' , type : 'string' } ] } ,
205- metadata : { columnWidths : { c1 : 120 } } ,
206- rowCount : 3 ,
207- maxRows : 10_000 ,
208- workspaceId : WORKSPACE_ID ,
209- folderId : null ,
210- createdBy : 'u-1' ,
211- locks : {
212- schemaLocked : false ,
213- insertLocked : false ,
214- updateLocked : false ,
215- deleteLocked : false ,
216- } ,
217- archivedAt : null ,
218- createdAt : new Date ( '2026-01-01T00:00:00.000Z' ) ,
219- updatedAt : new Date ( '2026-01-02T00:00:00.000Z' ) ,
220- }
221-
222- it ( 'reads tables from the data layer rather than over the wire' , async ( ) => {
223- mockListTables . mockResolvedValue ( [ TABLE_ROW ] )
224- const client = makeClient ( )
225-
226- await prefetchTables ( client , WORKSPACE_ID , USER_ID )
227-
228- expect ( mockListTables ) . toHaveBeenCalledWith ( WORKSPACE_ID , { scope : 'active' } )
229- } )
230-
231186 /**
232- * `listTablesContract`'s response schema is a passthrough `z.custom`, so a client fetch
233- * caches the route's JSON verbatim. Seeding the raw data-layer row would put `Date`s and
234- * the server-only `metadata` field under a key the hook never sees them on .
187+ * The tables list is the one read on this page still served over HTTP: `listTables` lives in
188+ * a module graph that reaches the executable tool registry, which
189+ * `check:tool-registry-boundary` refuses to let into a page graph .
235190 */
236- it ( 'seeds the wire shape a client fetch caches, not the raw data-layer row' , async ( ) => {
237- mockListTables . mockResolvedValue ( [ TABLE_ROW ] )
238- const client = makeClient ( )
239-
240- await prefetchTables ( client , WORKSPACE_ID , USER_ID )
241-
242- const [ cached ] = client . getQueryData ( tableKeys . list ( WORKSPACE_ID , 'active' ) ) as Array <
243- Record < string , unknown >
244- >
245- expect ( cached . createdAt ) . toBe ( '2026-01-01T00:00:00.000Z' )
246- expect ( cached . updatedAt ) . toBe ( '2026-01-02T00:00:00.000Z' )
247- expect ( cached . archivedAt ) . toBeNull ( )
248- expect ( cached ) . not . toHaveProperty ( 'metadata' )
249- expect ( cached . schema ) . toEqual ( {
250- columns : [ { id : 'c1' , name : 'name' , type : 'string' , required : false , unique : false } ] ,
251- } )
252- expect ( cached . jobStatus ) . toBeNull ( )
253- expect ( cached . jobRowsProcessed ) . toBe ( 0 )
254- } )
255-
256- it ( 'caches no tables when the viewer cannot be proved' , async ( ) => {
257- mockGetWorkspaceHostContextForViewer . mockResolvedValue ( null )
191+ it ( 'primes the exact key useTablesList reads and unwraps data.tables' , async ( ) => {
192+ const tables = [ { id : 't-1' } ]
193+ mockPrefetchInternalJson . mockResolvedValue ( { data : { tables } } )
258194 const client = makeClient ( )
259195
260196 await prefetchTables ( client , WORKSPACE_ID , USER_ID )
261197
262- expect ( mockListTables ) . not . toHaveBeenCalled ( )
263- expect ( client . getQueryData ( tableKeys . list ( WORKSPACE_ID , 'active' ) ) ) . toBeUndefined ( )
198+ expect ( mockPrefetchInternalJson ) . toHaveBeenCalledWith (
199+ `/api/table?workspaceId=${ WORKSPACE_ID } &scope=active`
200+ )
201+ expect ( client . getQueryData ( tableKeys . list ( WORKSPACE_ID , 'active' ) ) ) . toEqual ( tables )
264202 } )
265203 } )
266-
267204 describe ( 'prefetchFilesBrowser' , ( ) => {
268205 it ( 'primes the folder key the client hook reads' , async ( ) => {
269206 const folders = [ { id : 'folder-1' } ]
@@ -398,7 +335,7 @@ describe('workspace list prefetches', () => {
398335 const boom = new Error ( '500' )
399336 mockListWorkspaceFilesWithShares . mockRejectedValue ( boom )
400337 mockListFoldersForWorkspace . mockRejectedValue ( boom )
401- mockListTables . mockRejectedValue ( boom )
338+ mockPrefetchInternalJson . mockRejectedValue ( boom )
402339 mockListInternalKnowledgeBases . mockRejectedValue ( boom )
403340 mockListPinnedItemsForUser . mockRejectedValue ( boom )
404341 mockGetWorkspaceMemberProfiles . mockRejectedValue ( boom )
0 commit comments