@powersync/common 0.0.0-dev-20260630144038 → 0.0.0-dev-20261015114518

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 (48) hide show
  1. package/lib/attachments/AttachmentContext.js +2 -1
  2. package/lib/attachments/AttachmentContext.js.map +1 -1
  3. package/lib/attachments/AttachmentQueue.d.ts +98 -42
  4. package/lib/attachments/AttachmentQueue.js +103 -22
  5. package/lib/attachments/AttachmentQueue.js.map +1 -1
  6. package/lib/attachments/AttachmentTransportAdapter.d.ts +47 -0
  7. package/lib/attachments/AttachmentTransportAdapter.js +2 -0
  8. package/lib/attachments/AttachmentTransportAdapter.js.map +1 -0
  9. package/lib/attachments/BufferedAttachmentTransport.d.ts +24 -0
  10. package/lib/attachments/BufferedAttachmentTransport.js +32 -0
  11. package/lib/attachments/BufferedAttachmentTransport.js.map +1 -0
  12. package/lib/attachments/LocalStorageAdapter.d.ts +19 -0
  13. package/lib/attachments/Schema.d.ts +21 -2
  14. package/lib/attachments/Schema.js +14 -10
  15. package/lib/attachments/Schema.js.map +1 -1
  16. package/lib/attachments/SyncingService.d.ts +21 -8
  17. package/lib/attachments/SyncingService.js +59 -30
  18. package/lib/attachments/SyncingService.js.map +1 -1
  19. package/lib/client/CommonPowerSyncDatabase.d.ts +25 -1
  20. package/lib/client/connection/PowerSyncBackendConnector.d.ts +11 -0
  21. package/lib/client/connection/PowerSyncCredentials.d.ts +1 -1
  22. package/lib/client/runOnSchemaChange.js +2 -0
  23. package/lib/client/runOnSchemaChange.js.map +1 -1
  24. package/lib/client/sync/CheckpointRequest.d.ts +32 -0
  25. package/lib/client/sync/CheckpointRequest.js +2 -0
  26. package/lib/client/sync/CheckpointRequest.js.map +1 -0
  27. package/lib/client/sync/options.d.ts +42 -0
  28. package/lib/client/sync/options.js.map +1 -1
  29. package/lib/db/crud/SyncStatus.d.ts +1 -1
  30. package/lib/index.d.ts +3 -1
  31. package/lib/index.js +2 -0
  32. package/lib/index.js.map +1 -1
  33. package/package.json +4 -3
  34. package/src/attachments/AttachmentContext.ts +2 -1
  35. package/src/attachments/AttachmentQueue.ts +176 -68
  36. package/src/attachments/AttachmentTransportAdapter.ts +49 -0
  37. package/src/attachments/BufferedAttachmentTransport.ts +37 -0
  38. package/src/attachments/LocalStorageAdapter.ts +20 -0
  39. package/src/attachments/Schema.ts +29 -20
  40. package/src/attachments/SyncingService.ts +67 -34
  41. package/src/client/CommonPowerSyncDatabase.ts +26 -1
  42. package/src/client/connection/PowerSyncBackendConnector.ts +12 -0
  43. package/src/client/connection/PowerSyncCredentials.ts +1 -1
  44. package/src/client/runOnSchemaChange.ts +2 -0
  45. package/src/client/sync/CheckpointRequest.ts +31 -0
  46. package/src/client/sync/options.ts +44 -0
  47. package/src/db/crud/SyncStatus.ts +1 -1
  48. package/src/index.ts +9 -1
@@ -1,4 +1,4 @@
1
- import { Table } from '../db/schema/Table.js';
1
+ import { RowType, Table } from '../db/schema/Table.js';
2
2
  import { TableOptions } from '../db/schema/Table.js';
3
3
  /**
4
4
  * The default name of the local table storing attachment data.
@@ -48,11 +48,30 @@ export declare enum AttachmentState {
48
48
  */
49
49
  export interface AttachmentTableOptions extends Omit<TableOptions, 'name' | 'columns'> {
50
50
  }
51
+ /**
52
+ * @alpha
53
+ */
54
+ export declare const ATTACHMENT_TABLE_COLUMNS: {
55
+ filename: import("../db/schema/Column.js").BaseColumnType<string | null>;
56
+ local_uri: import("../db/schema/Column.js").BaseColumnType<string | null>;
57
+ timestamp: import("../db/schema/Column.js").BaseColumnType<number | null>;
58
+ size: import("../db/schema/Column.js").BaseColumnType<number | null>;
59
+ media_type: import("../db/schema/Column.js").BaseColumnType<string | null>;
60
+ state: import("../db/schema/Column.js").BaseColumnType<number | null>;
61
+ has_synced: import("../db/schema/Column.js").BaseColumnType<number | null>;
62
+ meta_data: import("../db/schema/Column.js").BaseColumnType<string | null>;
63
+ };
51
64
  /**
52
65
  * AttachmentTable defines the schema for the attachment queue table.
53
66
  *
54
67
  * @alpha
55
68
  */
56
- export declare class AttachmentTable extends Table {
69
+ export declare class AttachmentTable extends Table<typeof ATTACHMENT_TABLE_COLUMNS> {
57
70
  constructor(options?: AttachmentTableOptions);
58
71
  }
72
+ /**
73
+ * AttachmentTableRecord represents the row type of the attachment table.
74
+ *
75
+ * @alpha
76
+ */
77
+ export type AttachmentTableRecord = RowType<AttachmentTable>;
@@ -40,6 +40,19 @@ export var AttachmentState;
40
40
  AttachmentState[AttachmentState["SYNCED"] = 3] = "SYNCED";
41
41
  AttachmentState[AttachmentState["ARCHIVED"] = 4] = "ARCHIVED"; // Attachment has been orphaned, i.e. the associated record has been deleted
42
42
  })(AttachmentState || (AttachmentState = {}));
43
+ /**
44
+ * @alpha
45
+ */
46
+ export const ATTACHMENT_TABLE_COLUMNS = {
47
+ filename: column.text,
48
+ local_uri: column.text,
49
+ timestamp: column.integer,
50
+ size: column.integer,
51
+ media_type: column.text,
52
+ state: column.integer, // Corresponds to AttachmentState
53
+ has_synced: column.integer,
54
+ meta_data: column.text
55
+ };
43
56
  /**
44
57
  * AttachmentTable defines the schema for the attachment queue table.
45
58
  *
@@ -47,16 +60,7 @@ export var AttachmentState;
47
60
  */
48
61
  export class AttachmentTable extends Table {
49
62
  constructor(options) {
50
- super({
51
- filename: column.text,
52
- local_uri: column.text,
53
- timestamp: column.integer,
54
- size: column.integer,
55
- media_type: column.text,
56
- state: column.integer, // Corresponds to AttachmentState
57
- has_synced: column.integer,
58
- meta_data: column.text
59
- }, {
63
+ super(ATTACHMENT_TABLE_COLUMNS, {
60
64
  ...options,
61
65
  viewName: options?.viewName ?? ATTACHMENT_TABLE,
62
66
  localOnly: true,
@@ -1 +1 @@
1
- {"version":3,"file":"Schema.js","sourceRoot":"","sources":["../../src/attachments/Schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAG9C;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,aAAa,CAAC;AAmB9C;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAQ;IACxC,OAAO;QACL,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,QAAQ,EAAE,GAAG,CAAC,SAAS;QACvB,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,SAAS,EAAE,GAAG,CAAC,UAAU;QACzB,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,QAAQ,EAAE,GAAG,CAAC,SAAS;QACvB,SAAS,EAAE,GAAG,CAAC,UAAU,KAAK,CAAC;QAC/B,KAAK,EAAE,GAAG,CAAC,KAAK;KACjB,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAN,IAAY,eAMX;AAND,WAAY,eAAe;IACzB,uEAAiB,CAAA;IACjB,2EAAmB,CAAA;IACnB,uEAAiB,CAAA;IACjB,yDAAU,CAAA;IACV,6DAAY,CAAA,CAAC,4EAA4E;AAC3F,CAAC,EANW,eAAe,KAAf,eAAe,QAM1B;AAOD;;;;GAIG;AACH,MAAM,OAAO,eAAgB,SAAQ,KAAK;IACxC,YAAY,OAAgC;QAC1C,KAAK,CACH;YACE,QAAQ,EAAE,MAAM,CAAC,IAAI;YACrB,SAAS,EAAE,MAAM,CAAC,IAAI;YACtB,SAAS,EAAE,MAAM,CAAC,OAAO;YACzB,IAAI,EAAE,MAAM,CAAC,OAAO;YACpB,UAAU,EAAE,MAAM,CAAC,IAAI;YACvB,KAAK,EAAE,MAAM,CAAC,OAAO,EAAE,iCAAiC;YACxD,UAAU,EAAE,MAAM,CAAC,OAAO;YAC1B,SAAS,EAAE,MAAM,CAAC,IAAI;SACvB,EACD;YACE,GAAG,OAAO;YACV,QAAQ,EAAE,OAAO,EAAE,QAAQ,IAAI,gBAAgB;YAC/C,SAAS,EAAE,IAAI;YACf,UAAU,EAAE,KAAK;SAClB,CACF,CAAC;IACJ,CAAC;CACF"}
1
+ {"version":3,"file":"Schema.js","sourceRoot":"","sources":["../../src/attachments/Schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAW,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAGvD;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,aAAa,CAAC;AAmB9C;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAQ;IACxC,OAAO;QACL,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,QAAQ,EAAE,GAAG,CAAC,SAAS;QACvB,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,SAAS,EAAE,GAAG,CAAC,UAAU;QACzB,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,QAAQ,EAAE,GAAG,CAAC,SAAS;QACvB,SAAS,EAAE,GAAG,CAAC,UAAU,KAAK,CAAC;QAC/B,KAAK,EAAE,GAAG,CAAC,KAAK;KACjB,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAN,IAAY,eAMX;AAND,WAAY,eAAe;IACzB,uEAAiB,CAAA;IACjB,2EAAmB,CAAA;IACnB,uEAAiB,CAAA;IACjB,yDAAU,CAAA;IACV,6DAAY,CAAA,CAAC,4EAA4E;AAC3F,CAAC,EANW,eAAe,KAAf,eAAe,QAM1B;AAOD;;GAEG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC,QAAQ,EAAE,MAAM,CAAC,IAAI;IACrB,SAAS,EAAE,MAAM,CAAC,IAAI;IACtB,SAAS,EAAE,MAAM,CAAC,OAAO;IACzB,IAAI,EAAE,MAAM,CAAC,OAAO;IACpB,UAAU,EAAE,MAAM,CAAC,IAAI;IACvB,KAAK,EAAE,MAAM,CAAC,OAAO,EAAE,iCAAiC;IACxD,UAAU,EAAE,MAAM,CAAC,OAAO;IAC1B,SAAS,EAAE,MAAM,CAAC,IAAI;CACvB,CAAC;AAEF;;;;GAIG;AACH,MAAM,OAAO,eAAgB,SAAQ,KAAsC;IACzE,YAAY,OAAgC;QAC1C,KAAK,CAAC,wBAAwB,EAAE;YAC9B,GAAG,OAAO;YACV,QAAQ,EAAE,OAAO,EAAE,QAAQ,IAAI,gBAAgB;YAC/C,SAAS,EAAE,IAAI;YACf,UAAU,EAAE,KAAK;SAClB,CAAC,CAAC;IACL,CAAC;CACF"}
@@ -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,24 +9,37 @@ 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
- * All updates are saved in a single batch after processing.
26
+ *
27
+ * Each attachment's I/O runs outside the attachment-service mutex, and the row's
28
+ * state transition is persisted immediately after it completes. This keeps the
29
+ * mutex available to concurrent `saveFile` / `deleteFile` / watched-attachment
30
+ * processing while a batch is in flight, and means consumer queries against the
31
+ * attachments queue see incremental progress instead of one atomic commit at the
32
+ * end of the batch.
24
33
  *
25
34
  * @param attachments - Array of attachment records to process
26
- * @param context - Attachment context for database operations
27
- * @returns Promise that resolves when all attachments have been processed and saved
35
+ * @param options - Optional controls. Pass `signal` (an `AbortSignal`) to interrupt
36
+ * the batch: it is checked between attachments and, once aborted, the
37
+ * loop exits early — letting `stopSync` stop a running batch within
38
+ * one attachment's processing time.
28
39
  */
29
- processAttachments(attachments: AttachmentRecord[], context: AttachmentContext): Promise<void>;
40
+ processAttachments(attachments: AttachmentRecord[], options?: {
41
+ signal?: AbortSignal;
42
+ }): Promise<void>;
30
43
  /**
31
44
  * Uploads an attachment from local storage to remote storage.
32
45
  * On success, marks as SYNCED. On failure, defers to error handler or archives.
@@ -38,7 +51,7 @@ export declare class SyncingService {
38
51
  uploadAttachment(attachment: AttachmentRecord): Promise<AttachmentRecord>;
39
52
  /**
40
53
  * Downloads an attachment from remote storage to local storage.
41
- * Retrieves the file, converts to base64, and saves locally.
54
+ * The destination `localUri` is assigned here and the transport writes the file to it.
42
55
  * On success, marks as SYNCED. On failure, defers to error handler or archives.
43
56
  *
44
57
  * @param attachment - The attachment record to download
@@ -4,50 +4,81 @@ 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
  }
22
25
  /**
23
26
  * Processes attachments based on their state (upload, download, or delete).
24
- * All updates are saved in a single batch after processing.
27
+ *
28
+ * Each attachment's I/O runs outside the attachment-service mutex, and the row's
29
+ * state transition is persisted immediately after it completes. This keeps the
30
+ * mutex available to concurrent `saveFile` / `deleteFile` / watched-attachment
31
+ * processing while a batch is in flight, and means consumer queries against the
32
+ * attachments queue see incremental progress instead of one atomic commit at the
33
+ * end of the batch.
25
34
  *
26
35
  * @param attachments - Array of attachment records to process
27
- * @param context - Attachment context for database operations
28
- * @returns Promise that resolves when all attachments have been processed and saved
36
+ * @param options - Optional controls. Pass `signal` (an `AbortSignal`) to interrupt
37
+ * the batch: it is checked between attachments and, once aborted, the
38
+ * loop exits early — letting `stopSync` stop a running batch within
39
+ * one attachment's processing time.
29
40
  */
30
- async processAttachments(attachments, context) {
31
- const updatedAttachments = [];
41
+ async processAttachments(attachments, options) {
42
+ const signal = options?.signal;
43
+ this.logger.log({
44
+ level: LogLevels.info,
45
+ message: `Starting processAttachments with ${attachments.length} attachments`
46
+ });
32
47
  for (const attachment of attachments) {
33
- switch (attachment.state) {
34
- case AttachmentState.QUEUED_UPLOAD:
35
- const uploaded = await this.uploadAttachment(attachment);
36
- updatedAttachments.push(uploaded);
37
- break;
38
- case AttachmentState.QUEUED_DOWNLOAD:
39
- const downloaded = await this.downloadAttachment(attachment);
40
- updatedAttachments.push(downloaded);
41
- break;
42
- case AttachmentState.QUEUED_DELETE:
43
- const deleted = await this.deleteAttachment(attachment, context);
44
- updatedAttachments.push(deleted);
45
- break;
46
- default:
47
- break;
48
+ if (signal?.aborted) {
49
+ this.logger.log({
50
+ level: LogLevels.info,
51
+ message: 'Sync cancelled; stopping iteration early'
52
+ });
53
+ return;
54
+ }
55
+ try {
56
+ let updated;
57
+ switch (attachment.state) {
58
+ case AttachmentState.QUEUED_UPLOAD:
59
+ updated = await this.uploadAttachment(attachment);
60
+ break;
61
+ case AttachmentState.QUEUED_DOWNLOAD:
62
+ updated = await this.downloadAttachment(attachment);
63
+ break;
64
+ case AttachmentState.QUEUED_DELETE:
65
+ // `deleteAttachment` needs a context (it removes the row in a
66
+ // transaction); briefly re-acquire the mutex for just this row.
67
+ updated = await this.attachmentService.withContext((ctx) => this.deleteAttachment(attachment, ctx));
68
+ break;
69
+ default:
70
+ continue;
71
+ }
72
+ await this.attachmentService.withContext((ctx) => ctx.saveAttachments([updated]));
73
+ }
74
+ catch (error) {
75
+ this.logger.log({
76
+ level: LogLevels.warn,
77
+ message: `Error during sync for ${attachment.id}`,
78
+ error
79
+ });
48
80
  }
49
81
  }
50
- await context.saveAttachments(updatedAttachments);
51
82
  }
52
83
  /**
53
84
  * Uploads an attachment from local storage to remote storage.
@@ -63,8 +94,7 @@ export class SyncingService {
63
94
  if (attachment.localUri == null) {
64
95
  throw new Error(`No localUri for attachment ${attachment.id}`);
65
96
  }
66
- const fileBlob = await this.localStorage.readFile(attachment.localUri);
67
- await this.remoteStorage.uploadFile(fileBlob, attachment);
97
+ await this.transport.upload({ ...attachment, localUri: attachment.localUri });
68
98
  return {
69
99
  ...attachment,
70
100
  state: AttachmentState.SYNCED,
@@ -84,7 +114,7 @@ export class SyncingService {
84
114
  }
85
115
  /**
86
116
  * Downloads an attachment from remote storage to local storage.
87
- * Retrieves the file, converts to base64, and saves locally.
117
+ * The destination `localUri` is assigned here and the transport writes the file to it.
88
118
  * On success, marks as SYNCED. On failure, defers to error handler or archives.
89
119
  *
90
120
  * @param attachment - The attachment record to download
@@ -93,9 +123,8 @@ export class SyncingService {
93
123
  async downloadAttachment(attachment) {
94
124
  this.logger.log({ level: LogLevels.info, message: `Downloading attachment ${attachment.filename}` });
95
125
  try {
96
- const fileData = await this.remoteStorage.downloadFile(attachment);
97
126
  const localUri = this.localStorage.getLocalUri(attachment.filename);
98
- await this.localStorage.saveFile(localUri, fileData);
127
+ await this.transport.download({ ...attachment, localUri });
99
128
  return {
100
129
  ...attachment,
101
130
  state: AttachmentState.SYNCED,
@@ -125,7 +154,7 @@ export class SyncingService {
125
154
  */
126
155
  async deleteAttachment(attachment, context) {
127
156
  try {
128
- await this.remoteStorage.deleteFile(attachment);
157
+ await this.transport.delete(attachment);
129
158
  if (attachment.localUri) {
130
159
  await this.localStorage.deleteFile(attachment.localUri);
131
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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"}
@@ -16,12 +16,24 @@ import { ArrayQueryDefinition, Query } from './Query.js';
16
16
  import { WatchCompatibleQuery } from './watched/WatchedQuery.js';
17
17
  import { Mutex } from '../utils/mutex.js';
18
18
  import { QueryResult } from '../db/QueryResult.js';
19
+ import { CheckpointRequest } from './sync/CheckpointRequest.js';
19
20
  /**
21
+ * Options passed to {@link CommonPowerSyncDatabase#disconnectAndClear}.
22
+ *
20
23
  * @public
21
24
  */
22
25
  export interface DisconnectAndClearOptions {
23
26
  /** When set to false, data in local-only tables is preserved. */
24
27
  clearLocal?: boolean;
28
+ /**
29
+ * A [soft] clear deletes publicly visible tables, but keeps internal copies of data synced in the database.
30
+ *
31
+ * This usually means that if {@link CommonPowerSyncDatabase#connect} is later called again with a JWT from the same
32
+ * user, the first sync is very fast because all internal data is still available. When a different user logs in, no
33
+ * old data would be visible at any point. Using soft deletes is recommended where it's not a security issue that old
34
+ * data could be reconstructed from internal database tables.
35
+ */
36
+ soft?: boolean;
25
37
  }
26
38
  /**
27
39
  * Options required regardless of how a PowerSync database is opened.
@@ -205,6 +217,18 @@ export interface CommonPowerSyncDatabase extends BaseObserverInterface<PowerSync
205
217
  * @returns A {@link SyncStream} instance that can be subscribed to.
206
218
  */
207
219
  syncStream(name: string, params?: Record<string, any>): SyncStream;
220
+ /**
221
+ * Requests a checkpoint from the PowerSync service.
222
+ *
223
+ * The returned request can be awaited (using {@link CheckpointRequest#waitForSync}) to confirm that the local
224
+ * database has applied server-side changes up to the checkpoint. This method requires an active or connecting sync
225
+ * client connected with a {@link CheckpointMode} set to `requests` and PowerSync service version 1.24.0 or later.
226
+ *
227
+ * It can throw for connection, mode, authentication, or service request failures.
228
+ *
229
+ * @alpha
230
+ */
231
+ requestCheckpoint(): Promise<CheckpointRequest>;
208
232
  /**
209
233
  * Close the database, releasing resources.
210
234
  *
@@ -307,7 +331,7 @@ export interface CommonPowerSyncDatabase extends BaseObserverInterface<PowerSync
307
331
  writeLock<T>(callback: (db: LockContext) => Promise<T>): Promise<T>;
308
332
  /**
309
333
  * Open a read-only transaction.
310
- * Read transactions can run concurrently to a write transaction.
334
+ * When multiple connections are available, read transactions can run concurrently to a write transaction.
311
335
  * Changes from any write transaction are not visible to read transactions started before it.
312
336
  *
313
337
  * @param callback - Function to execute within the transaction
@@ -23,4 +23,15 @@ export interface PowerSyncBackendConnector {
23
23
  * Any thrown errors will result in a retry after the configured wait period (default: 5 seconds).
24
24
  */
25
25
  uploadData: (database: CommonPowerSyncDatabase) => Promise<void>;
26
+ /**
27
+ * Posts a client-generated checkpoint request to the backend and returns the effective checkpoint request state.
28
+ *
29
+ * This method is optional. It only needs to be implemented when the selected {@link CheckpointMode} is `requests`
30
+ * and [asynchronous backend uploads](https://docs.powersync.com/client-sdks/advanced/checkpoint-requests#asynchronous-upload-backends)
31
+ * are used. In any other case, this method should not be present on backend connectors.
32
+ *
33
+ * @param requestId - The client-generated checkpoint request ID (a positive 64-bit integer encoded as a string).
34
+ * @param clientId - The PowerSync client ID for the current device.
35
+ */
36
+ postCheckpointRequest?(clientId: string, requestId: string): Promise<string>;
26
37
  }
@@ -4,5 +4,5 @@
4
4
  export interface PowerSyncCredentials {
5
5
  endpoint: string;
6
6
  token: string;
7
- expiresAt?: Date;
7
+ expiresAt?: Date | undefined;
8
8
  }
@@ -3,6 +3,8 @@
3
3
  */
4
4
  export function runOnSchemaChange(callback, db, options) {
5
5
  const triggerWatchedQuery = () => {
6
+ if (options?.signal?.aborted)
7
+ return;
6
8
  const abortController = new AbortController();
7
9
  let disposeSchemaListener = null;
8
10
  const stopWatching = () => {
@@ -1 +1 @@
1
- {"version":3,"file":"runOnSchemaChange.js","sourceRoot":"","sources":["../../src/client/runOnSchemaChange.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAC/B,QAAuC,EACvC,EAA2B,EAC3B,OAAyB;IAEzB,MAAM,mBAAmB,GAAG,GAAG,EAAE;QAC/B,MAAM,eAAe,GAAG,IAAI,eAAe,EAAE,CAAC;QAC9C,IAAI,qBAAqB,GAAwB,IAAI,CAAC;QACtD,MAAM,YAAY,GAAG,GAAG,EAAE;YACxB,eAAe,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;YACzC,qBAAqB,EAAE,EAAE,CAAC;YAC1B,qBAAqB,GAAG,IAAI,CAAC;YAC7B,kDAAkD;YAClD,OAAO,EAAE,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;QAC9D,CAAC,CAAC;QAEF,OAAO,EAAE,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;QACzD,qBAAqB,GAAG,EAAE,CAAC,gBAAgB,CAAC;YAC1C,aAAa,EAAE,KAAK,IAAI,EAAE;gBACxB,YAAY,EAAE,CAAC;gBACf,yIAAyI;gBACzI,UAAU,CAAC,GAAG,EAAE,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAC,CAAC;YAC7C,CAAC;SACF,CAAC,CAAC;QACH,QAAQ,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;IACnC,CAAC,CAAC;IAEF,mBAAmB,EAAE,CAAC;AACxB,CAAC"}
1
+ {"version":3,"file":"runOnSchemaChange.js","sourceRoot":"","sources":["../../src/client/runOnSchemaChange.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAC/B,QAAuC,EACvC,EAA2B,EAC3B,OAAyB;IAEzB,MAAM,mBAAmB,GAAG,GAAG,EAAE;QAC/B,IAAI,OAAO,EAAE,MAAM,EAAE,OAAO;YAAE,OAAO;QAErC,MAAM,eAAe,GAAG,IAAI,eAAe,EAAE,CAAC;QAC9C,IAAI,qBAAqB,GAAwB,IAAI,CAAC;QACtD,MAAM,YAAY,GAAG,GAAG,EAAE;YACxB,eAAe,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;YACzC,qBAAqB,EAAE,EAAE,CAAC;YAC1B,qBAAqB,GAAG,IAAI,CAAC;YAC7B,kDAAkD;YAClD,OAAO,EAAE,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;QAC9D,CAAC,CAAC;QAEF,OAAO,EAAE,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;QACzD,qBAAqB,GAAG,EAAE,CAAC,gBAAgB,CAAC;YAC1C,aAAa,EAAE,KAAK,IAAI,EAAE;gBACxB,YAAY,EAAE,CAAC;gBACf,yIAAyI;gBACzI,UAAU,CAAC,GAAG,EAAE,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAC,CAAC;YAC7C,CAAC;SACF,CAAC,CAAC;QACH,QAAQ,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;IACnC,CAAC,CAAC;IAEF,mBAAmB,EAAE,CAAC;AACxB,CAAC"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * A checkpoint request created by {@link CommonPowerSyncDatabase#requestCheckpoint}.
3
+ *
4
+ * Use this value to wait until the local database has applied server-side changes up to the requested checkpoint. This
5
+ * is useful for explicit refresh flows where the caller wants confirmation that the local view has caught up to the
6
+ * service.
7
+ *
8
+ * Checkpoint requests are backed by request ids tracked in the local database, so they are reusable across disconnect
9
+ * and reconnect cycles. A wait interrupted by a disconnect throws an error, but the same request can be awaited again
10
+ * once a new connection is established.
11
+ *
12
+ * Requests do not survive {@link CommonPowerSyncDatabase#disconnectAndClear}, instances created before a clear should
13
+ * be discarded and requested again.
14
+ *
15
+ * @alpha
16
+ */
17
+ export interface CheckpointRequest {
18
+ /**
19
+ * Whether this checkpoint request has synced before.
20
+ */
21
+ readonly hasSynced: boolean;
22
+ /**
23
+ * Waits until this checkpoint has been synced locally.
24
+ *
25
+ * This method fails on sync errors: If a download or upload error occurs before this checkpoint request has synced,
26
+ * that error is rethrown here. This makes it easier to observe sync errors when relying on checkpoints. Once sync has
27
+ * recovered, it is valid to call this method again to await the checkpoint.
28
+ */
29
+ waitForSync(options?: {
30
+ signal?: AbortSignal;
31
+ }): Promise<void>;
32
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=CheckpointRequest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CheckpointRequest.js","sourceRoot":"","sources":["../../../src/client/sync/CheckpointRequest.ts"],"names":[],"mappings":""}
@@ -40,6 +40,18 @@ export interface SyncOptions {
40
40
  * milliseconds.
41
41
  */
42
42
  crudUploadThrottleMs?: number;
43
+ /**
44
+ * The mode used to request checkpoints from the service (used after uploading local data).
45
+ */
46
+ checkpointMode?: CheckpointMode;
47
+ /**
48
+ * Enables the core extension's diagnostics event stream: detailed per-bucket download stats,
49
+ * including each bucket's `target_count`, and inferred column types. Off by default.
50
+ *
51
+ * The events are internal. No public API exposes them; only PowerSync DevTools reads them, to show
52
+ * per-bucket totals. See https://docs.powersync.com/tools/devtools-overview.
53
+ */
54
+ diagnostics?: boolean;
43
55
  }
44
56
  /**
45
57
  * @public
@@ -63,3 +75,33 @@ export declare enum FetchStrategy {
63
75
  */
64
76
  Sequential = "sequential"
65
77
  }
78
+ /**
79
+ * The mechanism to request checkpoints from the PowerSync service.
80
+ *
81
+ * Checkpoint requests are used after a client uploads local mutations. The PowerSync service later references them in
82
+ * downloaded data, allowing the SDK to assume that uploaded data has been synced down again.
83
+ *
84
+ * There are two ways to send checkpoint requests: A legacy (but default and stable) format supported by all PowerSync
85
+ * service versions, and a newer (`requests`) method which is only available from PowerSync service version 1.24.0 or
86
+ * later.
87
+ *
88
+ * Note that the requests checkpoint mode is an alpha API.
89
+ *
90
+ * @public
91
+ */
92
+ export type CheckpointMode = 'legacy' | 'requests' | {
93
+ requests: CheckpointRequestsOptions;
94
+ };
95
+ /**
96
+ * Options associated with a {@link CheckpointMode} when the requests-based checkpoint option is used.
97
+ *
98
+ * @public
99
+ */
100
+ export interface CheckpointRequestsOptions {
101
+ /**
102
+ * The delay, in milliseconds, to wait before re-sending a checkpoint request when it hasn't been applied in time.
103
+ *
104
+ * The minimum value for this is 10 seconds, lower values will be ignored.
105
+ */
106
+ retryDelay: number;
107
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"options.js","sourceRoot":"","sources":["../../../src/client/sync/options.ts"],"names":[],"mappings":"AAqDA;;GAEG;AACH,MAAM,CAAN,IAAY,0BAGX;AAHD,WAAY,0BAA0B;IACpC,2CAAa,CAAA;IACb,uDAAyB,CAAA;AAC3B,CAAC,EAHW,0BAA0B,KAA1B,0BAA0B,QAGrC;AAED;;GAEG;AACH,MAAM,CAAN,IAAY,aAYX;AAZD,WAAY,aAAa;IACvB;;;OAGG;IACH,sCAAqB,CAAA;IAErB;;;OAGG;IACH,0CAAyB,CAAA;AAC3B,CAAC,EAZW,aAAa,KAAb,aAAa,QAYxB"}
1
+ {"version":3,"file":"options.js","sourceRoot":"","sources":["../../../src/client/sync/options.ts"],"names":[],"mappings":"AAmEA;;GAEG;AACH,MAAM,CAAN,IAAY,0BAGX;AAHD,WAAY,0BAA0B;IACpC,2CAAa,CAAA;IACb,uDAAyB,CAAA;AAC3B,CAAC,EAHW,0BAA0B,KAA1B,0BAA0B,QAGrC;AAED;;GAEG;AACH,MAAM,CAAN,IAAY,aAYX;AAZD,WAAY,aAAa;IACvB;;;OAGG;IACH,sCAAqB,CAAA;IAErB;;;OAGG;IACH,0CAAyB,CAAA;AAC3B,CAAC,EAZW,aAAa,KAAb,aAAa,QAYxB"}
@@ -82,7 +82,7 @@ export interface SyncStatus {
82
82
  */
83
83
  get hasSynced(): boolean | undefined;
84
84
  /**
85
- * All sync streams currently being tracked in teh database.
85
+ * All sync streams currently being tracked in the database.
86
86
  *
87
87
  * This returns null when the database is currently being opened and we don't have reliable information about all
88
88
  * included streams yet.
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';
@@ -13,9 +14,10 @@ export * from './client/SQLOpenFactory.js';
13
14
  export * from './client/sync/bucket/CrudBatch.js';
14
15
  export { CrudEntry, OpId, UpdateType } from './client/sync/bucket/CrudEntry.js';
15
16
  export * from './client/sync/bucket/CrudTransaction.js';
17
+ export * from './client/sync/CheckpointRequest.js';
16
18
  export * from './client/sync/stream/JsonValue.js';
17
19
  export * from './client/sync/sync-streams.js';
18
- export { SyncOptions, SyncStreamConnectionMethod, FetchStrategy } from './client/sync/options.js';
20
+ export { SyncOptions, SyncStreamConnectionMethod, FetchStrategy, CheckpointMode, CheckpointRequestsOptions } from './client/sync/options.js';
19
21
  export { ProgressWithOperations, SyncProgress } from './db/crud/SyncProgress.js';
20
22
  export * from './db/crud/SyncStatus.js';
21
23
  export * from './db/crud/UploadQueueStatus.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';
@@ -13,6 +14,7 @@ export * from './client/SQLOpenFactory.js';
13
14
  export * from './client/sync/bucket/CrudBatch.js';
14
15
  export { UpdateType } from './client/sync/bucket/CrudEntry.js';
15
16
  export * from './client/sync/bucket/CrudTransaction.js';
17
+ export * from './client/sync/CheckpointRequest.js';
16
18
  export * from './client/sync/stream/JsonValue.js';
17
19
  export * from './client/sync/sync-streams.js';
18
20
  export { SyncStreamConnectionMethod, FetchStrategy } from './client/sync/options.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,oCAAoC,CAAC;AACnD,cAAc,mCAAmC,CAAC;AAClD,cAAc,+BAA+B,CAAC;AAC9C,OAAO,EAEL,0BAA0B,EAC1B,aAAa,EAGd,MAAM,0BAA0B,CAAC;AAGlC,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": "0.0.0-dev-20260630144038",
3
+ "version": "0.0.0-dev-20261015114518",
4
4
  "publishConfig": {
5
5
  "registry": "https://registry.npmjs.org/",
6
6
  "access": "public"
@@ -32,13 +32,14 @@
32
32
  "devDependencies": {
33
33
  "@types/node": "^24.0.0",
34
34
  "@types/uuid": "^9.0.6",
35
- "@microsoft/api-extractor": "^7.58.7"
35
+ "@microsoft/api-extractor": "^7.59.0"
36
36
  },
37
37
  "scripts": {
38
38
  "build": "tsc -b",
39
39
  "build:prod": "tsc -b",
40
40
  "clean": "rm -rf lib dist tsconfig.tsbuildinfo",
41
41
  "test": "vitest",
42
- "test:exports": "attw --pack . --ignore-rules no-resolution cjs-resolves-to-esm"
42
+ "test:exports": "attw --pack . --ignore-rules no-resolution cjs-resolves-to-esm",
43
+ "api-diff": "api-extractor run --verbose"
43
44
  }
44
45
  }
@@ -231,7 +231,8 @@ export class AttachmentContext {
231
231
  );
232
232
 
233
233
  const archivedAttachments = results.map(attachmentFromSql);
234
- if (archivedAttachments.length === 0) return false;
234
+ // Nothing above the cache limit, so the paginated cleanup in `expireCache` is complete.
235
+ if (archivedAttachments.length === 0) return true;
235
236
 
236
237
  await callback?.(archivedAttachments);
237
238
  this.logger.log({