Skip to content

Commit 70087bf

Browse files
committed
refactor(files): trim restating comments and duplicate file-listing tests
Drops TSDoc that restated identifiers, tightens the list route's docs, and removes the integration test that re-checked the cursor validation the file-query unit test owns. The authorization test now asserts the forbidden code and that the read member gets files, and the rollup test reads the root stats once. The name-index plan test moves to the plan suite.
1 parent 41ce612 commit 70087bf

5 files changed

Lines changed: 15 additions & 68 deletions

File tree

‎apps/sim/app/api/workspaces/[id]/files/route.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import { readSortedCursor, writeSortedCursor } from '@/app/api/v2/lib/response'
2727

2828
export const dynamic = 'force-dynamic'
2929

30-
/** Every param that changes which files, in which order, a page walk returns. */
30+
/** The params besides the sort that change which files a page walk returns; the cursor is bound to them. */
3131
function fileCursorFilters(
3232
workspaceId: string,
3333
query: { scope: 'active' | 'archived'; folderId?: string | null }
@@ -40,7 +40,7 @@ function fileCursorFilters(
4040

4141
/**
4242
* GET /api/workspaces/[id]/files — List workspace files: one bounded page with `nextCursor`
43-
* when any paging param is sent, else the whole scope exactly as before paging existed.
43+
* when any paging param is sent, else the whole scope.
4444
*/
4545
export const GET = defineInternalJsonRoute({
4646
contract: listWorkspaceFilesContract,

‎apps/sim/lib/api/contracts/workspace-files.ts‎

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,8 @@ export const workspaceFileParamsSchema = workspaceFilesParamsSchema.extend({
3232
/** The fields a paged list sorts by: the v2 list's, which the shared keyset implements. */
3333
const WORKSPACE_FILE_SORT_FIELDS = ['name', 'size', 'uploadedAt', 'updatedAt'] as const
3434

35-
/** The largest page `GET /api/workspaces/[id]/files` serves when paging. */
3635
const MAX_WORKSPACE_FILE_PAGE_SIZE = 500
3736

38-
/** The page size a paged list request that omits `limit` gets. */
3937
export const DEFAULT_WORKSPACE_FILE_PAGE_SIZE = 100
4038

4139
/** A folder filter in the browser's addressing: `root` for the workspace root, else a folder id. */
@@ -45,7 +43,7 @@ const workspaceFileFolderFilterSchema = z
4543

4644
/**
4745
* The list's paging parameters. Sending any of them asks for one bounded page (default sort
48-
* `uploadedAt` ascending, the unpaged order, and 100 files) answered with `nextCursor`; sending
46+
* `uploadedAt` ascending, the unpaged order, and {@link DEFAULT_WORKSPACE_FILE_PAGE_SIZE} files) answered with `nextCursor`; sending
4947
* none keeps the unpaged response, which returns the whole scope.
5048
*/
5149
export const WORKSPACE_FILE_PAGE_PARAMS = [
@@ -212,7 +210,6 @@ const workspaceFileSuccessSchema = z.object({
212210
success: z.boolean(),
213211
})
214212

215-
/** The body every file-list read answers with. */
216213
const workspaceFilesResponseSchema = workspaceFileSuccessSchema.extend({
217214
files: z.array(workspaceFileRecordSchema),
218215
})
@@ -266,7 +263,6 @@ export const searchWorkspaceFilesContract = defineRouteContract({
266263
response: { mode: 'json', schema: workspaceFilesResponseSchema },
267264
})
268265

269-
/** The most entries each of a lookup's `ids`, `keys`, and `references` may carry. */
270266
const MAX_WORKSPACE_FILE_LOOKUP_ENTRIES = 100
271267

272268
const lookupEntriesSchema = (field: string) =>

‎apps/sim/lib/uploads/contexts/workspace/file-manager.ts‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1821,7 +1821,6 @@ export async function listWorkspaceFiles(
18211821
}
18221822
}
18231823

1824-
/** The column each timestamp sort orders on. */
18251824
const TIMESTAMP_SORT_COLUMNS = {
18261825
uploadedAt: workspaceFiles.uploadedAt,
18271826
updatedAt: workspaceFiles.updatedAt,

‎apps/sim/lib/workspace-files/__integration__/file-listing.integration.ts‎

Lines changed: 11 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
*/
66
import { db } from '@sim/db'
77
import { permissions, user, workspace, workspaceFiles } from '@sim/db/schema'
8-
import { explainCaptured } from '@sim/db/testing/explain'
98
import { assertDisposableTestDatabaseUrl } from '@sim/db/testing/test-infrastructure'
109
import { deleteWorkspaceFixture, insertWorkspaceFixture } from '@sim/db/testing/workspace-fixtures'
1110
import { generateId } from '@sim/utils/id'
@@ -175,11 +174,9 @@ describe('bounded workspace file reads in PostgreSQL', () => {
175174
INSERT INTO folder (id, name, user_id, workspace_id, resource_type, parent_id)
176175
VALUES (${folders.deep}, 'Deep', ${alice}, ${workspaceId}, 'file', ${folders.sub})`)
177176

178-
/**
179-
* Ties on every sort key: the same name in different folders, equal sizes, and timestamps
180-
* equal to the microsecond or distinct only below the millisecond — where ordering on the raw
181-
* column and ordering on its millisecond truncation disagree.
182-
*/
177+
// Ties on every sort key: the same name in different folders, equal sizes, and timestamps
178+
// equal to the microsecond or distinct only below the millisecond — where ordering on the raw
179+
// column and ordering on its millisecond truncation disagree.
183180
const t = '2026-03-01T10:00:00.123'
184181
for (const seed of [
185182
{
@@ -293,14 +290,6 @@ describe('bounded workspace file reads in PostgreSQL', () => {
293290
])
294291
expect([...firstPage.map((row) => row.id), ...resumed]).toEqual(legacyOrder)
295292
})
296-
297-
it('rejects a cursor value the sort cannot hold as a validation error', async () => {
298-
await expect(
299-
page({ sortBy: 'uploadedAt', after: ['not-a-date', 'wf_x'] })
300-
).rejects.toMatchObject({
301-
code: 'validation',
302-
})
303-
})
304293
})
305294

306295
describe('folder filters by id', () => {
@@ -358,45 +347,6 @@ describe('bounded workspace file reads in PostgreSQL', () => {
358347
})
359348
).rejects.toMatchObject({ code: 'validation' })
360349
})
361-
362-
/**
363-
* The folder predicate must be spelled on `coalesce(folder_id, '')`: that is the key the
364-
* `(workspace_id, coalesce(folder_id, ''), original_name)` index leads with, and a name-sorted
365-
* folder page that cannot seek it reads every live file the workspace holds.
366-
*/
367-
it('seeks the folder name index for a name-sorted root or folder page', async () => {
368-
await db.execute(sql`
369-
INSERT INTO ${workspaceFiles} (id, key, user_id, workspace_id, folder_id, context, original_name, content_type, size_bytes)
370-
SELECT 'wf_pad_' || n || '_' || ${workspaceId}, 'pad/' || n || '/' || ${workspaceId}, ${alice},
371-
${workspaceId}, CASE WHEN n % 2 = 0 THEN ${folders.media} END, 'workspace', 'pad-' || n || '.txt',
372-
'text/plain', 1
373-
FROM generate_series(1, 3000) AS n`)
374-
await db.execute(sql`ANALYZE ${workspaceFiles}`)
375-
try {
376-
for (const folderId of [null, folders.media]) {
377-
const nodes = await explainCaptured(
378-
db,
379-
() =>
380-
queryWorkspaceFiles(workspaceId, {
381-
folderId,
382-
sortBy: 'name',
383-
sortOrder: 'asc',
384-
limit: 50,
385-
after: ['pad-1500.txt', 'wf_x'],
386-
}),
387-
{ match: /order by/ }
388-
)
389-
const scan = nodes.find(
390-
(node) => node['Index Name'] === 'workspace_files_workspace_folder_name_active_unique'
391-
)
392-
expect(scan?.['Index Cond']).toMatch(/COALESCE\(folder_id.*original_name >=/)
393-
}
394-
} finally {
395-
await db.execute(
396-
sql`DELETE FROM ${workspaceFiles} WHERE id LIKE 'wf_pad_%' AND workspace_id = ${workspaceId}`
397-
)
398-
}
399-
})
400350
})
401351

402352
describe('name search', () => {
@@ -474,13 +424,14 @@ describe('bounded workspace file reads in PostgreSQL', () => {
474424
})
475425

476426
it('rolls each child folder subtree up, excluding deleted files', async () => {
477-
expect((await stats(null)).folders).toEqual(
427+
const atRoot = (await stats(null)).folders
428+
expect(atRoot).toHaveLength(2)
429+
expect(atRoot).toEqual(
478430
expect.arrayContaining([
479431
{ folderId: folders.docs, fileCount: 4, sizeBytes: 100 + 200 + 400 + 1000 },
480432
{ folderId: folders.media, fileCount: 1, sizeBytes: 50 },
481433
])
482434
)
483-
expect((await stats(null)).folders).toHaveLength(2)
484435
expect((await stats(folders.docs)).folders).toEqual([
485436
{ folderId: folders.sub, fileCount: 2, sizeBytes: 1400 },
486437
])
@@ -495,20 +446,21 @@ describe('bounded workspace file reads in PostgreSQL', () => {
495446

496447
describe('authorization', () => {
497448
it('serves a read member and refuses a non-member on every read', async () => {
498-
await expect(page({}, { userId: bob })).resolves.toBeDefined()
499-
await expect(page({}, { userId: carol })).rejects.toBeDefined()
449+
expect((await page({}, { userId: bob })).files).toHaveLength(files.length)
450+
const refused = { code: 'forbidden' }
451+
await expect(page({}, { userId: carol })).rejects.toMatchObject(refused)
500452
await expect(
501453
lookupWorkspaceFiles.execute({
502454
principal: session(carol),
503455
input: { workspaceId, ids: ['wf_x'] },
504456
})
505-
).rejects.toBeDefined()
457+
).rejects.toMatchObject(refused)
506458
await expect(
507459
getWorkspaceFileFolderStats.execute({
508460
principal: session(carol),
509461
input: { workspaceId, parentId: null },
510462
})
511-
).rejects.toBeDefined()
463+
).rejects.toMatchObject(refused)
512464
})
513465
})
514466
})

‎apps/sim/lib/workspace-files/application/list-workspace-files.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ export const getWorkspaceFileFolderStats = defineAuthorizedWorkspaceFileUseCase(
187187
return { folders: [] }
188188
}
189189
const rows = [...folderIndex.rowById.values()]
190-
/** One child index for every subtree: `resolveFolderScope` would rebuild it per child. */
190+
// One child index for every subtree: `resolveFolderScope` would rebuild it per child.
191191
const childrenByParent = indexFolderChildren(rows)
192192
const subtrees = rows
193193
.filter((row) => (row.parentId ?? null) === input.parentId)

0 commit comments

Comments
 (0)