( options: FileMetadataInsertOptions )
| 27 | * Handles duplicate key errors gracefully by returning existing record |
| 28 | */ |
| 29 | export async function insertFileMetadata( |
| 30 | options: FileMetadataInsertOptions |
| 31 | ): Promise<FileMetadataRecord> { |
| 32 | const { key, userId, workspaceId, context, originalName, contentType, size, folderId, id } = |
| 33 | options |
| 34 | |
| 35 | const existingDeleted = await db |
| 36 | .select() |
| 37 | .from(workspaceFiles) |
| 38 | .where(eq(workspaceFiles.key, key)) |
| 39 | .limit(1) |
| 40 | |
| 41 | if (existingDeleted.length > 0 && existingDeleted[0].deletedAt) { |
| 42 | const [restored] = await db |
| 43 | .update(workspaceFiles) |
| 44 | .set({ |
| 45 | userId, |
| 46 | workspaceId: workspaceId || null, |
| 47 | folderId: folderId ?? null, |
| 48 | context, |
| 49 | originalName, |
| 50 | displayName: originalName, |
| 51 | contentType, |
| 52 | size, |
| 53 | deletedAt: null, |
| 54 | uploadedAt: new Date(), |
| 55 | }) |
| 56 | .where(eq(workspaceFiles.id, existingDeleted[0].id)) |
| 57 | .returning() |
| 58 | |
| 59 | if (restored) { |
| 60 | return restored |
| 61 | } |
| 62 | } |
| 63 | |
| 64 | const existing = await db |
| 65 | .select() |
| 66 | .from(workspaceFiles) |
| 67 | .where(and(eq(workspaceFiles.key, key), isNull(workspaceFiles.deletedAt))) |
| 68 | .limit(1) |
| 69 | |
| 70 | if (existing.length > 0) { |
| 71 | return existing[0] |
| 72 | } |
| 73 | |
| 74 | const fileId = id || generateId() |
| 75 | |
| 76 | try { |
| 77 | const [inserted] = await db |
| 78 | .insert(workspaceFiles) |
| 79 | .values({ |
| 80 | id: fileId, |
| 81 | key, |
| 82 | userId, |
| 83 | workspaceId: workspaceId || null, |
| 84 | folderId: folderId ?? null, |
| 85 | context, |
| 86 | originalName, |
no test coverage detected