@powersync/common 2.0.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,30 +2,29 @@ import { PowerSyncLogger } from '../utils/Logger.js';
2
2
  import { Transaction } from '../db/DBAdapter.js';
3
3
  import { AttachmentContext } from './AttachmentContext.js';
4
4
  import { AttachmentErrorHandler } from './AttachmentErrorHandler.js';
5
- import { AttachmentData, LocalStorageAdapter } from './LocalStorageAdapter.js';
5
+ import { AttachmentTransportAdapter } from './AttachmentTransportAdapter.js';
6
+ import { AttachmentData, LocalStorageAdapter, StreamingLocalStorageAdapter } from './LocalStorageAdapter.js';
6
7
  import { RemoteStorageAdapter } from './RemoteStorageAdapter.js';
7
8
  import { AttachmentRecord } from './Schema.js';
8
9
  import { WatchedAttachmentItem } from './WatchedAttachmentItem.js';
9
10
  import { CommonPowerSyncDatabase } from '../client/CommonPowerSyncDatabase.js';
10
11
  /**
11
- * Configuration options for {@link AttachmentQueue}.
12
+ * Fields common to every {@link AttachmentQueueOptions} variant.
12
13
  *
13
14
  * @experimental
14
15
  * @alpha This is currently experimental and may change without a major version bump.
15
16
  */
16
- export interface AttachmentQueueOptions {
17
+ export interface BaseAttachmentQueueOptions<TLocal extends LocalStorageAdapter = LocalStorageAdapter> {
17
18
  /**
18
19
  * PowerSync database instance
19
20
  */
20
21
  db: CommonPowerSyncDatabase;
21
22
  /**
22
- * Remote storage adapter for upload/download operations
23
- */
24
- remoteStorage: RemoteStorageAdapter;
25
- /**
26
- * Local storage adapter for file persistence
23
+ * Local storage adapter for file persistence. Its type determines whether
24
+ * {@link AttachmentQueue.saveFileFromUri} is available (a
25
+ * {@link StreamingLocalStorageAdapter} enables it).
27
26
  */
28
- localStorage: LocalStorageAdapter;
27
+ localStorage: TLocal;
29
28
  /**
30
29
  * Callback for monitoring attachment changes in your data model
31
30
  */
@@ -57,6 +56,48 @@ export interface AttachmentQueueOptions {
57
56
  /** Handler for upload, download and delete errors */
58
57
  errorHandler?: AttachmentErrorHandler;
59
58
  }
59
+ /**
60
+ * Configuration options for {@link AttachmentQueue}.
61
+ *
62
+ * Provide **exactly one** remote mechanism:
63
+ * - `remoteStorage` — a {@link RemoteStorageAdapter}, wrapped in the default
64
+ * default buffered transport that delegates upload/download/delete to it.
65
+ * - `transportAdapter` — an {@link AttachmentTransportAdapter} that owns all remote
66
+ * operations directly (e.g. a native file-URI implementation for buffer-free
67
+ * transfer of large files). No `remoteStorage` is needed in this case.
68
+ *
69
+ * Supplying both, or neither, is a type error.
70
+ *
71
+ * @experimental
72
+ * @alpha This is currently experimental and may change without a major version bump.
73
+ */
74
+ export type AttachmentQueueOptions<TLocal extends LocalStorageAdapter = LocalStorageAdapter> = BaseAttachmentQueueOptions<TLocal> & ({
75
+ remoteStorage: RemoteStorageAdapter;
76
+ transportAdapter?: never;
77
+ } | {
78
+ transportAdapter: AttachmentTransportAdapter;
79
+ remoteStorage?: never;
80
+ });
81
+ /**
82
+ * Fields shared by {@link AttachmentQueue.saveFile} and {@link AttachmentQueue.saveFileFromUri}.
83
+ *
84
+ * @alpha
85
+ */
86
+ export interface SaveAttachmentOptions {
87
+ /** File extension (e.g., 'jpg', 'pdf') */
88
+ fileExtension: string;
89
+ /** MIME type of the file (e.g., 'image/jpeg') */
90
+ mediaType?: string;
91
+ /** Optional metadata to associate with the attachment */
92
+ metaData?: string;
93
+ /** Optional custom ID. If not provided, a UUID will be generated */
94
+ id?: string;
95
+ /**
96
+ * Optional callback to execute additional database operations within the same transaction as the
97
+ * attachment creation.
98
+ */
99
+ updateHook?: (transaction: Transaction, attachment: AttachmentRecord) => Promise<void>;
100
+ }
60
101
  /**
61
102
  * AttachmentQueue manages the lifecycle and synchronization of attachments
62
103
  * between local and remote storage.
@@ -66,15 +107,13 @@ export interface AttachmentQueueOptions {
66
107
  * @experimental
67
108
  * @alpha This is currently experimental and may change without a major version bump.
68
109
  */
69
- export declare class AttachmentQueue {
110
+ export declare class AttachmentQueue<TLocal extends LocalStorageAdapter = LocalStorageAdapter> {
70
111
  /** Timer for periodic synchronization operations */
71
112
  private periodicSyncTimer?;
72
113
  /** Service for synchronizing attachments between local and remote storage */
73
114
  private readonly syncingService;
74
115
  /** Adapter for local file storage operations */
75
- readonly localStorage: LocalStorageAdapter;
76
- /** Adapter for remote file storage operations */
77
- readonly remoteStorage: RemoteStorageAdapter;
116
+ readonly localStorage: TLocal;
78
117
  /**
79
118
  * Callback function to watch for changes in attachment references in your data model.
80
119
  *
@@ -127,7 +166,7 @@ export declare class AttachmentQueue {
127
166
  *
128
167
  * @param options - Configuration options
129
168
  */
130
- constructor({ db, localStorage, remoteStorage, watchAttachments, logger, tableName, syncIntervalMs, syncThrottleDuration, downloadAttachments, archivedCacheLimit, errorHandler }: AttachmentQueueOptions);
169
+ constructor({ db, localStorage, remoteStorage, transportAdapter, watchAttachments, logger, tableName, syncIntervalMs, syncThrottleDuration, downloadAttachments, archivedCacheLimit, errorHandler }: AttachmentQueueOptions<TLocal>);
131
170
  /**
132
171
  * Generates a new attachment ID using a SQLite UUID function.
133
172
  *
@@ -171,37 +210,36 @@ export declare class AttachmentQueue {
171
210
  */
172
211
  withAttachmentContext<T>(callback: (context: AttachmentContext) => Promise<T>): Promise<T>;
173
212
  /**
174
- * Saves a file to local storage and queues it for upload to remote storage.
213
+ * Creates a `QUEUED_UPLOAD` attachment record, placing the file at the managed
214
+ * `localUri` from the given `source`, and persists the record
215
+ * alongside the caller's `updateHook` in a single transaction.
216
+ */
217
+ private createUploadAttachment;
218
+ /**
219
+ * Saves in-memory file data to local storage and queues it for upload.
175
220
  *
176
- * @param options - File save options
221
+ * @param options - File data plus {@link SaveAttachmentOptions}
177
222
  * @returns Promise resolving to the created attachment record
178
223
  */
179
- saveFile({ data, fileExtension, mediaType, metaData, id, updateHook }: {
180
- /**
181
- * The file data as ArrayBuffer, Blob, or base64 string
182
- */
224
+ saveFile(options: SaveAttachmentOptions & {
183
225
  data: AttachmentData;
184
- /**
185
- * File extension (e.g., 'jpg', 'pdf')
186
- */
187
- fileExtension: string;
188
- /**
189
- * MIME type of the file (e.g., 'image/jpeg')
190
- */
191
- mediaType?: string;
192
- /**
193
- * Optional metadata to associate with the attachment
194
- */
195
- metaData?: string;
196
- /**
197
- * Optional custom ID. If not provided, a UUID will be generated
198
- */
199
- id?: string;
200
- /**
201
- * Optional callback to execute additional database operations within the same transaction as the attachment
202
- * creation.
203
- */
204
- updateHook?: (transaction: Transaction, attachment: AttachmentRecord) => Promise<void>;
226
+ }): Promise<AttachmentRecord>;
227
+ /**
228
+ * Registers a file that already exists on disk and queues it for upload, moving it
229
+ * into managed storage without loading it into memory.
230
+ *
231
+ * Prefer this over {@link AttachmentQueue.saveFile} for large, app-originated files
232
+ * (recordings, videos): it avoids reading the file into an `ArrayBuffer` just to write
233
+ * it back to disk. Requires the local storage adapter to implement `moveFile`.
234
+ *
235
+ * Only available when the queue is configured with a {@link StreamingLocalStorageAdapter}
236
+ * (one that implements `moveFile`).
237
+ *
238
+ * @param options - The existing file's `localUri` plus {@link SaveAttachmentOptions}
239
+ * @returns Promise resolving to the created attachment record
240
+ */
241
+ saveFileFromUri(this: AttachmentQueue<StreamingLocalStorageAdapter>, options: SaveAttachmentOptions & {
242
+ localUri: string;
205
243
  }): Promise<AttachmentRecord>;
206
244
  deleteFile({ id, updateHook }: {
207
245
  id: string;
@@ -1,5 +1,6 @@
1
1
  import { LogLevels } from '../utils/Logger.js';
2
2
  import { AttachmentService } from './AttachmentService.js';
3
+ import { BufferedAttachmentTransport } from './BufferedAttachmentTransport.js';
3
4
  import { ATTACHMENT_TABLE, AttachmentState } from './Schema.js';
4
5
  import { SyncingService } from './SyncingService.js';
5
6
  /**
@@ -18,8 +19,6 @@ export class AttachmentQueue {
18
19
  syncingService;
19
20
  /** Adapter for local file storage operations */
20
21
  localStorage;
21
- /** Adapter for remote file storage operations */
22
- remoteStorage;
23
22
  /**
24
23
  * Callback function to watch for changes in attachment references in your data model.
25
24
  *
@@ -72,10 +71,9 @@ export class AttachmentQueue {
72
71
  *
73
72
  * @param options - Configuration options
74
73
  */
75
- constructor({ db, localStorage, remoteStorage, watchAttachments, logger, tableName = ATTACHMENT_TABLE, syncIntervalMs = 30 * 1000, syncThrottleDuration, downloadAttachments = true, archivedCacheLimit = 100, errorHandler }) {
74
+ constructor({ db, localStorage, remoteStorage, transportAdapter, watchAttachments, logger, tableName = ATTACHMENT_TABLE, syncIntervalMs = 30 * 1000, syncThrottleDuration, downloadAttachments = true, archivedCacheLimit = 100, errorHandler }) {
76
75
  this.db = db;
77
76
  this.syncLoopMutex = db.createMutex();
78
- this.remoteStorage = remoteStorage;
79
77
  this.localStorage = localStorage;
80
78
  this.watchAttachments = watchAttachments;
81
79
  this.tableName = tableName;
@@ -85,7 +83,8 @@ export class AttachmentQueue {
85
83
  this.downloadAttachments = downloadAttachments;
86
84
  this.logger = logger ?? db.logger;
87
85
  this.attachmentService = new AttachmentService(db, this.logger, tableName, archivedCacheLimit);
88
- this.syncingService = new SyncingService(this.attachmentService, localStorage, remoteStorage, this.logger, errorHandler);
86
+ const transport = transportAdapter ?? new BufferedAttachmentTransport(localStorage, remoteStorage);
87
+ this.syncingService = new SyncingService(this.attachmentService, localStorage, transport, this.logger, errorHandler);
89
88
  }
90
89
  /**
91
90
  * Generates a new attachment ID using a SQLite UUID function.
@@ -286,16 +285,27 @@ export class AttachmentQueue {
286
285
  return this.attachmentService.withContext(callback);
287
286
  }
288
287
  /**
289
- * Saves a file to local storage and queues it for upload to remote storage.
290
- *
291
- * @param options - File save options
292
- * @returns Promise resolving to the created attachment record
288
+ * Creates a `QUEUED_UPLOAD` attachment record, placing the file at the managed
289
+ * `localUri` from the given `source`, and persists the record
290
+ * alongside the caller's `updateHook` in a single transaction.
293
291
  */
294
- async saveFile({ data, fileExtension, mediaType, metaData, id, updateHook }) {
292
+ async createUploadAttachment({ fileExtension, mediaType, metaData, id, updateHook }, source) {
295
293
  const resolvedId = id ?? (await this.generateAttachmentId());
296
294
  const filename = `${resolvedId}.${fileExtension}`;
297
295
  const localUri = this.localStorage.getLocalUri(filename);
298
- const size = await this.localStorage.saveFile(localUri, data);
296
+ let size;
297
+ if (source.kind === 'data') {
298
+ size = await this.localStorage.saveFile(localUri, source.data);
299
+ }
300
+ else {
301
+ // saveFileFromUri is only exposed for streaming-capable local adapters; guard at
302
+ // runtime too for plain-JS callers.
303
+ const localStorage = this.localStorage;
304
+ if (!localStorage.moveFile) {
305
+ throw new Error('The configured local storage adapter does not support moveFile, required by saveFileFromUri.');
306
+ }
307
+ size = await localStorage.moveFile(source.localUri, localUri);
308
+ }
299
309
  const attachment = {
300
310
  id: resolvedId,
301
311
  filename,
@@ -315,6 +325,32 @@ export class AttachmentQueue {
315
325
  });
316
326
  return attachment;
317
327
  }
328
+ /**
329
+ * Saves in-memory file data to local storage and queues it for upload.
330
+ *
331
+ * @param options - File data plus {@link SaveAttachmentOptions}
332
+ * @returns Promise resolving to the created attachment record
333
+ */
334
+ async saveFile(options) {
335
+ return this.createUploadAttachment(options, { kind: 'data', data: options.data });
336
+ }
337
+ /**
338
+ * Registers a file that already exists on disk and queues it for upload, moving it
339
+ * into managed storage without loading it into memory.
340
+ *
341
+ * Prefer this over {@link AttachmentQueue.saveFile} for large, app-originated files
342
+ * (recordings, videos): it avoids reading the file into an `ArrayBuffer` just to write
343
+ * it back to disk. Requires the local storage adapter to implement `moveFile`.
344
+ *
345
+ * Only available when the queue is configured with a {@link StreamingLocalStorageAdapter}
346
+ * (one that implements `moveFile`).
347
+ *
348
+ * @param options - The existing file's `localUri` plus {@link SaveAttachmentOptions}
349
+ * @returns Promise resolving to the created attachment record
350
+ */
351
+ async saveFileFromUri(options) {
352
+ return this.createUploadAttachment(options, { kind: 'uri', localUri: options.localUri });
353
+ }
318
354
  async deleteFile({ id, updateHook }) {
319
355
  await this.attachmentService.withContext(async (ctx) => {
320
356
  const attachment = await ctx.getAttachment(id);
@@ -1 +1 @@
1
- {"version":3,"file":"AttachmentQueue.js","sourceRoot":"","sources":["../../src/attachments/AttachmentQueue.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AttachmentQueue.js","sourceRoot":"","sources":["../../src/attachments/AttachmentQueue.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ import { AttachmentRecord } from './Schema.js';
2
+ /**
3
+ * An {@link AttachmentRecord} that is guaranteed to have a `localUri`.
4
+ *
5
+ * The syncing service assigns `localUri` before invoking a transport download,
6
+ * so implementations always receive both the metadata and the destination path.
7
+ *
8
+ * @alpha
9
+ */
10
+ export type LocatedAttachmentRecord = AttachmentRecord & {
11
+ localUri: string;
12
+ };
13
+ /**
14
+ * AttachmentTransportAdapter owns all remote-side operations for an attachment —
15
+ * transfer (upload/download) and delete — as single operations.
16
+ *
17
+ * A transport owns the entire transfer, letting implementations pick the most
18
+ * efficient mechanism available (buffer, stream, or a platform-native file-URI
19
+ * upload/download API). On platforms like React Native this allows large files to
20
+ * be transferred without ever materializing them in the JS heap.
21
+ *
22
+ * The default transport composes the local and remote storage adapters. Provide a custom transport (via
23
+ * `AttachmentQueue`'s `transportAdapter` option) to own the whole remote side; in
24
+ * that case a separate `remoteStorage` is not required.
25
+ *
26
+ * @experimental
27
+ * @alpha This is currently experimental and may change without a major version bump.
28
+ */
29
+ export interface AttachmentTransportAdapter {
30
+ /**
31
+ * Uploads the attachment's local file to remote storage.
32
+ * @param attachment - The attachment to upload. `localUri` points at the source file.
33
+ */
34
+ upload(attachment: LocatedAttachmentRecord): Promise<void>;
35
+ /**
36
+ * Downloads the remote file into `attachment.localUri`.
37
+ * @param attachment - The attachment to download. `localUri` is the destination path,
38
+ * assigned by the syncing service before this call.
39
+ */
40
+ download(attachment: LocatedAttachmentRecord): Promise<void>;
41
+ /**
42
+ * Deletes the attachment's file from remote storage. Local file removal is handled
43
+ * separately by the syncing service.
44
+ * @param attachment - The attachment to delete.
45
+ */
46
+ delete(attachment: AttachmentRecord): Promise<void>;
47
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=AttachmentTransportAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AttachmentTransportAdapter.js","sourceRoot":"","sources":["../../src/attachments/AttachmentTransportAdapter.ts"],"names":[],"mappings":""}
@@ -0,0 +1,24 @@
1
+ import { AttachmentTransportAdapter, LocatedAttachmentRecord } from './AttachmentTransportAdapter.js';
2
+ import { LocalStorageAdapter } from './LocalStorageAdapter.js';
3
+ import { RemoteStorageAdapter } from './RemoteStorageAdapter.js';
4
+ import { AttachmentRecord } from './Schema.js';
5
+ /**
6
+ * Default {@link AttachmentTransportAdapter}, composing the local and remote
7
+ * storage adapters.
8
+ *
9
+ * The full file body is materialized as an `ArrayBuffer` in JS memory between the
10
+ * two adapter calls. This is fine for small files but can cause memory pressure on
11
+ * large ones — environments that support native transfer should provide a custom
12
+ * transport instead.
13
+ *
14
+ * @experimental
15
+ * @alpha This is currently experimental and may change without a major version bump.
16
+ */
17
+ export declare class BufferedAttachmentTransport implements AttachmentTransportAdapter {
18
+ private localStorage;
19
+ private remoteStorage;
20
+ constructor(localStorage: LocalStorageAdapter, remoteStorage: RemoteStorageAdapter);
21
+ upload(attachment: LocatedAttachmentRecord): Promise<void>;
22
+ download(attachment: LocatedAttachmentRecord): Promise<void>;
23
+ delete(attachment: AttachmentRecord): Promise<void>;
24
+ }
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Default {@link AttachmentTransportAdapter}, composing the local and remote
3
+ * storage adapters.
4
+ *
5
+ * The full file body is materialized as an `ArrayBuffer` in JS memory between the
6
+ * two adapter calls. This is fine for small files but can cause memory pressure on
7
+ * large ones — environments that support native transfer should provide a custom
8
+ * transport instead.
9
+ *
10
+ * @experimental
11
+ * @alpha This is currently experimental and may change without a major version bump.
12
+ */
13
+ export class BufferedAttachmentTransport {
14
+ localStorage;
15
+ remoteStorage;
16
+ constructor(localStorage, remoteStorage) {
17
+ this.localStorage = localStorage;
18
+ this.remoteStorage = remoteStorage;
19
+ }
20
+ async upload(attachment) {
21
+ const fileData = await this.localStorage.readFile(attachment.localUri);
22
+ await this.remoteStorage.uploadFile(fileData, attachment);
23
+ }
24
+ async download(attachment) {
25
+ const fileData = await this.remoteStorage.downloadFile(attachment);
26
+ await this.localStorage.saveFile(attachment.localUri, fileData);
27
+ }
28
+ async delete(attachment) {
29
+ await this.remoteStorage.deleteFile(attachment);
30
+ }
31
+ }
32
+ //# sourceMappingURL=BufferedAttachmentTransport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BufferedAttachmentTransport.js","sourceRoot":"","sources":["../../src/attachments/BufferedAttachmentTransport.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;GAWG;AACH,MAAM,OAAO,2BAA2B;IAE5B;IACA;IAFV,YACU,YAAiC,EACjC,aAAmC;QADnC,iBAAY,GAAZ,YAAY,CAAqB;QACjC,kBAAa,GAAb,aAAa,CAAsB;IAC1C,CAAC;IAEJ,KAAK,CAAC,MAAM,CAAC,UAAmC;QAC9C,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QACvE,MAAM,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IAC5D,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,UAAmC;QAChD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;QACnE,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,UAAU,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAClE,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,UAA4B;QACvC,MAAM,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;IAClD,CAAC;CACF"}
@@ -66,3 +66,22 @@ export interface LocalStorageAdapter {
66
66
  */
67
67
  getLocalUri(filename: string): string;
68
68
  }
69
+ /**
70
+ * A {@link LocalStorageAdapter} that can relocate a file into managed storage without
71
+ * loading it into memory. Required for {@link AttachmentQueue.saveFileFromUri}; only
72
+ * queues configured with a streaming-capable local adapter expose that method.
73
+ *
74
+ * @experimental
75
+ * @alpha This is currently experimental and may change without a major version bump.
76
+ */
77
+ export interface StreamingLocalStorageAdapter extends LocalStorageAdapter {
78
+ /**
79
+ * Moves a file into managed storage without loading it into memory.
80
+ * Overwrites any existing file at the target. When source and target are the same
81
+ * path, this is a no-op that just reports the size.
82
+ * @param sourceUri - Path of the existing file
83
+ * @param targetUri - Destination path within managed storage
84
+ * @returns Number of bytes in the moved file
85
+ */
86
+ moveFile(sourceUri: string, targetUri: string): Promise<number>;
87
+ }
@@ -1,7 +1,7 @@
1
1
  import { PowerSyncLogger } from '../utils/Logger.js';
2
2
  import { AttachmentService } from './AttachmentService.js';
3
+ import { AttachmentTransportAdapter } from './AttachmentTransportAdapter.js';
3
4
  import { LocalStorageAdapter } from './LocalStorageAdapter.js';
4
- import { RemoteStorageAdapter } from './RemoteStorageAdapter.js';
5
5
  import { AttachmentRecord } from './Schema.js';
6
6
  import { AttachmentErrorHandler } from './AttachmentErrorHandler.js';
7
7
  import { AttachmentContext } from './AttachmentContext.js';
@@ -9,15 +9,18 @@ import { AttachmentContext } from './AttachmentContext.js';
9
9
  * Orchestrates attachment synchronization between local and remote storage.
10
10
  * Handles uploads, downloads, deletions, and state transitions.
11
11
  *
12
+ * Remote operations (upload/download/delete) go through the {@link AttachmentTransportAdapter};
13
+ * local file operations use the {@link LocalStorageAdapter}.
14
+ *
12
15
  * @internal
13
16
  */
14
17
  export declare class SyncingService {
15
18
  private attachmentService;
16
19
  private localStorage;
17
- private remoteStorage;
20
+ private transport;
18
21
  private logger;
19
22
  private errorHandler?;
20
- constructor(attachmentService: AttachmentService, localStorage: LocalStorageAdapter, remoteStorage: RemoteStorageAdapter, logger: PowerSyncLogger, errorHandler?: AttachmentErrorHandler);
23
+ constructor(attachmentService: AttachmentService, localStorage: LocalStorageAdapter, transport: AttachmentTransportAdapter, logger: PowerSyncLogger, errorHandler?: AttachmentErrorHandler);
21
24
  /**
22
25
  * Processes attachments based on their state (upload, download, or delete).
23
26
  *
@@ -48,7 +51,7 @@ export declare class SyncingService {
48
51
  uploadAttachment(attachment: AttachmentRecord): Promise<AttachmentRecord>;
49
52
  /**
50
53
  * Downloads an attachment from remote storage to local storage.
51
- * Retrieves the file, converts to base64, and saves locally.
54
+ * The destination `localUri` is assigned here and the transport writes the file to it.
52
55
  * On success, marks as SYNCED. On failure, defers to error handler or archives.
53
56
  *
54
57
  * @param attachment - The attachment record to download
@@ -4,18 +4,21 @@ import { AttachmentState } from './Schema.js';
4
4
  * Orchestrates attachment synchronization between local and remote storage.
5
5
  * Handles uploads, downloads, deletions, and state transitions.
6
6
  *
7
+ * Remote operations (upload/download/delete) go through the {@link AttachmentTransportAdapter};
8
+ * local file operations use the {@link LocalStorageAdapter}.
9
+ *
7
10
  * @internal
8
11
  */
9
12
  export class SyncingService {
10
13
  attachmentService;
11
14
  localStorage;
12
- remoteStorage;
15
+ transport;
13
16
  logger;
14
17
  errorHandler;
15
- constructor(attachmentService, localStorage, remoteStorage, logger, errorHandler) {
18
+ constructor(attachmentService, localStorage, transport, logger, errorHandler) {
16
19
  this.attachmentService = attachmentService;
17
20
  this.localStorage = localStorage;
18
- this.remoteStorage = remoteStorage;
21
+ this.transport = transport;
19
22
  this.logger = logger;
20
23
  this.errorHandler = errorHandler;
21
24
  }
@@ -91,8 +94,7 @@ export class SyncingService {
91
94
  if (attachment.localUri == null) {
92
95
  throw new Error(`No localUri for attachment ${attachment.id}`);
93
96
  }
94
- const fileBlob = await this.localStorage.readFile(attachment.localUri);
95
- await this.remoteStorage.uploadFile(fileBlob, attachment);
97
+ await this.transport.upload({ ...attachment, localUri: attachment.localUri });
96
98
  return {
97
99
  ...attachment,
98
100
  state: AttachmentState.SYNCED,
@@ -112,7 +114,7 @@ export class SyncingService {
112
114
  }
113
115
  /**
114
116
  * Downloads an attachment from remote storage to local storage.
115
- * Retrieves the file, converts to base64, and saves locally.
117
+ * The destination `localUri` is assigned here and the transport writes the file to it.
116
118
  * On success, marks as SYNCED. On failure, defers to error handler or archives.
117
119
  *
118
120
  * @param attachment - The attachment record to download
@@ -121,9 +123,8 @@ export class SyncingService {
121
123
  async downloadAttachment(attachment) {
122
124
  this.logger.log({ level: LogLevels.info, message: `Downloading attachment ${attachment.filename}` });
123
125
  try {
124
- const fileData = await this.remoteStorage.downloadFile(attachment);
125
126
  const localUri = this.localStorage.getLocalUri(attachment.filename);
126
- await this.localStorage.saveFile(localUri, fileData);
127
+ await this.transport.download({ ...attachment, localUri });
127
128
  return {
128
129
  ...attachment,
129
130
  state: AttachmentState.SYNCED,
@@ -153,7 +154,7 @@ export class SyncingService {
153
154
  */
154
155
  async deleteAttachment(attachment, context) {
155
156
  try {
156
- await this.remoteStorage.deleteFile(attachment);
157
+ await this.transport.delete(attachment);
157
158
  if (attachment.localUri) {
158
159
  await this.localStorage.deleteFile(attachment.localUri);
159
160
  }
@@ -1 +1 @@
1
- {"version":3,"file":"SyncingService.js","sourceRoot":"","sources":["../../src/attachments/SyncingService.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SyncingService.js","sourceRoot":"","sources":["../../src/attachments/SyncingService.ts"],"names":[],"mappings":"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"}
@@ -307,7 +307,7 @@ export interface CommonPowerSyncDatabase extends BaseObserverInterface<PowerSync
307
307
  writeLock<T>(callback: (db: LockContext) => Promise<T>): Promise<T>;
308
308
  /**
309
309
  * Open a read-only transaction.
310
- * Read transactions can run concurrently to a write transaction.
310
+ * When multiple connections are available, read transactions can run concurrently to a write transaction.
311
311
  * Changes from any write transaction are not visible to read transactions started before it.
312
312
  *
313
313
  * @param callback - Function to execute within the transaction
package/lib/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export * from './attachments/AttachmentContext.js';
2
2
  export * from './attachments/AttachmentErrorHandler.js';
3
3
  export * from './attachments/AttachmentQueue.js';
4
+ export * from './attachments/AttachmentTransportAdapter.js';
4
5
  export * from './attachments/LocalStorageAdapter.js';
5
6
  export * from './attachments/RemoteStorageAdapter.js';
6
7
  export * from './attachments/Schema.js';
package/lib/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  export * from './attachments/AttachmentContext.js';
2
2
  export * from './attachments/AttachmentErrorHandler.js';
3
3
  export * from './attachments/AttachmentQueue.js';
4
+ export * from './attachments/AttachmentTransportAdapter.js';
4
5
  export * from './attachments/LocalStorageAdapter.js';
5
6
  export * from './attachments/RemoteStorageAdapter.js';
6
7
  export * from './attachments/Schema.js';
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,oCAAoC,CAAC;AACnD,cAAc,yCAAyC,CAAC;AACxD,cAAc,kCAAkC,CAAC;AACjD,cAAc,sCAAsC,CAAC;AACrD,cAAc,uCAAuC,CAAC;AACtD,cAAc,yBAAyB,CAAC;AACxC,cAAc,wCAAwC,CAAC;AAEvD,cAAc,qCAAqC,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAA+B,MAAM,kCAAkC,CAAC;AACrG,cAAc,kDAAkD,CAAC;AACjE,cAAc,6CAA6C,CAAC;AAC5D,cAAc,4BAA4B,CAAC;AAC3C,cAAc,mCAAmC,CAAC;AAClD,OAAO,EAAmB,UAAU,EAAE,MAAM,mCAAmC,CAAC;AAChF,cAAc,yCAAyC,CAAC;AACxD,cAAc,mCAAmC,CAAC;AAClD,cAAc,+BAA+B,CAAC;AAC9C,OAAO,EAAe,0BAA0B,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAGlG,cAAc,yBAAyB,CAAC;AACxC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,8BAA8B,CAAC;AAE7C,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AAErC,cAAc,mBAAmB,CAAC;AAClC,cAAc,kCAAkC,CAAC;AACjD,cAAc,qCAAqC,CAAC;AACpD,cAAc,iCAAiC,CAAC;AAChD,cAAc,4CAA4C,CAAC;AAC3D,cAAc,2DAA2D,CAAC;AAC1E,cAAc,uDAAuD,CAAC;AACtE,cAAc,kCAAkC,CAAC;AAGjD,cAAc,yBAAyB,CAAC;AACxC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,mBAAmB,CAAC;AAElC,cAAc,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,oCAAoC,CAAC;AACnD,cAAc,yCAAyC,CAAC;AACxD,cAAc,kCAAkC,CAAC;AACjD,cAAc,6CAA6C,CAAC;AAC5D,cAAc,sCAAsC,CAAC;AACrD,cAAc,uCAAuC,CAAC;AACtD,cAAc,yBAAyB,CAAC;AACxC,cAAc,wCAAwC,CAAC;AAEvD,cAAc,qCAAqC,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAA+B,MAAM,kCAAkC,CAAC;AACrG,cAAc,kDAAkD,CAAC;AACjE,cAAc,6CAA6C,CAAC;AAC5D,cAAc,4BAA4B,CAAC;AAC3C,cAAc,mCAAmC,CAAC;AAClD,OAAO,EAAmB,UAAU,EAAE,MAAM,mCAAmC,CAAC;AAChF,cAAc,yCAAyC,CAAC;AACxD,cAAc,mCAAmC,CAAC;AAClD,cAAc,+BAA+B,CAAC;AAC9C,OAAO,EAAe,0BAA0B,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAGlG,cAAc,yBAAyB,CAAC;AACxC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,8BAA8B,CAAC;AAE7C,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AAErC,cAAc,mBAAmB,CAAC;AAClC,cAAc,kCAAkC,CAAC;AACjD,cAAc,qCAAqC,CAAC;AACpD,cAAc,iCAAiC,CAAC;AAChD,cAAc,4CAA4C,CAAC;AAC3D,cAAc,2DAA2D,CAAC;AAC1E,cAAc,uDAAuD,CAAC;AACtE,cAAc,kCAAkC,CAAC;AAGjD,cAAc,yBAAyB,CAAC;AACxC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,mBAAmB,CAAC;AAElC,cAAc,kBAAkB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@powersync/common",
3
- "version": "2.0.0",
3
+ "version": "2.1.0",
4
4
  "publishConfig": {
5
5
  "registry": "https://registry.npmjs.org/",
6
6
  "access": "public"
@@ -5,7 +5,9 @@ import { Transaction } from '../db/DBAdapter.js';
5
5
  import { AttachmentContext } from './AttachmentContext.js';
6
6
  import { AttachmentErrorHandler } from './AttachmentErrorHandler.js';
7
7
  import { AttachmentService } from './AttachmentService.js';
8
- import { AttachmentData, LocalStorageAdapter } from './LocalStorageAdapter.js';
8
+ import { AttachmentTransportAdapter } from './AttachmentTransportAdapter.js';
9
+ import { BufferedAttachmentTransport } from './BufferedAttachmentTransport.js';
10
+ import { AttachmentData, LocalStorageAdapter, StreamingLocalStorageAdapter } from './LocalStorageAdapter.js';
9
11
  import { RemoteStorageAdapter } from './RemoteStorageAdapter.js';
10
12
  import { ATTACHMENT_TABLE, AttachmentRecord, AttachmentState } from './Schema.js';
11
13
  import { SyncingService } from './SyncingService.js';
@@ -13,24 +15,22 @@ import { WatchedAttachmentItem } from './WatchedAttachmentItem.js';
13
15
  import { CommonPowerSyncDatabase } from '../client/CommonPowerSyncDatabase.js';
14
16
 
15
17
  /**
16
- * Configuration options for {@link AttachmentQueue}.
18
+ * Fields common to every {@link AttachmentQueueOptions} variant.
17
19
  *
18
20
  * @experimental
19
21
  * @alpha This is currently experimental and may change without a major version bump.
20
22
  */
21
- export interface AttachmentQueueOptions {
23
+ export interface BaseAttachmentQueueOptions<TLocal extends LocalStorageAdapter = LocalStorageAdapter> {
22
24
  /**
23
25
  * PowerSync database instance
24
26
  */
25
27
  db: CommonPowerSyncDatabase;
26
28
  /**
27
- * Remote storage adapter for upload/download operations
28
- */
29
- remoteStorage: RemoteStorageAdapter;
30
- /**
31
- * Local storage adapter for file persistence
29
+ * Local storage adapter for file persistence. Its type determines whether
30
+ * {@link AttachmentQueue.saveFileFromUri} is available (a
31
+ * {@link StreamingLocalStorageAdapter} enables it).
32
32
  */
33
- localStorage: LocalStorageAdapter;
33
+ localStorage: TLocal;
34
34
  /**
35
35
  * Callback for monitoring attachment changes in your data model
36
36
  */
@@ -64,6 +64,52 @@ export interface AttachmentQueueOptions {
64
64
  errorHandler?: AttachmentErrorHandler;
65
65
  }
66
66
 
67
+ /**
68
+ * Configuration options for {@link AttachmentQueue}.
69
+ *
70
+ * Provide **exactly one** remote mechanism:
71
+ * - `remoteStorage` — a {@link RemoteStorageAdapter}, wrapped in the default
72
+ * default buffered transport that delegates upload/download/delete to it.
73
+ * - `transportAdapter` — an {@link AttachmentTransportAdapter} that owns all remote
74
+ * operations directly (e.g. a native file-URI implementation for buffer-free
75
+ * transfer of large files). No `remoteStorage` is needed in this case.
76
+ *
77
+ * Supplying both, or neither, is a type error.
78
+ *
79
+ * @experimental
80
+ * @alpha This is currently experimental and may change without a major version bump.
81
+ */
82
+ export type AttachmentQueueOptions<TLocal extends LocalStorageAdapter = LocalStorageAdapter> =
83
+ BaseAttachmentQueueOptions<TLocal> &
84
+ (
85
+ | { remoteStorage: RemoteStorageAdapter; transportAdapter?: never }
86
+ | { transportAdapter: AttachmentTransportAdapter; remoteStorage?: never }
87
+ );
88
+
89
+ /**
90
+ * Fields shared by {@link AttachmentQueue.saveFile} and {@link AttachmentQueue.saveFileFromUri}.
91
+ *
92
+ * @alpha
93
+ */
94
+ export interface SaveAttachmentOptions {
95
+ /** File extension (e.g., 'jpg', 'pdf') */
96
+ fileExtension: string;
97
+ /** MIME type of the file (e.g., 'image/jpeg') */
98
+ mediaType?: string;
99
+ /** Optional metadata to associate with the attachment */
100
+ metaData?: string;
101
+ /** Optional custom ID. If not provided, a UUID will be generated */
102
+ id?: string;
103
+ /**
104
+ * Optional callback to execute additional database operations within the same transaction as the
105
+ * attachment creation.
106
+ */
107
+ updateHook?: (transaction: Transaction, attachment: AttachmentRecord) => Promise<void>;
108
+ }
109
+
110
+ /** How the file bytes reach managed storage when creating an upload attachment. */
111
+ type AttachmentSource = { kind: 'data'; data: AttachmentData } | { kind: 'uri'; localUri: string };
112
+
67
113
  /**
68
114
  * AttachmentQueue manages the lifecycle and synchronization of attachments
69
115
  * between local and remote storage.
@@ -73,7 +119,7 @@ export interface AttachmentQueueOptions {
73
119
  * @experimental
74
120
  * @alpha This is currently experimental and may change without a major version bump.
75
121
  */
76
- export class AttachmentQueue {
122
+ export class AttachmentQueue<TLocal extends LocalStorageAdapter = LocalStorageAdapter> {
77
123
  /** Timer for periodic synchronization operations */
78
124
  private periodicSyncTimer?: ReturnType<typeof setInterval>;
79
125
 
@@ -81,10 +127,7 @@ export class AttachmentQueue {
81
127
  private readonly syncingService: SyncingService;
82
128
 
83
129
  /** Adapter for local file storage operations */
84
- readonly localStorage: LocalStorageAdapter;
85
-
86
- /** Adapter for remote file storage operations */
87
- readonly remoteStorage: RemoteStorageAdapter;
130
+ readonly localStorage: TLocal;
88
131
 
89
132
  /**
90
133
  * Callback function to watch for changes in attachment references in your data model.
@@ -159,6 +202,7 @@ export class AttachmentQueue {
159
202
  db,
160
203
  localStorage,
161
204
  remoteStorage,
205
+ transportAdapter,
162
206
  watchAttachments,
163
207
  logger,
164
208
  tableName = ATTACHMENT_TABLE,
@@ -167,10 +211,9 @@ export class AttachmentQueue {
167
211
  downloadAttachments = true,
168
212
  archivedCacheLimit = 100,
169
213
  errorHandler
170
- }: AttachmentQueueOptions) {
214
+ }: AttachmentQueueOptions<TLocal>) {
171
215
  this.db = db;
172
216
  this.syncLoopMutex = db.createMutex();
173
- this.remoteStorage = remoteStorage;
174
217
  this.localStorage = localStorage;
175
218
  this.watchAttachments = watchAttachments;
176
219
  this.tableName = tableName;
@@ -180,10 +223,13 @@ export class AttachmentQueue {
180
223
  this.downloadAttachments = downloadAttachments;
181
224
  this.logger = logger ?? db.logger;
182
225
  this.attachmentService = new AttachmentService(db, this.logger, tableName, archivedCacheLimit);
226
+
227
+ const transport = transportAdapter ?? new BufferedAttachmentTransport(localStorage, remoteStorage!);
228
+
183
229
  this.syncingService = new SyncingService(
184
230
  this.attachmentService,
185
231
  localStorage,
186
- remoteStorage,
232
+ transport,
187
233
  this.logger,
188
234
  errorHandler
189
235
  );
@@ -408,49 +454,30 @@ export class AttachmentQueue {
408
454
  return this.attachmentService.withContext(callback);
409
455
  }
410
456
  /**
411
- * Saves a file to local storage and queues it for upload to remote storage.
412
- *
413
- * @param options - File save options
414
- * @returns Promise resolving to the created attachment record
457
+ * Creates a `QUEUED_UPLOAD` attachment record, placing the file at the managed
458
+ * `localUri` from the given `source`, and persists the record
459
+ * alongside the caller's `updateHook` in a single transaction.
415
460
  */
416
- async saveFile({
417
- data,
418
- fileExtension,
419
- mediaType,
420
- metaData,
421
- id,
422
- updateHook
423
- }: {
424
- /**
425
- * The file data as ArrayBuffer, Blob, or base64 string
426
- */
427
- data: AttachmentData;
428
- /**
429
- * File extension (e.g., 'jpg', 'pdf')
430
- */
431
- fileExtension: string;
432
- /**
433
- * MIME type of the file (e.g., 'image/jpeg')
434
- */
435
- mediaType?: string;
436
- /**
437
- * Optional metadata to associate with the attachment
438
- */
439
- metaData?: string;
440
- /**
441
- * Optional custom ID. If not provided, a UUID will be generated
442
- */
443
- id?: string;
444
- /**
445
- * Optional callback to execute additional database operations within the same transaction as the attachment
446
- * creation.
447
- */
448
- updateHook?: (transaction: Transaction, attachment: AttachmentRecord) => Promise<void>;
449
- }): Promise<AttachmentRecord> {
461
+ private async createUploadAttachment(
462
+ { fileExtension, mediaType, metaData, id, updateHook }: SaveAttachmentOptions,
463
+ source: AttachmentSource
464
+ ): Promise<AttachmentRecord> {
450
465
  const resolvedId = id ?? (await this.generateAttachmentId());
451
466
  const filename = `${resolvedId}.${fileExtension}`;
452
467
  const localUri = this.localStorage.getLocalUri(filename);
453
- const size = await this.localStorage.saveFile(localUri, data);
468
+
469
+ let size: number;
470
+ if (source.kind === 'data') {
471
+ size = await this.localStorage.saveFile(localUri, source.data);
472
+ } else {
473
+ // saveFileFromUri is only exposed for streaming-capable local adapters; guard at
474
+ // runtime too for plain-JS callers.
475
+ const localStorage = this.localStorage as Partial<StreamingLocalStorageAdapter>;
476
+ if (!localStorage.moveFile) {
477
+ throw new Error('The configured local storage adapter does not support moveFile, required by saveFileFromUri.');
478
+ }
479
+ size = await localStorage.moveFile(source.localUri, localUri);
480
+ }
454
481
 
455
482
  const attachment: AttachmentRecord = {
456
483
  id: resolvedId,
@@ -474,6 +501,37 @@ export class AttachmentQueue {
474
501
  return attachment;
475
502
  }
476
503
 
504
+ /**
505
+ * Saves in-memory file data to local storage and queues it for upload.
506
+ *
507
+ * @param options - File data plus {@link SaveAttachmentOptions}
508
+ * @returns Promise resolving to the created attachment record
509
+ */
510
+ async saveFile(options: SaveAttachmentOptions & { data: AttachmentData }): Promise<AttachmentRecord> {
511
+ return this.createUploadAttachment(options, { kind: 'data', data: options.data });
512
+ }
513
+
514
+ /**
515
+ * Registers a file that already exists on disk and queues it for upload, moving it
516
+ * into managed storage without loading it into memory.
517
+ *
518
+ * Prefer this over {@link AttachmentQueue.saveFile} for large, app-originated files
519
+ * (recordings, videos): it avoids reading the file into an `ArrayBuffer` just to write
520
+ * it back to disk. Requires the local storage adapter to implement `moveFile`.
521
+ *
522
+ * Only available when the queue is configured with a {@link StreamingLocalStorageAdapter}
523
+ * (one that implements `moveFile`).
524
+ *
525
+ * @param options - The existing file's `localUri` plus {@link SaveAttachmentOptions}
526
+ * @returns Promise resolving to the created attachment record
527
+ */
528
+ async saveFileFromUri(
529
+ this: AttachmentQueue<StreamingLocalStorageAdapter>,
530
+ options: SaveAttachmentOptions & { localUri: string }
531
+ ): Promise<AttachmentRecord> {
532
+ return this.createUploadAttachment(options, { kind: 'uri', localUri: options.localUri });
533
+ }
534
+
477
535
  async deleteFile({
478
536
  id,
479
537
  updateHook
@@ -0,0 +1,49 @@
1
+ import { AttachmentRecord } from './Schema.js';
2
+
3
+ /**
4
+ * An {@link AttachmentRecord} that is guaranteed to have a `localUri`.
5
+ *
6
+ * The syncing service assigns `localUri` before invoking a transport download,
7
+ * so implementations always receive both the metadata and the destination path.
8
+ *
9
+ * @alpha
10
+ */
11
+ export type LocatedAttachmentRecord = AttachmentRecord & { localUri: string };
12
+
13
+ /**
14
+ * AttachmentTransportAdapter owns all remote-side operations for an attachment —
15
+ * transfer (upload/download) and delete — as single operations.
16
+ *
17
+ * A transport owns the entire transfer, letting implementations pick the most
18
+ * efficient mechanism available (buffer, stream, or a platform-native file-URI
19
+ * upload/download API). On platforms like React Native this allows large files to
20
+ * be transferred without ever materializing them in the JS heap.
21
+ *
22
+ * The default transport composes the local and remote storage adapters. Provide a custom transport (via
23
+ * `AttachmentQueue`'s `transportAdapter` option) to own the whole remote side; in
24
+ * that case a separate `remoteStorage` is not required.
25
+ *
26
+ * @experimental
27
+ * @alpha This is currently experimental and may change without a major version bump.
28
+ */
29
+ export interface AttachmentTransportAdapter {
30
+ /**
31
+ * Uploads the attachment's local file to remote storage.
32
+ * @param attachment - The attachment to upload. `localUri` points at the source file.
33
+ */
34
+ upload(attachment: LocatedAttachmentRecord): Promise<void>;
35
+
36
+ /**
37
+ * Downloads the remote file into `attachment.localUri`.
38
+ * @param attachment - The attachment to download. `localUri` is the destination path,
39
+ * assigned by the syncing service before this call.
40
+ */
41
+ download(attachment: LocatedAttachmentRecord): Promise<void>;
42
+
43
+ /**
44
+ * Deletes the attachment's file from remote storage. Local file removal is handled
45
+ * separately by the syncing service.
46
+ * @param attachment - The attachment to delete.
47
+ */
48
+ delete(attachment: AttachmentRecord): Promise<void>;
49
+ }
@@ -0,0 +1,37 @@
1
+ import { AttachmentTransportAdapter, LocatedAttachmentRecord } from './AttachmentTransportAdapter.js';
2
+ import { LocalStorageAdapter } from './LocalStorageAdapter.js';
3
+ import { RemoteStorageAdapter } from './RemoteStorageAdapter.js';
4
+ import { AttachmentRecord } from './Schema.js';
5
+
6
+ /**
7
+ * Default {@link AttachmentTransportAdapter}, composing the local and remote
8
+ * storage adapters.
9
+ *
10
+ * The full file body is materialized as an `ArrayBuffer` in JS memory between the
11
+ * two adapter calls. This is fine for small files but can cause memory pressure on
12
+ * large ones — environments that support native transfer should provide a custom
13
+ * transport instead.
14
+ *
15
+ * @experimental
16
+ * @alpha This is currently experimental and may change without a major version bump.
17
+ */
18
+ export class BufferedAttachmentTransport implements AttachmentTransportAdapter {
19
+ constructor(
20
+ private localStorage: LocalStorageAdapter,
21
+ private remoteStorage: RemoteStorageAdapter
22
+ ) {}
23
+
24
+ async upload(attachment: LocatedAttachmentRecord): Promise<void> {
25
+ const fileData = await this.localStorage.readFile(attachment.localUri);
26
+ await this.remoteStorage.uploadFile(fileData, attachment);
27
+ }
28
+
29
+ async download(attachment: LocatedAttachmentRecord): Promise<void> {
30
+ const fileData = await this.remoteStorage.downloadFile(attachment);
31
+ await this.localStorage.saveFile(attachment.localUri, fileData);
32
+ }
33
+
34
+ async delete(attachment: AttachmentRecord): Promise<void> {
35
+ await this.remoteStorage.deleteFile(attachment);
36
+ }
37
+ }
@@ -76,3 +76,23 @@ export interface LocalStorageAdapter {
76
76
  */
77
77
  getLocalUri(filename: string): string;
78
78
  }
79
+
80
+ /**
81
+ * A {@link LocalStorageAdapter} that can relocate a file into managed storage without
82
+ * loading it into memory. Required for {@link AttachmentQueue.saveFileFromUri}; only
83
+ * queues configured with a streaming-capable local adapter expose that method.
84
+ *
85
+ * @experimental
86
+ * @alpha This is currently experimental and may change without a major version bump.
87
+ */
88
+ export interface StreamingLocalStorageAdapter extends LocalStorageAdapter {
89
+ /**
90
+ * Moves a file into managed storage without loading it into memory.
91
+ * Overwrites any existing file at the target. When source and target are the same
92
+ * path, this is a no-op that just reports the size.
93
+ * @param sourceUri - Path of the existing file
94
+ * @param targetUri - Destination path within managed storage
95
+ * @returns Number of bytes in the moved file
96
+ */
97
+ moveFile(sourceUri: string, targetUri: string): Promise<number>;
98
+ }
@@ -1,7 +1,7 @@
1
1
  import { LogLevels, PowerSyncLogger } from '../utils/Logger.js';
2
2
  import { AttachmentService } from './AttachmentService.js';
3
+ import { AttachmentTransportAdapter } from './AttachmentTransportAdapter.js';
3
4
  import { LocalStorageAdapter } from './LocalStorageAdapter.js';
4
- import { RemoteStorageAdapter } from './RemoteStorageAdapter.js';
5
5
  import { AttachmentRecord, AttachmentState } from './Schema.js';
6
6
  import { AttachmentErrorHandler } from './AttachmentErrorHandler.js';
7
7
  import { AttachmentContext } from './AttachmentContext.js';
@@ -10,25 +10,28 @@ import { AttachmentContext } from './AttachmentContext.js';
10
10
  * Orchestrates attachment synchronization between local and remote storage.
11
11
  * Handles uploads, downloads, deletions, and state transitions.
12
12
  *
13
+ * Remote operations (upload/download/delete) go through the {@link AttachmentTransportAdapter};
14
+ * local file operations use the {@link LocalStorageAdapter}.
15
+ *
13
16
  * @internal
14
17
  */
15
18
  export class SyncingService {
16
19
  private attachmentService: AttachmentService;
17
20
  private localStorage: LocalStorageAdapter;
18
- private remoteStorage: RemoteStorageAdapter;
21
+ private transport: AttachmentTransportAdapter;
19
22
  private logger: PowerSyncLogger;
20
23
  private errorHandler?: AttachmentErrorHandler;
21
24
 
22
25
  constructor(
23
26
  attachmentService: AttachmentService,
24
27
  localStorage: LocalStorageAdapter,
25
- remoteStorage: RemoteStorageAdapter,
28
+ transport: AttachmentTransportAdapter,
26
29
  logger: PowerSyncLogger,
27
30
  errorHandler?: AttachmentErrorHandler
28
31
  ) {
29
32
  this.attachmentService = attachmentService;
30
33
  this.localStorage = localStorage;
31
- this.remoteStorage = remoteStorage;
34
+ this.transport = transport;
32
35
  this.logger = logger;
33
36
  this.errorHandler = errorHandler;
34
37
  }
@@ -114,8 +117,7 @@ export class SyncingService {
114
117
  throw new Error(`No localUri for attachment ${attachment.id}`);
115
118
  }
116
119
 
117
- const fileBlob = await this.localStorage.readFile(attachment.localUri);
118
- await this.remoteStorage.uploadFile(fileBlob, attachment);
120
+ await this.transport.upload({ ...attachment, localUri: attachment.localUri });
119
121
 
120
122
  return {
121
123
  ...attachment,
@@ -137,7 +139,7 @@ export class SyncingService {
137
139
 
138
140
  /**
139
141
  * Downloads an attachment from remote storage to local storage.
140
- * Retrieves the file, converts to base64, and saves locally.
142
+ * The destination `localUri` is assigned here and the transport writes the file to it.
141
143
  * On success, marks as SYNCED. On failure, defers to error handler or archives.
142
144
  *
143
145
  * @param attachment - The attachment record to download
@@ -146,10 +148,8 @@ export class SyncingService {
146
148
  async downloadAttachment(attachment: AttachmentRecord): Promise<AttachmentRecord> {
147
149
  this.logger.log({ level: LogLevels.info, message: `Downloading attachment ${attachment.filename}` });
148
150
  try {
149
- const fileData = await this.remoteStorage.downloadFile(attachment);
150
-
151
151
  const localUri = this.localStorage.getLocalUri(attachment.filename);
152
- await this.localStorage.saveFile(localUri, fileData);
152
+ await this.transport.download({ ...attachment, localUri });
153
153
 
154
154
  return {
155
155
  ...attachment,
@@ -181,7 +181,7 @@ export class SyncingService {
181
181
  */
182
182
  async deleteAttachment(attachment: AttachmentRecord, context: AttachmentContext): Promise<AttachmentRecord> {
183
183
  try {
184
- await this.remoteStorage.deleteFile(attachment);
184
+ await this.transport.delete(attachment);
185
185
  if (attachment.localUri) {
186
186
  await this.localStorage.deleteFile(attachment.localUri);
187
187
  }
@@ -343,7 +343,7 @@ export interface CommonPowerSyncDatabase extends BaseObserverInterface<PowerSync
343
343
 
344
344
  /**
345
345
  * Open a read-only transaction.
346
- * Read transactions can run concurrently to a write transaction.
346
+ * When multiple connections are available, read transactions can run concurrently to a write transaction.
347
347
  * Changes from any write transaction are not visible to read transactions started before it.
348
348
  *
349
349
  * @param callback - Function to execute within the transaction
package/src/index.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export * from './attachments/AttachmentContext.js';
2
2
  export * from './attachments/AttachmentErrorHandler.js';
3
3
  export * from './attachments/AttachmentQueue.js';
4
+ export * from './attachments/AttachmentTransportAdapter.js';
4
5
  export * from './attachments/LocalStorageAdapter.js';
5
6
  export * from './attachments/RemoteStorageAdapter.js';
6
7
  export * from './attachments/Schema.js';