diff --git a/.changeset/fuzzy-cameras-sip.md b/.changeset/fuzzy-cameras-sip.md new file mode 100644 index 000000000..e1d7a2f7f --- /dev/null +++ b/.changeset/fuzzy-cameras-sip.md @@ -0,0 +1,5 @@ +--- +'@powersync/common': patch +--- + +Allow watched attachment items to provide a media type for queued downloads. diff --git a/packages/common/src/attachments/AttachmentQueue.ts b/packages/common/src/attachments/AttachmentQueue.ts index 59fa299be..9be3e41a8 100644 --- a/packages/common/src/attachments/AttachmentQueue.ts +++ b/packages/common/src/attachments/AttachmentQueue.ts @@ -228,6 +228,7 @@ export class AttachmentQueue { state: AttachmentState.QUEUED_DOWNLOAD, hasSynced: false, metaData: watchedAttachment.metaData, + mediaType: watchedAttachment.mediaType, timestamp: new Date().getTime() }); continue; diff --git a/packages/common/src/attachments/README.md b/packages/common/src/attachments/README.md index ea2678dba..182640de3 100644 --- a/packages/common/src/attachments/README.md +++ b/packages/common/src/attachments/README.md @@ -427,10 +427,12 @@ type WatchedAttachmentItem = { id: string; fileExtension: string; // e.g., 'jpg', 'pdf' metaData?: string; + mediaType?: string; // e.g., 'image/jpeg' } | { id: string; filename: string; // e.g., 'document.pdf' metaData?: string; + mediaType?: string; // e.g., 'application/pdf' }; ``` diff --git a/packages/common/src/attachments/WatchedAttachmentItem.ts b/packages/common/src/attachments/WatchedAttachmentItem.ts index f73326511..cc0263058 100644 --- a/packages/common/src/attachments/WatchedAttachmentItem.ts +++ b/packages/common/src/attachments/WatchedAttachmentItem.ts @@ -10,10 +10,12 @@ export type WatchedAttachmentItem = filename: string; fileExtension?: never; metaData?: string; + mediaType?: string; } | { id: string; fileExtension: string; filename?: never; metaData?: string; + mediaType?: string; }; diff --git a/packages/node/tests/attachments.test.ts b/packages/node/tests/attachments.test.ts index 15766a7f0..7847f17d8 100644 --- a/packages/node/tests/attachments.test.ts +++ b/packages/node/tests/attachments.test.ts @@ -214,6 +214,67 @@ describe('attachment queue', () => { } ); + it( + 'should pass watched media type to downloaded attachments', + { + timeout: 10000 + }, + async () => { + queue = new AttachmentQueue({ + db, + watchAttachments: (onUpdate) => { + db.watch( + /* sql */ + ` + SELECT + photo_id + FROM + users + WHERE + photo_id IS NOT NULL + `, + [], + { + onResult: async (result: any) => + await onUpdate( + result.rows?._array.map((r: any) => ({ + id: r.photo_id, + fileExtension: 'jpg', + mediaType: 'image/jpeg' + })) ?? [] + ) + } + ); + }, + remoteStorage: mockRemoteStorage, + localStorage: mockLocalStorage, + syncIntervalMs: INTERVAL_MILLISECONDS, + archivedCacheLimit: 0 + }); + + await queue.startSync(); + + const id = await queue.generateAttachmentId(); + await db.execute('INSERT INTO users (id, name, email, photo_id) VALUES (uuid(), ?, ?, ?)', [ + 'testuser', + 'testuser@journeyapps.com', + id + ]); + + const attachments = await waitForMatchCondition( + () => watchAttachmentsTable(), + (results) => results.some((r) => r.id === id && r.state === AttachmentState.SYNCED), + 5 + ); + + const attachmentRecord = attachments.find((r) => r.id === id); + expect(attachmentRecord?.mediaType).toBe('image/jpeg'); + expect(mockDownloadFile).toHaveBeenCalledWith(expect.objectContaining({ mediaType: 'image/jpeg' })); + + await queue.stopSync(); + } + ); + it( 'should upload attachments when a new file is saved', {