@powersync/common 1.46.0 → 1.47.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.
Files changed (55) hide show
  1. package/README.md +5 -1
  2. package/dist/bundle.cjs +1266 -360
  3. package/dist/bundle.cjs.map +1 -1
  4. package/dist/bundle.mjs +1259 -361
  5. package/dist/bundle.mjs.map +1 -1
  6. package/dist/bundle.node.cjs +1266 -360
  7. package/dist/bundle.node.cjs.map +1 -1
  8. package/dist/bundle.node.mjs +1259 -361
  9. package/dist/bundle.node.mjs.map +1 -1
  10. package/dist/index.d.cts +530 -29
  11. package/lib/attachments/AttachmentContext.d.ts +86 -0
  12. package/lib/attachments/AttachmentContext.js +229 -0
  13. package/lib/attachments/AttachmentContext.js.map +1 -0
  14. package/lib/attachments/AttachmentErrorHandler.d.ts +31 -0
  15. package/lib/attachments/AttachmentErrorHandler.js +2 -0
  16. package/lib/attachments/AttachmentErrorHandler.js.map +1 -0
  17. package/lib/attachments/AttachmentQueue.d.ts +149 -0
  18. package/lib/attachments/AttachmentQueue.js +362 -0
  19. package/lib/attachments/AttachmentQueue.js.map +1 -0
  20. package/lib/attachments/AttachmentService.d.ts +29 -0
  21. package/lib/attachments/AttachmentService.js +56 -0
  22. package/lib/attachments/AttachmentService.js.map +1 -0
  23. package/lib/attachments/LocalStorageAdapter.d.ts +62 -0
  24. package/lib/attachments/LocalStorageAdapter.js +6 -0
  25. package/lib/attachments/LocalStorageAdapter.js.map +1 -0
  26. package/lib/attachments/RemoteStorageAdapter.d.ts +27 -0
  27. package/lib/attachments/RemoteStorageAdapter.js +2 -0
  28. package/lib/attachments/RemoteStorageAdapter.js.map +1 -0
  29. package/lib/attachments/Schema.d.ts +50 -0
  30. package/lib/attachments/Schema.js +62 -0
  31. package/lib/attachments/Schema.js.map +1 -0
  32. package/lib/attachments/SyncingService.d.ts +62 -0
  33. package/lib/attachments/SyncingService.js +168 -0
  34. package/lib/attachments/SyncingService.js.map +1 -0
  35. package/lib/attachments/WatchedAttachmentItem.d.ts +17 -0
  36. package/lib/attachments/WatchedAttachmentItem.js +2 -0
  37. package/lib/attachments/WatchedAttachmentItem.js.map +1 -0
  38. package/lib/index.d.ts +10 -0
  39. package/lib/index.js +10 -0
  40. package/lib/index.js.map +1 -1
  41. package/lib/utils/mutex.d.ts +1 -1
  42. package/lib/utils/mutex.js.map +1 -1
  43. package/package.json +1 -1
  44. package/src/attachments/AttachmentContext.ts +279 -0
  45. package/src/attachments/AttachmentErrorHandler.ts +34 -0
  46. package/src/attachments/AttachmentQueue.ts +472 -0
  47. package/src/attachments/AttachmentService.ts +62 -0
  48. package/src/attachments/LocalStorageAdapter.ts +72 -0
  49. package/src/attachments/README.md +718 -0
  50. package/src/attachments/RemoteStorageAdapter.ts +30 -0
  51. package/src/attachments/Schema.ts +87 -0
  52. package/src/attachments/SyncingService.ts +193 -0
  53. package/src/attachments/WatchedAttachmentItem.ts +19 -0
  54. package/src/index.ts +11 -0
  55. package/src/utils/mutex.ts +1 -1
@@ -0,0 +1,362 @@
1
+ import { DEFAULT_WATCH_THROTTLE_MS } from '../client/watched/WatchedQuery.js';
2
+ import { ATTACHMENT_TABLE, AttachmentState } from './Schema.js';
3
+ import { SyncingService } from './SyncingService.js';
4
+ import { AttachmentService } from './AttachmentService.js';
5
+ /**
6
+ * AttachmentQueue manages the lifecycle and synchronization of attachments
7
+ * between local and remote storage.
8
+ * Provides automatic synchronization, upload/download queuing, attachment monitoring,
9
+ * verification and repair of local files, and cleanup of archived attachments.
10
+ *
11
+ * @experimental
12
+ * @alpha This is currently experimental and may change without a major version bump.
13
+ */
14
+ export class AttachmentQueue {
15
+ /** Timer for periodic synchronization operations */
16
+ periodicSyncTimer;
17
+ /** Service for synchronizing attachments between local and remote storage */
18
+ syncingService;
19
+ /** Adapter for local file storage operations */
20
+ localStorage;
21
+ /** Adapter for remote file storage operations */
22
+ remoteStorage;
23
+ /**
24
+ * Callback function to watch for changes in attachment references in your data model.
25
+ *
26
+ * This should be implemented by the user of AttachmentQueue to monitor changes in your application's
27
+ * data that reference attachments. When attachments are added, removed, or modified,
28
+ * this callback should trigger the onUpdate function with the current set of attachments.
29
+ */
30
+ watchAttachments;
31
+ /** Name of the database table storing attachment records */
32
+ tableName;
33
+ /** Logger instance for diagnostic information */
34
+ logger;
35
+ /** Interval in milliseconds between periodic sync operations. Default: 30000 (30 seconds) */
36
+ syncIntervalMs = 30 * 1000;
37
+ /** Duration in milliseconds to throttle sync operations */
38
+ syncThrottleDuration;
39
+ /** Whether to automatically download remote attachments. Default: true */
40
+ downloadAttachments = true;
41
+ /** Maximum number of archived attachments to keep before cleanup. Default: 100 */
42
+ archivedCacheLimit;
43
+ /** Service for managing attachment-related database operations */
44
+ attachmentService;
45
+ /** PowerSync database instance */
46
+ db;
47
+ /** Cleanup function for status change listener */
48
+ statusListenerDispose;
49
+ watchActiveAttachments;
50
+ watchAttachmentsAbortController;
51
+ /**
52
+ * Creates a new AttachmentQueue instance.
53
+ *
54
+ * @param options - Configuration options
55
+ * @param options.db - PowerSync database instance
56
+ * @param options.remoteStorage - Remote storage adapter for upload/download operations
57
+ * @param options.localStorage - Local storage adapter for file persistence
58
+ * @param options.watchAttachments - Callback for monitoring attachment changes in your data model
59
+ * @param options.tableName - Name of the table to store attachment records. Default: 'ps_attachment_queue'
60
+ * @param options.logger - Logger instance. Defaults to db.logger
61
+ * @param options.syncIntervalMs - Interval between automatic syncs in milliseconds. Default: 30000
62
+ * @param options.syncThrottleDuration - Throttle duration for sync operations in milliseconds. Default: 1000
63
+ * @param options.downloadAttachments - Whether to automatically download remote attachments. Default: true
64
+ * @param options.archivedCacheLimit - Maximum archived attachments before cleanup. Default: 100
65
+ */
66
+ constructor({ db, localStorage, remoteStorage, watchAttachments, logger, tableName = ATTACHMENT_TABLE, syncIntervalMs = 30 * 1000, syncThrottleDuration = DEFAULT_WATCH_THROTTLE_MS, downloadAttachments = true, archivedCacheLimit = 100, errorHandler }) {
67
+ this.db = db;
68
+ this.remoteStorage = remoteStorage;
69
+ this.localStorage = localStorage;
70
+ this.watchAttachments = watchAttachments;
71
+ this.tableName = tableName;
72
+ this.syncIntervalMs = syncIntervalMs;
73
+ this.syncThrottleDuration = syncThrottleDuration;
74
+ this.archivedCacheLimit = archivedCacheLimit;
75
+ this.downloadAttachments = downloadAttachments;
76
+ this.logger = logger ?? db.logger;
77
+ this.attachmentService = new AttachmentService(db, this.logger, tableName, archivedCacheLimit);
78
+ this.syncingService = new SyncingService(this.attachmentService, localStorage, remoteStorage, this.logger, errorHandler);
79
+ }
80
+ /**
81
+ * Generates a new attachment ID using a SQLite UUID function.
82
+ *
83
+ * @returns Promise resolving to the new attachment ID
84
+ */
85
+ async generateAttachmentId() {
86
+ return this.db.get('SELECT uuid() as id').then((row) => row.id);
87
+ }
88
+ /**
89
+ * Starts the attachment synchronization process.
90
+ *
91
+ * This method:
92
+ * - Stops any existing sync operations
93
+ * - Sets up periodic synchronization based on syncIntervalMs
94
+ * - Registers listeners for active attachment changes
95
+ * - Processes watched attachments to queue uploads/downloads
96
+ * - Handles state transitions for archived and new attachments
97
+ */
98
+ async startSync() {
99
+ await this.stopSync();
100
+ this.watchActiveAttachments = this.attachmentService.watchActiveAttachments({
101
+ throttleMs: this.syncThrottleDuration
102
+ });
103
+ // immediately invoke the sync storage to initialize local storage
104
+ await this.localStorage.initialize();
105
+ await this.verifyAttachments();
106
+ // Sync storage periodically
107
+ this.periodicSyncTimer = setInterval(async () => {
108
+ await this.syncStorage();
109
+ }, this.syncIntervalMs);
110
+ // Sync storage when there is a change in active attachments
111
+ this.watchActiveAttachments.registerListener({
112
+ onDiff: async () => {
113
+ await this.syncStorage();
114
+ }
115
+ });
116
+ this.statusListenerDispose = this.db.registerListener({
117
+ statusChanged: (status) => {
118
+ if (status.connected) {
119
+ // Device came online, process attachments immediately
120
+ this.syncStorage().catch((error) => {
121
+ this.logger.error('Error syncing storage on connection:', error);
122
+ });
123
+ }
124
+ }
125
+ });
126
+ this.watchAttachmentsAbortController = new AbortController();
127
+ const signal = this.watchAttachmentsAbortController.signal;
128
+ // Process attachments when there is a change in watched attachments
129
+ this.watchAttachments(async (watchedAttachments) => {
130
+ // Skip processing if sync has been stopped
131
+ if (signal.aborted) {
132
+ return;
133
+ }
134
+ await this.attachmentService.withContext(async (ctx) => {
135
+ // Need to get all the attachments which are tracked in the DB.
136
+ // We might need to restore an archived attachment.
137
+ const currentAttachments = await ctx.getAttachments();
138
+ const attachmentUpdates = [];
139
+ for (const watchedAttachment of watchedAttachments) {
140
+ const existingQueueItem = currentAttachments.find((a) => a.id === watchedAttachment.id);
141
+ if (!existingQueueItem) {
142
+ // Item is watched but not in the queue yet. Need to add it.
143
+ if (!this.downloadAttachments) {
144
+ continue;
145
+ }
146
+ const filename = watchedAttachment.filename ?? `${watchedAttachment.id}.${watchedAttachment.fileExtension}`;
147
+ attachmentUpdates.push({
148
+ id: watchedAttachment.id,
149
+ filename,
150
+ state: AttachmentState.QUEUED_DOWNLOAD,
151
+ hasSynced: false,
152
+ metaData: watchedAttachment.metaData,
153
+ timestamp: new Date().getTime()
154
+ });
155
+ continue;
156
+ }
157
+ if (existingQueueItem.state === AttachmentState.ARCHIVED) {
158
+ // The attachment is present again. Need to queue it for sync.
159
+ // We might be able to optimize this in future
160
+ if (existingQueueItem.hasSynced === true) {
161
+ // No remote action required, we can restore the record (avoids deletion)
162
+ attachmentUpdates.push({
163
+ ...existingQueueItem,
164
+ state: AttachmentState.SYNCED
165
+ });
166
+ }
167
+ else {
168
+ // The localURI should be set if the record was meant to be uploaded
169
+ // and hasSynced is false then
170
+ // it must be an upload operation
171
+ const newState = existingQueueItem.localUri == null ? AttachmentState.QUEUED_DOWNLOAD : AttachmentState.QUEUED_UPLOAD;
172
+ attachmentUpdates.push({
173
+ ...existingQueueItem,
174
+ state: newState
175
+ });
176
+ }
177
+ }
178
+ }
179
+ for (const attachment of currentAttachments) {
180
+ const notInWatchedItems = watchedAttachments.find((i) => i.id === attachment.id) == null;
181
+ if (notInWatchedItems) {
182
+ switch (attachment.state) {
183
+ case AttachmentState.QUEUED_DELETE:
184
+ case AttachmentState.QUEUED_UPLOAD:
185
+ // Only archive if it has synced
186
+ if (attachment.hasSynced === true) {
187
+ attachmentUpdates.push({
188
+ ...attachment,
189
+ state: AttachmentState.ARCHIVED
190
+ });
191
+ }
192
+ break;
193
+ default:
194
+ // Archive other states such as QUEUED_DOWNLOAD
195
+ attachmentUpdates.push({
196
+ ...attachment,
197
+ state: AttachmentState.ARCHIVED
198
+ });
199
+ }
200
+ }
201
+ }
202
+ if (attachmentUpdates.length > 0) {
203
+ await ctx.saveAttachments(attachmentUpdates);
204
+ }
205
+ });
206
+ }, signal);
207
+ }
208
+ /**
209
+ * Synchronizes all active attachments between local and remote storage.
210
+ *
211
+ * This is called automatically at regular intervals when sync is started,
212
+ * but can also be called manually to trigger an immediate sync.
213
+ */
214
+ async syncStorage() {
215
+ await this.attachmentService.withContext(async (ctx) => {
216
+ const activeAttachments = await ctx.getActiveAttachments();
217
+ await this.localStorage.initialize();
218
+ await this.syncingService.processAttachments(activeAttachments, ctx);
219
+ await this.syncingService.deleteArchivedAttachments(ctx);
220
+ });
221
+ }
222
+ /**
223
+ * Stops the attachment synchronization process.
224
+ *
225
+ * Clears the periodic sync timer and closes all active attachment watchers.
226
+ */
227
+ async stopSync() {
228
+ clearInterval(this.periodicSyncTimer);
229
+ this.periodicSyncTimer = undefined;
230
+ if (this.watchActiveAttachments)
231
+ await this.watchActiveAttachments.close();
232
+ if (this.watchAttachmentsAbortController) {
233
+ this.watchAttachmentsAbortController.abort();
234
+ }
235
+ if (this.statusListenerDispose) {
236
+ this.statusListenerDispose();
237
+ this.statusListenerDispose = undefined;
238
+ }
239
+ }
240
+ /**
241
+ * Saves a file to local storage and queues it for upload to remote storage.
242
+ *
243
+ * @param options - File save options
244
+ * @param options.data - The file data as ArrayBuffer, Blob, or base64 string
245
+ * @param options.fileExtension - File extension (e.g., 'jpg', 'pdf')
246
+ * @param options.mediaType - MIME type of the file (e.g., 'image/jpeg')
247
+ * @param options.metaData - Optional metadata to associate with the attachment
248
+ * @param options.id - Optional custom ID. If not provided, a UUID will be generated
249
+ * @param options.updateHook - Optional callback to execute additional database operations
250
+ * within the same transaction as the attachment creation
251
+ * @returns Promise resolving to the created attachment record
252
+ */
253
+ async saveFile({ data, fileExtension, mediaType, metaData, id, updateHook }) {
254
+ const resolvedId = id ?? (await this.generateAttachmentId());
255
+ const filename = `${resolvedId}.${fileExtension}`;
256
+ const localUri = this.localStorage.getLocalUri(filename);
257
+ const size = await this.localStorage.saveFile(localUri, data);
258
+ const attachment = {
259
+ id: resolvedId,
260
+ filename,
261
+ mediaType,
262
+ localUri,
263
+ state: AttachmentState.QUEUED_UPLOAD,
264
+ hasSynced: false,
265
+ size,
266
+ timestamp: new Date().getTime(),
267
+ metaData
268
+ };
269
+ await this.attachmentService.withContext(async (ctx) => {
270
+ await ctx.db.writeTransaction(async (tx) => {
271
+ await updateHook?.(tx, attachment);
272
+ await ctx.upsertAttachment(attachment, tx);
273
+ });
274
+ });
275
+ return attachment;
276
+ }
277
+ async deleteFile({ id, updateHook }) {
278
+ await this.attachmentService.withContext(async (ctx) => {
279
+ const attachment = await ctx.getAttachment(id);
280
+ if (!attachment) {
281
+ throw new Error(`Attachment with id ${id} not found`);
282
+ }
283
+ await ctx.db.writeTransaction(async (tx) => {
284
+ await updateHook?.(tx, attachment);
285
+ await ctx.upsertAttachment({
286
+ ...attachment,
287
+ state: AttachmentState.QUEUED_DELETE,
288
+ hasSynced: false
289
+ }, tx);
290
+ });
291
+ });
292
+ }
293
+ async expireCache() {
294
+ let isDone = false;
295
+ while (!isDone) {
296
+ await this.attachmentService.withContext(async (ctx) => {
297
+ isDone = await this.syncingService.deleteArchivedAttachments(ctx);
298
+ });
299
+ }
300
+ }
301
+ async clearQueue() {
302
+ await this.attachmentService.withContext(async (ctx) => {
303
+ await ctx.clearQueue();
304
+ });
305
+ await this.localStorage.clear();
306
+ }
307
+ /**
308
+ * Verifies the integrity of all attachment records and repairs inconsistencies.
309
+ *
310
+ * This method checks each attachment record against the local filesystem and:
311
+ * - Updates localUri if the file exists at a different path
312
+ * - Archives attachments with missing local files that haven't been uploaded
313
+ * - Requeues synced attachments for download if their local files are missing
314
+ */
315
+ async verifyAttachments() {
316
+ await this.attachmentService.withContext(async (ctx) => {
317
+ const attachments = await ctx.getAttachments();
318
+ const updates = [];
319
+ for (const attachment of attachments) {
320
+ if (attachment.localUri == null) {
321
+ continue;
322
+ }
323
+ const exists = await this.localStorage.fileExists(attachment.localUri);
324
+ if (exists) {
325
+ // The file exists, this is correct
326
+ continue;
327
+ }
328
+ const newLocalUri = this.localStorage.getLocalUri(attachment.filename);
329
+ const newExists = await this.localStorage.fileExists(newLocalUri);
330
+ if (newExists) {
331
+ // The file exists locally but the localUri is broken, we update it.
332
+ updates.push({
333
+ ...attachment,
334
+ localUri: newLocalUri
335
+ });
336
+ }
337
+ else {
338
+ // the file doesn't exist locally.
339
+ if (attachment.state === AttachmentState.SYNCED) {
340
+ // the file has been successfully synced to remote storage but is missing
341
+ // we download it again
342
+ updates.push({
343
+ ...attachment,
344
+ state: AttachmentState.QUEUED_DOWNLOAD,
345
+ localUri: undefined
346
+ });
347
+ }
348
+ else {
349
+ // the file wasn't successfully synced to remote storage, we archive it
350
+ updates.push({
351
+ ...attachment,
352
+ state: AttachmentState.ARCHIVED,
353
+ localUri: undefined // Clears the value
354
+ });
355
+ }
356
+ }
357
+ }
358
+ await ctx.saveAttachments(updates);
359
+ });
360
+ }
361
+ }
362
+ //# sourceMappingURL=AttachmentQueue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AttachmentQueue.js","sourceRoot":"","sources":["../../src/attachments/AttachmentQueue.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import { AbstractPowerSyncDatabase } from '../client/AbstractPowerSyncDatabase.js';
2
+ import { DifferentialWatchedQuery } from '../client/watched/processors/DifferentialQueryProcessor.js';
3
+ import { ILogger } from '../utils/Logger.js';
4
+ import { AttachmentContext } from './AttachmentContext.js';
5
+ import { AttachmentRecord } from './Schema.js';
6
+ /**
7
+ * Service for querying and watching attachment records in the database.
8
+ *
9
+ * @internal
10
+ */
11
+ export declare class AttachmentService {
12
+ private db;
13
+ private logger;
14
+ private tableName;
15
+ private mutex;
16
+ private context;
17
+ constructor(db: AbstractPowerSyncDatabase, logger: ILogger, tableName?: string, archivedCacheLimit?: number);
18
+ /**
19
+ * Creates a differential watch query for active attachments requiring synchronization.
20
+ * @returns Watch query that emits changes for queued uploads, downloads, and deletes
21
+ */
22
+ watchActiveAttachments({ throttleMs }?: {
23
+ throttleMs?: number;
24
+ }): DifferentialWatchedQuery<AttachmentRecord>;
25
+ /**
26
+ * Executes a callback with exclusive access to the attachment context.
27
+ */
28
+ withContext<T>(callback: (context: AttachmentContext) => Promise<T>): Promise<T>;
29
+ }
@@ -0,0 +1,56 @@
1
+ import { Mutex } from 'async-mutex';
2
+ import { mutexRunExclusive } from '../utils/mutex.js';
3
+ import { AttachmentContext } from './AttachmentContext.js';
4
+ import { AttachmentState } from './Schema.js';
5
+ /**
6
+ * Service for querying and watching attachment records in the database.
7
+ *
8
+ * @internal
9
+ */
10
+ export class AttachmentService {
11
+ db;
12
+ logger;
13
+ tableName;
14
+ mutex = new Mutex();
15
+ context;
16
+ constructor(db, logger, tableName = 'attachments', archivedCacheLimit = 100) {
17
+ this.db = db;
18
+ this.logger = logger;
19
+ this.tableName = tableName;
20
+ this.context = new AttachmentContext(db, tableName, logger, archivedCacheLimit);
21
+ }
22
+ /**
23
+ * Creates a differential watch query for active attachments requiring synchronization.
24
+ * @returns Watch query that emits changes for queued uploads, downloads, and deletes
25
+ */
26
+ watchActiveAttachments({ throttleMs } = {}) {
27
+ this.logger.info('Watching active attachments...');
28
+ const watch = this.db
29
+ .query({
30
+ sql: /* sql */ `
31
+ SELECT
32
+ *
33
+ FROM
34
+ ${this.tableName}
35
+ WHERE
36
+ state = ?
37
+ OR state = ?
38
+ OR state = ?
39
+ ORDER BY
40
+ timestamp ASC
41
+ `,
42
+ parameters: [AttachmentState.QUEUED_UPLOAD, AttachmentState.QUEUED_DOWNLOAD, AttachmentState.QUEUED_DELETE]
43
+ })
44
+ .differentialWatch({ throttleMs });
45
+ return watch;
46
+ }
47
+ /**
48
+ * Executes a callback with exclusive access to the attachment context.
49
+ */
50
+ async withContext(callback) {
51
+ return mutexRunExclusive(this.mutex, async () => {
52
+ return callback(this.context);
53
+ });
54
+ }
55
+ }
56
+ //# sourceMappingURL=AttachmentService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AttachmentService.js","sourceRoot":"","sources":["../../src/attachments/AttachmentService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAIpC,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAoB,eAAe,EAAE,MAAM,aAAa,CAAC;AAEhE;;;;GAIG;AACH,MAAM,OAAO,iBAAiB;IAKlB;IACA;IACA;IANF,KAAK,GAAG,IAAI,KAAK,EAAE,CAAC;IACpB,OAAO,CAAoB;IAEnC,YACU,EAA6B,EAC7B,MAAe,EACf,YAAoB,aAAa,EACzC,qBAA6B,GAAG;QAHxB,OAAE,GAAF,EAAE,CAA2B;QAC7B,WAAM,GAAN,MAAM,CAAS;QACf,cAAS,GAAT,SAAS,CAAwB;QAGzC,IAAI,CAAC,OAAO,GAAG,IAAI,iBAAiB,CAAC,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,kBAAkB,CAAC,CAAC;IAClF,CAAC;IAED;;;OAGG;IACH,sBAAsB,CAAC,EAAE,UAAU,KAA8B,EAAE;QACjE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC;QACnD,MAAM,KAAK,GAAG,IAAI,CAAC,EAAE;aAClB,KAAK,CAAmB;YACvB,GAAG,EAAE,SAAS,CAAC;;;;cAIT,IAAI,CAAC,SAAS;;;;;;;SAOnB;YACD,UAAU,EAAE,CAAC,eAAe,CAAC,aAAa,EAAE,eAAe,CAAC,eAAe,EAAE,eAAe,CAAC,aAAa,CAAC;SAC5G,CAAC;aACD,iBAAiB,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC;QAErC,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,WAAW,CAAI,QAAoD;QACvE,OAAO,iBAAiB,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,IAAI,EAAE;YAC9C,OAAO,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAChC,CAAC,CAAC,CAAC;IACL,CAAC;CACF"}
@@ -0,0 +1,62 @@
1
+ export type AttachmentData = ArrayBuffer | string;
2
+ export declare enum EncodingType {
3
+ UTF8 = "utf8",
4
+ Base64 = "base64"
5
+ }
6
+ /**
7
+ * LocalStorageAdapter defines the interface for local file storage operations.
8
+ * Implementations handle file I/O, directory management, and storage initialization.
9
+ *
10
+ * @experimental
11
+ * @alpha This is currently experimental and may change without a major version bump.
12
+ */
13
+ export interface LocalStorageAdapter {
14
+ /**
15
+ * Saves data to a local file.
16
+ * @param filePath Path where the file will be stored
17
+ * @param data Data to store (ArrayBuffer, Blob, or string)
18
+ * @returns Number of bytes written
19
+ */
20
+ saveFile(filePath: string, data: AttachmentData): Promise<number>;
21
+ /**
22
+ * Retrieves file data as an ArrayBuffer.
23
+ * @param filePath Path where the file is stored
24
+ * @returns ArrayBuffer containing the file data
25
+ */
26
+ readFile(filePath: string): Promise<ArrayBuffer>;
27
+ /**
28
+ * Deletes the file at the given path.
29
+ * @param filePath Path where the file is stored
30
+ */
31
+ deleteFile(filePath: string): Promise<void>;
32
+ /**
33
+ * Checks if a file exists at the given path.
34
+ * @param filePath Path where the file is stored
35
+ * @returns True if the file exists, false otherwise
36
+ */
37
+ fileExists(filePath: string): Promise<boolean>;
38
+ /**
39
+ * Creates a directory at the specified path.
40
+ * @param path The full path to the directory
41
+ */
42
+ makeDir(path: string): Promise<void>;
43
+ /**
44
+ * Removes a directory at the specified path.
45
+ * @param path The full path to the directory
46
+ */
47
+ rmDir(path: string): Promise<void>;
48
+ /**
49
+ * Initializes the storage adapter (e.g., creating necessary directories).
50
+ */
51
+ initialize(): Promise<void>;
52
+ /**
53
+ * Clears all files in the storage.
54
+ */
55
+ clear(): Promise<void>;
56
+ /**
57
+ * Returns the file path for the provided filename in the storage directory.
58
+ * @param filename The filename to get the path for
59
+ * @returns The full file path
60
+ */
61
+ getLocalUri(filename: string): string;
62
+ }
@@ -0,0 +1,6 @@
1
+ export var EncodingType;
2
+ (function (EncodingType) {
3
+ EncodingType["UTF8"] = "utf8";
4
+ EncodingType["Base64"] = "base64";
5
+ })(EncodingType || (EncodingType = {}));
6
+ //# sourceMappingURL=LocalStorageAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LocalStorageAdapter.js","sourceRoot":"","sources":["../../src/attachments/LocalStorageAdapter.ts"],"names":[],"mappings":"AAEA,MAAM,CAAN,IAAY,YAGX;AAHD,WAAY,YAAY;IACtB,6BAAa,CAAA;IACb,iCAAiB,CAAA;AACnB,CAAC,EAHW,YAAY,KAAZ,YAAY,QAGvB"}
@@ -0,0 +1,27 @@
1
+ import { AttachmentRecord } from './Schema.js';
2
+ /**
3
+ * RemoteStorageAdapter defines the interface for remote storage operations.
4
+ * Implementations handle uploading, downloading, and deleting files from remote storage.
5
+ *
6
+ * @experimental
7
+ * @alpha This is currently experimental and may change without a major version bump.
8
+ */
9
+ export interface RemoteStorageAdapter {
10
+ /**
11
+ * Uploads a file to remote storage.
12
+ * @param fileData The binary content of the file to upload
13
+ * @param attachment The associated attachment metadata
14
+ */
15
+ uploadFile(fileData: ArrayBuffer, attachment: AttachmentRecord): Promise<void>;
16
+ /**
17
+ * Downloads a file from remote storage.
18
+ * @param attachment The attachment describing the file to download
19
+ * @returns The binary data of the downloaded file
20
+ */
21
+ downloadFile(attachment: AttachmentRecord): Promise<ArrayBuffer>;
22
+ /**
23
+ * Deletes a file from remote storage.
24
+ * @param attachment The attachment describing the file to delete
25
+ */
26
+ deleteFile(attachment: AttachmentRecord): Promise<void>;
27
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=RemoteStorageAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RemoteStorageAdapter.js","sourceRoot":"","sources":["../../src/attachments/RemoteStorageAdapter.ts"],"names":[],"mappings":""}
@@ -0,0 +1,50 @@
1
+ import { Table } from '../db/schema/Table.js';
2
+ import { TableV2Options } from '../db/schema/Table.js';
3
+ export declare const ATTACHMENT_TABLE = "attachments";
4
+ /**
5
+ * AttachmentRecord represents an attachment in the local database.
6
+ *
7
+ * @experimental
8
+ */
9
+ export interface AttachmentRecord {
10
+ id: string;
11
+ filename: string;
12
+ localUri?: string;
13
+ size?: number;
14
+ mediaType?: string;
15
+ timestamp?: number;
16
+ metaData?: string;
17
+ hasSynced?: boolean;
18
+ state: AttachmentState;
19
+ }
20
+ /**
21
+ * Maps a database row to an AttachmentRecord.
22
+ *
23
+ * @param row - The database row object
24
+ * @returns The corresponding AttachmentRecord
25
+ *
26
+ * @experimental
27
+ */
28
+ export declare function attachmentFromSql(row: any): AttachmentRecord;
29
+ /**
30
+ * AttachmentState represents the current synchronization state of an attachment.
31
+ *
32
+ * @experimental
33
+ */
34
+ export declare enum AttachmentState {
35
+ QUEUED_UPLOAD = 0,// Attachment to be uploaded
36
+ QUEUED_DOWNLOAD = 1,// Attachment to be downloaded
37
+ QUEUED_DELETE = 2,// Attachment to be deleted
38
+ SYNCED = 3,// Attachment has been synced
39
+ ARCHIVED = 4
40
+ }
41
+ export interface AttachmentTableOptions extends Omit<TableV2Options, 'name' | 'columns'> {
42
+ }
43
+ /**
44
+ * AttachmentTable defines the schema for the attachment queue table.
45
+ *
46
+ * @internal
47
+ */
48
+ export declare class AttachmentTable extends Table {
49
+ constructor(options?: AttachmentTableOptions);
50
+ }