@powersync/common 0.0.0-dev-20260202162549 → 0.0.0-dev-20260216124709

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 (214) hide show
  1. package/dist/bundle.cjs +14470 -0
  2. package/dist/bundle.cjs.map +1 -0
  3. package/dist/bundle.mjs +14379 -0
  4. package/dist/bundle.mjs.map +1 -0
  5. package/dist/bundle.node.cjs +11948 -0
  6. package/dist/bundle.node.cjs.map +1 -0
  7. package/dist/bundle.node.mjs +11857 -0
  8. package/dist/bundle.node.mjs.map +1 -0
  9. package/dist/index.d.cts +4272 -0
  10. package/lib/attachments/AttachmentContext.d.ts +86 -0
  11. package/lib/attachments/AttachmentContext.js +229 -0
  12. package/lib/attachments/AttachmentContext.js.map +1 -0
  13. package/lib/attachments/AttachmentErrorHandler.d.ts +31 -0
  14. package/lib/attachments/AttachmentErrorHandler.js +2 -0
  15. package/lib/attachments/AttachmentErrorHandler.js.map +1 -0
  16. package/lib/attachments/AttachmentQueue.d.ts +149 -0
  17. package/lib/attachments/AttachmentQueue.js +362 -0
  18. package/lib/attachments/AttachmentQueue.js.map +1 -0
  19. package/lib/attachments/AttachmentService.d.ts +29 -0
  20. package/lib/attachments/AttachmentService.js +56 -0
  21. package/lib/attachments/AttachmentService.js.map +1 -0
  22. package/lib/attachments/LocalStorageAdapter.d.ts +62 -0
  23. package/lib/attachments/LocalStorageAdapter.js +6 -0
  24. package/lib/attachments/LocalStorageAdapter.js.map +1 -0
  25. package/lib/attachments/RemoteStorageAdapter.d.ts +27 -0
  26. package/lib/attachments/RemoteStorageAdapter.js +2 -0
  27. package/lib/attachments/RemoteStorageAdapter.js.map +1 -0
  28. package/lib/attachments/Schema.d.ts +50 -0
  29. package/lib/attachments/Schema.js +62 -0
  30. package/lib/attachments/Schema.js.map +1 -0
  31. package/lib/attachments/SyncingService.d.ts +62 -0
  32. package/lib/attachments/SyncingService.js +168 -0
  33. package/lib/attachments/SyncingService.js.map +1 -0
  34. package/lib/attachments/WatchedAttachmentItem.d.ts +17 -0
  35. package/lib/attachments/WatchedAttachmentItem.js +2 -0
  36. package/lib/attachments/WatchedAttachmentItem.js.map +1 -0
  37. package/lib/client/AbstractPowerSyncDatabase.d.ts +615 -0
  38. package/lib/client/AbstractPowerSyncDatabase.js +983 -0
  39. package/lib/client/AbstractPowerSyncDatabase.js.map +1 -0
  40. package/lib/client/AbstractPowerSyncOpenFactory.d.ts +22 -0
  41. package/lib/client/AbstractPowerSyncOpenFactory.js +25 -0
  42. package/lib/client/AbstractPowerSyncOpenFactory.js.map +1 -0
  43. package/lib/client/ConnectionManager.d.ts +112 -0
  44. package/lib/client/ConnectionManager.js +294 -0
  45. package/lib/client/ConnectionManager.js.map +1 -0
  46. package/lib/client/CustomQuery.d.ts +22 -0
  47. package/lib/client/CustomQuery.js +43 -0
  48. package/lib/client/CustomQuery.js.map +1 -0
  49. package/lib/client/Query.d.ts +97 -0
  50. package/lib/client/Query.js +2 -0
  51. package/lib/client/Query.js.map +1 -0
  52. package/lib/client/SQLOpenFactory.d.ts +42 -0
  53. package/lib/client/SQLOpenFactory.js +20 -0
  54. package/lib/client/SQLOpenFactory.js.map +1 -0
  55. package/lib/client/compilableQueryWatch.d.ts +7 -0
  56. package/lib/client/compilableQueryWatch.js +38 -0
  57. package/lib/client/compilableQueryWatch.js.map +1 -0
  58. package/lib/client/connection/PowerSyncBackendConnector.d.ts +23 -0
  59. package/lib/client/connection/PowerSyncBackendConnector.js +2 -0
  60. package/lib/client/connection/PowerSyncBackendConnector.js.map +1 -0
  61. package/lib/client/connection/PowerSyncCredentials.d.ts +5 -0
  62. package/lib/client/connection/PowerSyncCredentials.js +2 -0
  63. package/lib/client/connection/PowerSyncCredentials.js.map +1 -0
  64. package/lib/client/constants.d.ts +1 -0
  65. package/lib/client/constants.js +2 -0
  66. package/lib/client/constants.js.map +1 -0
  67. package/lib/client/runOnSchemaChange.d.ts +2 -0
  68. package/lib/client/runOnSchemaChange.js +24 -0
  69. package/lib/client/runOnSchemaChange.js.map +1 -0
  70. package/lib/client/sync/bucket/BucketStorageAdapter.d.ts +102 -0
  71. package/lib/client/sync/bucket/BucketStorageAdapter.js +19 -0
  72. package/lib/client/sync/bucket/BucketStorageAdapter.js.map +1 -0
  73. package/lib/client/sync/bucket/CrudBatch.d.ts +31 -0
  74. package/lib/client/sync/bucket/CrudBatch.js +26 -0
  75. package/lib/client/sync/bucket/CrudBatch.js.map +1 -0
  76. package/lib/client/sync/bucket/CrudEntry.d.ts +95 -0
  77. package/lib/client/sync/bucket/CrudEntry.js +110 -0
  78. package/lib/client/sync/bucket/CrudEntry.js.map +1 -0
  79. package/lib/client/sync/bucket/CrudTransaction.d.ts +29 -0
  80. package/lib/client/sync/bucket/CrudTransaction.js +25 -0
  81. package/lib/client/sync/bucket/CrudTransaction.js.map +1 -0
  82. package/lib/client/sync/bucket/OpType.d.ts +16 -0
  83. package/lib/client/sync/bucket/OpType.js +23 -0
  84. package/lib/client/sync/bucket/OpType.js.map +1 -0
  85. package/lib/client/sync/bucket/OplogEntry.d.ts +23 -0
  86. package/lib/client/sync/bucket/OplogEntry.js +36 -0
  87. package/lib/client/sync/bucket/OplogEntry.js.map +1 -0
  88. package/lib/client/sync/bucket/SqliteBucketStorage.d.ts +61 -0
  89. package/lib/client/sync/bucket/SqliteBucketStorage.js +324 -0
  90. package/lib/client/sync/bucket/SqliteBucketStorage.js.map +1 -0
  91. package/lib/client/sync/bucket/SyncDataBatch.d.ts +6 -0
  92. package/lib/client/sync/bucket/SyncDataBatch.js +12 -0
  93. package/lib/client/sync/bucket/SyncDataBatch.js.map +1 -0
  94. package/lib/client/sync/bucket/SyncDataBucket.d.ts +40 -0
  95. package/lib/client/sync/bucket/SyncDataBucket.js +40 -0
  96. package/lib/client/sync/bucket/SyncDataBucket.js.map +1 -0
  97. package/lib/client/sync/stream/AbstractRemote.d.ts +140 -0
  98. package/lib/client/sync/stream/AbstractRemote.js +506 -0
  99. package/lib/client/sync/stream/AbstractRemote.js.map +1 -0
  100. package/lib/client/sync/stream/AbstractStreamingSyncImplementation.d.ts +240 -0
  101. package/lib/client/sync/stream/AbstractStreamingSyncImplementation.js +990 -0
  102. package/lib/client/sync/stream/AbstractStreamingSyncImplementation.js.map +1 -0
  103. package/lib/client/sync/stream/WebsocketClientTransport.d.ts +15 -0
  104. package/lib/client/sync/stream/WebsocketClientTransport.js +61 -0
  105. package/lib/client/sync/stream/WebsocketClientTransport.js.map +1 -0
  106. package/lib/client/sync/stream/core-instruction.d.ts +72 -0
  107. package/lib/client/sync/stream/core-instruction.js +27 -0
  108. package/lib/client/sync/stream/core-instruction.js.map +1 -0
  109. package/lib/client/sync/stream/streaming-sync-types.d.ts +143 -0
  110. package/lib/client/sync/stream/streaming-sync-types.js +26 -0
  111. package/lib/client/sync/stream/streaming-sync-types.js.map +1 -0
  112. package/lib/client/sync/sync-streams.d.ts +98 -0
  113. package/lib/client/sync/sync-streams.js +2 -0
  114. package/lib/client/sync/sync-streams.js.map +1 -0
  115. package/lib/client/triggers/MemoryTriggerClaimManager.d.ts +6 -0
  116. package/lib/client/triggers/MemoryTriggerClaimManager.js +21 -0
  117. package/lib/client/triggers/MemoryTriggerClaimManager.js.map +1 -0
  118. package/lib/client/triggers/TriggerManager.d.ts +459 -0
  119. package/lib/client/triggers/TriggerManager.js +11 -0
  120. package/lib/client/triggers/TriggerManager.js.map +1 -0
  121. package/lib/client/triggers/TriggerManagerImpl.d.ts +39 -0
  122. package/lib/client/triggers/TriggerManagerImpl.js +393 -0
  123. package/lib/client/triggers/TriggerManagerImpl.js.map +1 -0
  124. package/lib/client/triggers/sanitizeSQL.d.ts +34 -0
  125. package/lib/client/triggers/sanitizeSQL.js +69 -0
  126. package/lib/client/triggers/sanitizeSQL.js.map +1 -0
  127. package/lib/client/watched/GetAllQuery.d.ts +32 -0
  128. package/lib/client/watched/GetAllQuery.js +25 -0
  129. package/lib/client/watched/GetAllQuery.js.map +1 -0
  130. package/lib/client/watched/WatchedQuery.d.ts +100 -0
  131. package/lib/client/watched/WatchedQuery.js +14 -0
  132. package/lib/client/watched/WatchedQuery.js.map +1 -0
  133. package/lib/client/watched/processors/AbstractQueryProcessor.d.ts +68 -0
  134. package/lib/client/watched/processors/AbstractQueryProcessor.js +151 -0
  135. package/lib/client/watched/processors/AbstractQueryProcessor.js.map +1 -0
  136. package/lib/client/watched/processors/DifferentialQueryProcessor.d.ts +121 -0
  137. package/lib/client/watched/processors/DifferentialQueryProcessor.js +173 -0
  138. package/lib/client/watched/processors/DifferentialQueryProcessor.js.map +1 -0
  139. package/lib/client/watched/processors/OnChangeQueryProcessor.d.ts +33 -0
  140. package/lib/client/watched/processors/OnChangeQueryProcessor.js +83 -0
  141. package/lib/client/watched/processors/OnChangeQueryProcessor.js.map +1 -0
  142. package/lib/client/watched/processors/comparators.d.ts +30 -0
  143. package/lib/client/watched/processors/comparators.js +35 -0
  144. package/lib/client/watched/processors/comparators.js.map +1 -0
  145. package/lib/db/ConnectionClosedError.d.ts +10 -0
  146. package/lib/db/ConnectionClosedError.js +21 -0
  147. package/lib/db/ConnectionClosedError.js.map +1 -0
  148. package/lib/db/DBAdapter.d.ts +115 -0
  149. package/lib/db/DBAdapter.js +20 -0
  150. package/lib/db/DBAdapter.js.map +1 -0
  151. package/lib/db/crud/SyncProgress.d.ts +68 -0
  152. package/lib/db/crud/SyncProgress.js +61 -0
  153. package/lib/db/crud/SyncProgress.js.map +1 -0
  154. package/lib/db/crud/SyncStatus.d.ts +195 -0
  155. package/lib/db/crud/SyncStatus.js +250 -0
  156. package/lib/db/crud/SyncStatus.js.map +1 -0
  157. package/lib/db/crud/UploadQueueStatus.d.ts +20 -0
  158. package/lib/db/crud/UploadQueueStatus.js +25 -0
  159. package/lib/db/crud/UploadQueueStatus.js.map +1 -0
  160. package/lib/db/schema/Column.d.ts +30 -0
  161. package/lib/db/schema/Column.js +43 -0
  162. package/lib/db/schema/Column.js.map +1 -0
  163. package/lib/db/schema/Index.d.ts +22 -0
  164. package/lib/db/schema/Index.js +30 -0
  165. package/lib/db/schema/Index.js.map +1 -0
  166. package/lib/db/schema/IndexedColumn.d.ts +19 -0
  167. package/lib/db/schema/IndexedColumn.js +30 -0
  168. package/lib/db/schema/IndexedColumn.js.map +1 -0
  169. package/lib/db/schema/RawTable.d.ts +61 -0
  170. package/lib/db/schema/RawTable.js +33 -0
  171. package/lib/db/schema/RawTable.js.map +1 -0
  172. package/lib/db/schema/Schema.d.ts +54 -0
  173. package/lib/db/schema/Schema.js +61 -0
  174. package/lib/db/schema/Schema.js.map +1 -0
  175. package/lib/db/schema/Table.d.ts +157 -0
  176. package/lib/db/schema/Table.js +208 -0
  177. package/lib/db/schema/Table.js.map +1 -0
  178. package/lib/db/schema/TableV2.d.ts +9 -0
  179. package/lib/db/schema/TableV2.js +9 -0
  180. package/lib/db/schema/TableV2.js.map +1 -0
  181. package/lib/index.d.ts +62 -0
  182. package/lib/index.js +63 -0
  183. package/lib/index.js.map +1 -0
  184. package/lib/types/types.d.ts +8 -0
  185. package/lib/types/types.js +2 -0
  186. package/lib/types/types.js.map +1 -0
  187. package/lib/utils/AbortOperation.d.ts +9 -0
  188. package/lib/utils/AbortOperation.js +19 -0
  189. package/lib/utils/AbortOperation.js.map +1 -0
  190. package/lib/utils/BaseObserver.d.ts +18 -0
  191. package/lib/utils/BaseObserver.js +27 -0
  192. package/lib/utils/BaseObserver.js.map +1 -0
  193. package/lib/utils/ControlledExecutor.d.ts +25 -0
  194. package/lib/utils/ControlledExecutor.js +51 -0
  195. package/lib/utils/ControlledExecutor.js.map +1 -0
  196. package/lib/utils/DataStream.d.ts +62 -0
  197. package/lib/utils/DataStream.js +169 -0
  198. package/lib/utils/DataStream.js.map +1 -0
  199. package/lib/utils/Logger.d.ts +31 -0
  200. package/lib/utils/Logger.js +37 -0
  201. package/lib/utils/Logger.js.map +1 -0
  202. package/lib/utils/MetaBaseObserver.d.ts +29 -0
  203. package/lib/utils/MetaBaseObserver.js +51 -0
  204. package/lib/utils/MetaBaseObserver.js.map +1 -0
  205. package/lib/utils/async.d.ts +23 -0
  206. package/lib/utils/async.js +55 -0
  207. package/lib/utils/async.js.map +1 -0
  208. package/lib/utils/mutex.d.ts +7 -0
  209. package/lib/utils/mutex.js +29 -0
  210. package/lib/utils/mutex.js.map +1 -0
  211. package/lib/utils/parseQuery.d.ts +6 -0
  212. package/lib/utils/parseQuery.js +17 -0
  213. package/lib/utils/parseQuery.js.map +1 -0
  214. package/package.json +1 -1
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Type of local change.
3
+ */
4
+ export var UpdateType;
5
+ (function (UpdateType) {
6
+ /** Insert or replace existing row. All non-null columns are included in the data. Generated by INSERT statements. */
7
+ UpdateType["PUT"] = "PUT";
8
+ /** Update existing row. Contains the id, and value of each changed column. Generated by UPDATE statements. */
9
+ UpdateType["PATCH"] = "PATCH";
10
+ /** Delete existing row. Contains the id. Generated by DELETE statements. */
11
+ UpdateType["DELETE"] = "DELETE";
12
+ })(UpdateType || (UpdateType = {}));
13
+ /**
14
+ * A single client-side change.
15
+ */
16
+ export class CrudEntry {
17
+ /**
18
+ * Auto-incrementing client-side id.
19
+ */
20
+ clientId;
21
+ /**
22
+ * ID of the changed row.
23
+ */
24
+ id;
25
+ /**
26
+ * Type of change.
27
+ */
28
+ op;
29
+ /**
30
+ * Data associated with the change.
31
+ */
32
+ opData;
33
+ /**
34
+ * For tables where the `trackPreviousValues` option has been enabled, this tracks previous values for
35
+ * `UPDATE` and `DELETE` statements.
36
+ */
37
+ previousValues;
38
+ /**
39
+ * Table that contained the change.
40
+ */
41
+ table;
42
+ /**
43
+ * Auto-incrementing transaction id. This is the same for all operations within the same transaction.
44
+ */
45
+ transactionId;
46
+ /**
47
+ * Client-side metadata attached with this write.
48
+ *
49
+ * This field is only available when the `trackMetadata` option was set to `true` when creating a table
50
+ * and the insert or update statement set the `_metadata` column.
51
+ */
52
+ metadata;
53
+ static fromRow(dbRow) {
54
+ const data = JSON.parse(dbRow.data);
55
+ return new CrudEntry(parseInt(dbRow.id), data.op, data.type, data.id, dbRow.tx_id, data.data, data.old, data.metadata);
56
+ }
57
+ constructor(clientId, op, table, id, transactionId, opData, previousValues, metadata) {
58
+ this.clientId = clientId;
59
+ this.id = id;
60
+ this.op = op;
61
+ this.opData = opData;
62
+ this.table = table;
63
+ this.transactionId = transactionId;
64
+ this.previousValues = previousValues;
65
+ this.metadata = metadata;
66
+ }
67
+ /**
68
+ * Converts the change to JSON format.
69
+ */
70
+ toJSON() {
71
+ return {
72
+ op_id: this.clientId,
73
+ op: this.op,
74
+ type: this.table,
75
+ id: this.id,
76
+ tx_id: this.transactionId,
77
+ data: this.opData,
78
+ old: this.previousValues,
79
+ metadata: this.metadata
80
+ };
81
+ }
82
+ equals(entry) {
83
+ return JSON.stringify(this.toComparisonArray()) == JSON.stringify(entry.toComparisonArray());
84
+ }
85
+ /**
86
+ * The hash code for this object.
87
+ * @deprecated This should not be necessary in the JS SDK.
88
+ * Use the @see CrudEntry#equals method instead.
89
+ * TODO remove in the next major release.
90
+ */
91
+ hashCode() {
92
+ return JSON.stringify(this.toComparisonArray());
93
+ }
94
+ /**
95
+ * Generates an array for use in deep comparison operations
96
+ */
97
+ toComparisonArray() {
98
+ return [
99
+ this.transactionId,
100
+ this.clientId,
101
+ this.op,
102
+ this.table,
103
+ this.id,
104
+ this.opData,
105
+ this.previousValues,
106
+ this.metadata
107
+ ];
108
+ }
109
+ }
110
+ //# sourceMappingURL=CrudEntry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CrudEntry.js","sourceRoot":"","sources":["../../../../src/client/sync/bucket/CrudEntry.ts"],"names":[],"mappings":"AAOA;;GAEG;AACH,MAAM,CAAN,IAAY,UAOX;AAPD,WAAY,UAAU;IACpB,qHAAqH;IACrH,yBAAW,CAAA;IACX,8GAA8G;IAC9G,6BAAe,CAAA;IACf,4EAA4E;IAC5E,+BAAiB,CAAA;AACnB,CAAC,EAPW,UAAU,KAAV,UAAU,QAOrB;AA+BD;;GAEG;AACH,MAAM,OAAO,SAAS;IACpB;;OAEG;IACH,QAAQ,CAAS;IACjB;;OAEG;IACH,EAAE,CAAS;IACX;;OAEG;IACH,EAAE,CAAa;IACf;;OAEG;IACH,MAAM,CAAuB;IAE7B;;;OAGG;IACH,cAAc,CAAuB;IAErC;;OAEG;IACH,KAAK,CAAS;IACd;;OAEG;IACH,aAAa,CAAU;IAEvB;;;;;OAKG;IACH,QAAQ,CAAU;IAElB,MAAM,CAAC,OAAO,CAAC,KAAoB;QACjC,MAAM,IAAI,GAAsB,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACvD,OAAO,IAAI,SAAS,CAClB,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,EAClB,IAAI,CAAC,EAAE,EACP,IAAI,CAAC,IAAI,EACT,IAAI,CAAC,EAAE,EACP,KAAK,CAAC,KAAK,EACX,IAAI,CAAC,IAAI,EACT,IAAI,CAAC,GAAG,EACR,IAAI,CAAC,QAAQ,CACd,CAAC;IACJ,CAAC;IAED,YACE,QAAgB,EAChB,EAAc,EACd,KAAa,EACb,EAAU,EACV,aAAsB,EACtB,MAA4B,EAC5B,cAAoC,EACpC,QAAiB;QAEjB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;QACnC,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;QACrC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED;;OAEG;IACH,MAAM;QACJ,OAAO;YACL,KAAK,EAAE,IAAI,CAAC,QAAQ;YACpB,EAAE,EAAE,IAAI,CAAC,EAAE;YACX,IAAI,EAAE,IAAI,CAAC,KAAK;YAChB,EAAE,EAAE,IAAI,CAAC,EAAE;YACX,KAAK,EAAE,IAAI,CAAC,aAAa;YACzB,IAAI,EAAE,IAAI,CAAC,MAAM;YACjB,GAAG,EAAE,IAAI,CAAC,cAAc;YACxB,QAAQ,EAAE,IAAI,CAAC,QAAQ;SACxB,CAAC;IACJ,CAAC;IAED,MAAM,CAAC,KAAgB;QACrB,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,iBAAiB,EAAE,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,iBAAiB,EAAE,CAAC,CAAC;IAC/F,CAAC;IAED;;;;;OAKG;IACH,QAAQ;QACN,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,iBAAiB,EAAE,CAAC,CAAC;IAClD,CAAC;IAED;;OAEG;IACH,iBAAiB;QACf,OAAO;YACL,IAAI,CAAC,aAAa;YAClB,IAAI,CAAC,QAAQ;YACb,IAAI,CAAC,EAAE;YACP,IAAI,CAAC,KAAK;YACV,IAAI,CAAC,EAAE;YACP,IAAI,CAAC,MAAM;YACX,IAAI,CAAC,cAAc;YACnB,IAAI,CAAC,QAAQ;SACd,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,29 @@
1
+ import { CrudBatch } from './CrudBatch.js';
2
+ import { CrudEntry } from './CrudEntry.js';
3
+ export declare class CrudTransaction extends CrudBatch {
4
+ /**
5
+ * List of client-side changes.
6
+ */
7
+ crud: CrudEntry[];
8
+ /**
9
+ * Call to remove the changes from the local queue, once successfully uploaded.
10
+ */
11
+ complete: (checkpoint?: string) => Promise<void>;
12
+ /**
13
+ * If null, this contains a list of changes recorded without an explicit transaction associated.
14
+ */
15
+ transactionId?: number | undefined;
16
+ constructor(
17
+ /**
18
+ * List of client-side changes.
19
+ */
20
+ crud: CrudEntry[],
21
+ /**
22
+ * Call to remove the changes from the local queue, once successfully uploaded.
23
+ */
24
+ complete: (checkpoint?: string) => Promise<void>,
25
+ /**
26
+ * If null, this contains a list of changes recorded without an explicit transaction associated.
27
+ */
28
+ transactionId?: number | undefined);
29
+ }
@@ -0,0 +1,25 @@
1
+ import { CrudBatch } from './CrudBatch.js';
2
+ export class CrudTransaction extends CrudBatch {
3
+ crud;
4
+ complete;
5
+ transactionId;
6
+ constructor(
7
+ /**
8
+ * List of client-side changes.
9
+ */
10
+ crud,
11
+ /**
12
+ * Call to remove the changes from the local queue, once successfully uploaded.
13
+ */
14
+ complete,
15
+ /**
16
+ * If null, this contains a list of changes recorded without an explicit transaction associated.
17
+ */
18
+ transactionId) {
19
+ super(crud, false, complete);
20
+ this.crud = crud;
21
+ this.complete = complete;
22
+ this.transactionId = transactionId;
23
+ }
24
+ }
25
+ //# sourceMappingURL=CrudTransaction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CrudTransaction.js","sourceRoot":"","sources":["../../../../src/client/sync/bucket/CrudTransaction.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAG3C,MAAM,OAAO,eAAgB,SAAQ,SAAS;IAKnC;IAIA;IAIA;IAZT;IACE;;OAEG;IACI,IAAiB;IACxB;;OAEG;IACI,QAAgD;IACvD;;OAEG;IACI,aAAsB;QAE7B,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;QAVtB,SAAI,GAAJ,IAAI,CAAa;QAIjB,aAAQ,GAAR,QAAQ,CAAwC;QAIhD,kBAAa,GAAb,aAAa,CAAS;IAG/B,CAAC;CACF"}
@@ -0,0 +1,16 @@
1
+ export declare enum OpTypeEnum {
2
+ CLEAR = 1,
3
+ MOVE = 2,
4
+ PUT = 3,
5
+ REMOVE = 4
6
+ }
7
+ export type OpTypeJSON = string;
8
+ /**
9
+ * Used internally for sync buckets.
10
+ */
11
+ export declare class OpType {
12
+ value: OpTypeEnum;
13
+ static fromJSON(jsonValue: OpTypeJSON): OpType;
14
+ constructor(value: OpTypeEnum);
15
+ toJSON(): string;
16
+ }
@@ -0,0 +1,23 @@
1
+ export var OpTypeEnum;
2
+ (function (OpTypeEnum) {
3
+ OpTypeEnum[OpTypeEnum["CLEAR"] = 1] = "CLEAR";
4
+ OpTypeEnum[OpTypeEnum["MOVE"] = 2] = "MOVE";
5
+ OpTypeEnum[OpTypeEnum["PUT"] = 3] = "PUT";
6
+ OpTypeEnum[OpTypeEnum["REMOVE"] = 4] = "REMOVE";
7
+ })(OpTypeEnum || (OpTypeEnum = {}));
8
+ /**
9
+ * Used internally for sync buckets.
10
+ */
11
+ export class OpType {
12
+ value;
13
+ static fromJSON(jsonValue) {
14
+ return new OpType(OpTypeEnum[jsonValue]);
15
+ }
16
+ constructor(value) {
17
+ this.value = value;
18
+ }
19
+ toJSON() {
20
+ return Object.entries(OpTypeEnum).find(([, value]) => value === this.value)[0];
21
+ }
22
+ }
23
+ //# sourceMappingURL=OpType.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OpType.js","sourceRoot":"","sources":["../../../../src/client/sync/bucket/OpType.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAY,UAKX;AALD,WAAY,UAAU;IACpB,6CAAS,CAAA;IACT,2CAAQ,CAAA;IACR,yCAAO,CAAA;IACP,+CAAU,CAAA;AACZ,CAAC,EALW,UAAU,KAAV,UAAU,QAKrB;AAID;;GAEG;AACH,MAAM,OAAO,MAAM;IAKE;IAJnB,MAAM,CAAC,QAAQ,CAAC,SAAqB;QACnC,OAAO,IAAI,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC;IAC3C,CAAC;IAED,YAAmB,KAAiB;QAAjB,UAAK,GAAL,KAAK,CAAY;IAAG,CAAC;IAExC,MAAM;QACJ,OAAO,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,CAAE,CAAC,CAAC,CAAC,CAAC;IAClF,CAAC;CACF"}
@@ -0,0 +1,23 @@
1
+ import { OpId } from './CrudEntry.js';
2
+ import { OpType, OpTypeJSON } from './OpType.js';
3
+ export interface OplogEntryJSON {
4
+ checksum: number;
5
+ data?: string;
6
+ object_id?: string;
7
+ object_type?: string;
8
+ op_id: string;
9
+ op: OpTypeJSON;
10
+ subkey?: string;
11
+ }
12
+ export declare class OplogEntry {
13
+ op_id: OpId;
14
+ op: OpType;
15
+ checksum: number;
16
+ subkey?: string | undefined;
17
+ object_type?: string | undefined;
18
+ object_id?: string | undefined;
19
+ data?: string | undefined;
20
+ static fromRow(row: OplogEntryJSON): OplogEntry;
21
+ constructor(op_id: OpId, op: OpType, checksum: number, subkey?: string | undefined, object_type?: string | undefined, object_id?: string | undefined, data?: string | undefined);
22
+ toJSON(fixedKeyEncoding?: boolean): OplogEntryJSON;
23
+ }
@@ -0,0 +1,36 @@
1
+ import { OpType } from './OpType.js';
2
+ export class OplogEntry {
3
+ op_id;
4
+ op;
5
+ checksum;
6
+ subkey;
7
+ object_type;
8
+ object_id;
9
+ data;
10
+ static fromRow(row) {
11
+ return new OplogEntry(row.op_id, OpType.fromJSON(row.op), row.checksum, row.subkey, row.object_type, row.object_id, row.data);
12
+ }
13
+ constructor(op_id, op, checksum, subkey, object_type, object_id, data) {
14
+ this.op_id = op_id;
15
+ this.op = op;
16
+ this.checksum = checksum;
17
+ this.subkey = subkey;
18
+ this.object_type = object_type;
19
+ this.object_id = object_id;
20
+ this.data = data;
21
+ }
22
+ toJSON(fixedKeyEncoding = false) {
23
+ return {
24
+ op_id: this.op_id,
25
+ op: this.op.toJSON(),
26
+ object_type: this.object_type,
27
+ object_id: this.object_id,
28
+ checksum: this.checksum,
29
+ data: this.data,
30
+ // Older versions of the JS SDK used to always JSON.stringify here. That has always been wrong,
31
+ // but we need to migrate gradually to not break existing databases.
32
+ subkey: fixedKeyEncoding ? this.subkey : JSON.stringify(this.subkey)
33
+ };
34
+ }
35
+ }
36
+ //# sourceMappingURL=OplogEntry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OplogEntry.js","sourceRoot":"","sources":["../../../../src/client/sync/bucket/OplogEntry.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAc,MAAM,aAAa,CAAC;AAYjD,MAAM,OAAO,UAAU;IAcZ;IACA;IACA;IACA;IACA;IACA;IACA;IAnBT,MAAM,CAAC,OAAO,CAAC,GAAmB;QAChC,OAAO,IAAI,UAAU,CACnB,GAAG,CAAC,KAAK,EACT,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,EACvB,GAAG,CAAC,QAAQ,EACZ,GAAG,CAAC,MAAM,EACV,GAAG,CAAC,WAAW,EACf,GAAG,CAAC,SAAS,EACb,GAAG,CAAC,IAAI,CACT,CAAC;IACJ,CAAC;IAED,YACS,KAAW,EACX,EAAU,EACV,QAAgB,EAChB,MAAe,EACf,WAAoB,EACpB,SAAkB,EAClB,IAAa;QANb,UAAK,GAAL,KAAK,CAAM;QACX,OAAE,GAAF,EAAE,CAAQ;QACV,aAAQ,GAAR,QAAQ,CAAQ;QAChB,WAAM,GAAN,MAAM,CAAS;QACf,gBAAW,GAAX,WAAW,CAAS;QACpB,cAAS,GAAT,SAAS,CAAS;QAClB,SAAI,GAAJ,IAAI,CAAS;IACnB,CAAC;IAEJ,MAAM,CAAC,gBAAgB,GAAG,KAAK;QAC7B,OAAO;YACL,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,EAAE,EAAE,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE;YACpB,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,+FAA+F;YAC/F,oEAAoE;YACpE,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC;SACrE,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,61 @@
1
+ import { ILogger } from 'js-logger';
2
+ import { DBAdapter, Transaction } from '../../../db/DBAdapter.js';
3
+ import { BaseObserver } from '../../../utils/BaseObserver.js';
4
+ import { BucketOperationProgress, BucketState, BucketStorageAdapter, BucketStorageListener, Checkpoint, PowerSyncControlCommand, SyncLocalDatabaseResult } from './BucketStorageAdapter.js';
5
+ import { CrudBatch } from './CrudBatch.js';
6
+ import { CrudEntry } from './CrudEntry.js';
7
+ import { SyncDataBatch } from './SyncDataBatch.js';
8
+ export declare class SqliteBucketStorage extends BaseObserver<BucketStorageListener> implements BucketStorageAdapter {
9
+ private db;
10
+ private logger;
11
+ tableNames: Set<string>;
12
+ private _hasCompletedSync;
13
+ private updateListener;
14
+ private _clientId?;
15
+ constructor(db: DBAdapter, logger?: ILogger);
16
+ init(): Promise<void>;
17
+ dispose(): Promise<void>;
18
+ _getClientId(): Promise<string>;
19
+ getClientId(): Promise<string>;
20
+ getMaxOpId(): string;
21
+ /**
22
+ * Reset any caches.
23
+ */
24
+ startSession(): void;
25
+ getBucketStates(): Promise<BucketState[]>;
26
+ getBucketOperationProgress(): Promise<BucketOperationProgress>;
27
+ saveSyncData(batch: SyncDataBatch, fixedKeyFormat?: boolean): Promise<void>;
28
+ removeBuckets(buckets: string[]): Promise<void>;
29
+ /**
30
+ * Mark a bucket for deletion.
31
+ */
32
+ private deleteBucket;
33
+ hasCompletedSync(): Promise<boolean>;
34
+ syncLocalDatabase(checkpoint: Checkpoint, priority?: number): Promise<SyncLocalDatabaseResult>;
35
+ /**
36
+ * Atomically update the local state to the current checkpoint.
37
+ *
38
+ * This includes creating new tables, dropping old tables, and copying data over from the oplog.
39
+ */
40
+ private updateObjectsFromBuckets;
41
+ validateChecksums(checkpoint: Checkpoint, priority: number | undefined): Promise<SyncLocalDatabaseResult>;
42
+ updateLocalTarget(cb: () => Promise<string>): Promise<boolean>;
43
+ nextCrudItem(): Promise<CrudEntry | undefined>;
44
+ hasCrud(): Promise<boolean>;
45
+ /**
46
+ * Get a batch of objects to send to the server.
47
+ * When the objects are successfully sent to the server, call .complete()
48
+ */
49
+ getCrudBatch(limit?: number): Promise<CrudBatch | null>;
50
+ writeTransaction<T>(callback: (tx: Transaction) => Promise<T>, options?: {
51
+ timeoutMs: number;
52
+ }): Promise<T>;
53
+ /**
54
+ * Set a target checkpoint.
55
+ */
56
+ setTargetCheckpoint(checkpoint: Checkpoint): Promise<void>;
57
+ control(op: PowerSyncControlCommand, payload: string | Uint8Array | ArrayBuffer | null): Promise<string>;
58
+ hasMigratedSubkeys(): Promise<boolean>;
59
+ migrateToFixedSubkeys(): Promise<void>;
60
+ static _subkeyMigrationKey: string;
61
+ }
@@ -0,0 +1,324 @@
1
+ import Logger from 'js-logger';
2
+ import { extractTableUpdates } from '../../../db/DBAdapter.js';
3
+ import { BaseObserver } from '../../../utils/BaseObserver.js';
4
+ import { MAX_OP_ID } from '../../constants.js';
5
+ import { PSInternalTable } from './BucketStorageAdapter.js';
6
+ import { CrudEntry } from './CrudEntry.js';
7
+ export class SqliteBucketStorage extends BaseObserver {
8
+ db;
9
+ logger;
10
+ tableNames;
11
+ _hasCompletedSync;
12
+ updateListener;
13
+ _clientId;
14
+ constructor(db, logger = Logger.get('SqliteBucketStorage')) {
15
+ super();
16
+ this.db = db;
17
+ this.logger = logger;
18
+ this._hasCompletedSync = false;
19
+ this.tableNames = new Set();
20
+ this.updateListener = db.registerListener({
21
+ tablesUpdated: (update) => {
22
+ const tables = extractTableUpdates(update);
23
+ if (tables.includes(PSInternalTable.CRUD)) {
24
+ this.iterateListeners((l) => l.crudUpdate?.());
25
+ }
26
+ }
27
+ });
28
+ }
29
+ async init() {
30
+ this._hasCompletedSync = false;
31
+ const existingTableRows = await this.db.getAll(`SELECT name FROM sqlite_master WHERE type='table' AND name GLOB 'ps_data_*'`);
32
+ for (const row of existingTableRows ?? []) {
33
+ this.tableNames.add(row.name);
34
+ }
35
+ }
36
+ async dispose() {
37
+ this.updateListener?.();
38
+ }
39
+ async _getClientId() {
40
+ const row = await this.db.get('SELECT powersync_client_id() as client_id');
41
+ return row['client_id'];
42
+ }
43
+ getClientId() {
44
+ if (this._clientId == null) {
45
+ this._clientId = this._getClientId();
46
+ }
47
+ return this._clientId;
48
+ }
49
+ getMaxOpId() {
50
+ return MAX_OP_ID;
51
+ }
52
+ /**
53
+ * Reset any caches.
54
+ */
55
+ startSession() { }
56
+ async getBucketStates() {
57
+ const result = await this.db.getAll("SELECT name as bucket, cast(last_op as TEXT) as op_id FROM ps_buckets WHERE pending_delete = 0 AND name != '$local'");
58
+ return result;
59
+ }
60
+ async getBucketOperationProgress() {
61
+ const rows = await this.db.getAll('SELECT name, count_at_last, count_since_last FROM ps_buckets');
62
+ return Object.fromEntries(rows.map((r) => [r.name, { atLast: r.count_at_last, sinceLast: r.count_since_last }]));
63
+ }
64
+ async saveSyncData(batch, fixedKeyFormat = false) {
65
+ await this.writeTransaction(async (tx) => {
66
+ for (const b of batch.buckets) {
67
+ await tx.execute('INSERT INTO powersync_operations(op, data) VALUES(?, ?)', [
68
+ 'save',
69
+ JSON.stringify({ buckets: [b.toJSON(fixedKeyFormat)] })
70
+ ]);
71
+ this.logger.debug(`Saved batch of data for bucket: ${b.bucket}, operations: ${b.data.length}`);
72
+ }
73
+ });
74
+ }
75
+ async removeBuckets(buckets) {
76
+ for (const bucket of buckets) {
77
+ await this.deleteBucket(bucket);
78
+ }
79
+ }
80
+ /**
81
+ * Mark a bucket for deletion.
82
+ */
83
+ async deleteBucket(bucket) {
84
+ await this.writeTransaction(async (tx) => {
85
+ await tx.execute('INSERT INTO powersync_operations(op, data) VALUES(?, ?)', ['delete_bucket', bucket]);
86
+ });
87
+ this.logger.debug(`Done deleting bucket ${bucket}`);
88
+ }
89
+ async hasCompletedSync() {
90
+ if (this._hasCompletedSync) {
91
+ return true;
92
+ }
93
+ const r = await this.db.get(`SELECT powersync_last_synced_at() as synced_at`);
94
+ const completed = r.synced_at != null;
95
+ if (completed) {
96
+ this._hasCompletedSync = true;
97
+ }
98
+ return completed;
99
+ }
100
+ async syncLocalDatabase(checkpoint, priority) {
101
+ const r = await this.validateChecksums(checkpoint, priority);
102
+ if (!r.checkpointValid) {
103
+ this.logger.error('Checksums failed for', r.checkpointFailures);
104
+ for (const b of r.checkpointFailures ?? []) {
105
+ await this.deleteBucket(b);
106
+ }
107
+ return { ready: false, checkpointValid: false, checkpointFailures: r.checkpointFailures };
108
+ }
109
+ if (priority == null) {
110
+ this.logger.debug(`Validated checksums checkpoint ${checkpoint.last_op_id}`);
111
+ }
112
+ else {
113
+ this.logger.debug(`Validated checksums for partial checkpoint ${checkpoint.last_op_id}, priority ${priority}`);
114
+ }
115
+ let buckets = checkpoint.buckets;
116
+ if (priority !== undefined) {
117
+ buckets = buckets.filter((b) => hasMatchingPriority(priority, b));
118
+ }
119
+ const bucketNames = buckets.map((b) => b.bucket);
120
+ await this.writeTransaction(async (tx) => {
121
+ await tx.execute(`UPDATE ps_buckets SET last_op = ? WHERE name IN (SELECT json_each.value FROM json_each(?))`, [
122
+ checkpoint.last_op_id,
123
+ JSON.stringify(bucketNames)
124
+ ]);
125
+ if (priority == null && checkpoint.write_checkpoint) {
126
+ await tx.execute("UPDATE ps_buckets SET last_op = ? WHERE name = '$local'", [checkpoint.write_checkpoint]);
127
+ }
128
+ });
129
+ const valid = await this.updateObjectsFromBuckets(checkpoint, priority);
130
+ if (!valid) {
131
+ return { ready: false, checkpointValid: true };
132
+ }
133
+ return {
134
+ ready: true,
135
+ checkpointValid: true
136
+ };
137
+ }
138
+ /**
139
+ * Atomically update the local state to the current checkpoint.
140
+ *
141
+ * This includes creating new tables, dropping old tables, and copying data over from the oplog.
142
+ */
143
+ async updateObjectsFromBuckets(checkpoint, priority) {
144
+ let arg = '';
145
+ if (priority !== undefined) {
146
+ const affectedBuckets = [];
147
+ for (const desc of checkpoint.buckets) {
148
+ if (hasMatchingPriority(priority, desc)) {
149
+ affectedBuckets.push(desc.bucket);
150
+ }
151
+ }
152
+ arg = JSON.stringify({ priority, buckets: affectedBuckets });
153
+ }
154
+ return this.writeTransaction(async (tx) => {
155
+ const { insertId: result } = await tx.execute('INSERT INTO powersync_operations(op, data) VALUES(?, ?)', [
156
+ 'sync_local',
157
+ arg
158
+ ]);
159
+ if (result == 1) {
160
+ if (priority == null) {
161
+ const bucketToCount = Object.fromEntries(checkpoint.buckets.map((b) => [b.bucket, b.count]));
162
+ // The two parameters could be replaced with one, but: https://github.com/powersync-ja/better-sqlite3/pull/6
163
+ const jsonBucketCount = JSON.stringify(bucketToCount);
164
+ await tx.execute("UPDATE ps_buckets SET count_since_last = 0, count_at_last = ?->name WHERE name != '$local' AND ?->name IS NOT NULL", [jsonBucketCount, jsonBucketCount]);
165
+ }
166
+ return true;
167
+ }
168
+ else {
169
+ return false;
170
+ }
171
+ });
172
+ }
173
+ async validateChecksums(checkpoint, priority) {
174
+ if (priority !== undefined) {
175
+ // Only validate the buckets within the priority we care about
176
+ const newBuckets = checkpoint.buckets.filter((cs) => hasMatchingPriority(priority, cs));
177
+ checkpoint = { ...checkpoint, buckets: newBuckets };
178
+ }
179
+ const rs = await this.db.execute('SELECT powersync_validate_checkpoint(?) as result', [
180
+ JSON.stringify({ ...checkpoint })
181
+ ]);
182
+ const resultItem = rs.rows?.item(0);
183
+ if (!resultItem) {
184
+ return {
185
+ checkpointValid: false,
186
+ ready: false,
187
+ checkpointFailures: []
188
+ };
189
+ }
190
+ const result = JSON.parse(resultItem['result']);
191
+ if (result['valid']) {
192
+ return { ready: true, checkpointValid: true };
193
+ }
194
+ else {
195
+ return {
196
+ checkpointValid: false,
197
+ ready: false,
198
+ checkpointFailures: result['failed_buckets']
199
+ };
200
+ }
201
+ }
202
+ async updateLocalTarget(cb) {
203
+ const rs1 = await this.db.getAll("SELECT target_op FROM ps_buckets WHERE name = '$local' AND target_op = CAST(? as INTEGER)", [MAX_OP_ID]);
204
+ if (!rs1.length) {
205
+ // Nothing to update
206
+ return false;
207
+ }
208
+ const rs = await this.db.getAll("SELECT seq FROM main.sqlite_sequence WHERE name = 'ps_crud'");
209
+ if (!rs.length) {
210
+ // Nothing to update
211
+ return false;
212
+ }
213
+ const seqBefore = rs[0]['seq'];
214
+ const opId = await cb();
215
+ return this.writeTransaction(async (tx) => {
216
+ const anyData = await tx.execute('SELECT 1 FROM ps_crud LIMIT 1');
217
+ if (anyData.rows?.length) {
218
+ // if isNotEmpty
219
+ this.logger.debug(`New data uploaded since write checkpoint ${opId} - need new write checkpoint`);
220
+ return false;
221
+ }
222
+ const rs = await tx.execute("SELECT seq FROM main.sqlite_sequence WHERE name = 'ps_crud'");
223
+ if (!rs.rows?.length) {
224
+ // assert isNotEmpty
225
+ throw new Error('SQLite Sequence should not be empty');
226
+ }
227
+ const seqAfter = rs.rows?.item(0)['seq'];
228
+ if (seqAfter != seqBefore) {
229
+ this.logger.debug(`New data uploaded since write checpoint ${opId} - need new write checkpoint (sequence updated)`);
230
+ // New crud data may have been uploaded since we got the checkpoint. Abort.
231
+ return false;
232
+ }
233
+ this.logger.debug(`Updating target write checkpoint to ${opId}`);
234
+ await tx.execute("UPDATE ps_buckets SET target_op = CAST(? as INTEGER) WHERE name='$local'", [opId]);
235
+ return true;
236
+ });
237
+ }
238
+ async nextCrudItem() {
239
+ const next = await this.db.getOptional('SELECT * FROM ps_crud ORDER BY id ASC LIMIT 1');
240
+ if (!next) {
241
+ return;
242
+ }
243
+ return CrudEntry.fromRow(next);
244
+ }
245
+ async hasCrud() {
246
+ const anyData = await this.db.getOptional('SELECT 1 FROM ps_crud LIMIT 1');
247
+ return !!anyData;
248
+ }
249
+ /**
250
+ * Get a batch of objects to send to the server.
251
+ * When the objects are successfully sent to the server, call .complete()
252
+ */
253
+ async getCrudBatch(limit = 100) {
254
+ if (!(await this.hasCrud())) {
255
+ return null;
256
+ }
257
+ const crudResult = await this.db.getAll('SELECT * FROM ps_crud ORDER BY id ASC LIMIT ?', [limit]);
258
+ const all = [];
259
+ for (const row of crudResult) {
260
+ all.push(CrudEntry.fromRow(row));
261
+ }
262
+ if (all.length === 0) {
263
+ return null;
264
+ }
265
+ const last = all[all.length - 1];
266
+ return {
267
+ crud: all,
268
+ haveMore: true,
269
+ complete: async (writeCheckpoint) => {
270
+ return this.writeTransaction(async (tx) => {
271
+ await tx.execute('DELETE FROM ps_crud WHERE id <= ?', [last.clientId]);
272
+ if (writeCheckpoint) {
273
+ const crudResult = await tx.execute('SELECT 1 FROM ps_crud LIMIT 1');
274
+ if (crudResult.rows?.length) {
275
+ await tx.execute("UPDATE ps_buckets SET target_op = CAST(? as INTEGER) WHERE name='$local'", [
276
+ writeCheckpoint
277
+ ]);
278
+ }
279
+ }
280
+ else {
281
+ await tx.execute("UPDATE ps_buckets SET target_op = CAST(? as INTEGER) WHERE name='$local'", [
282
+ this.getMaxOpId()
283
+ ]);
284
+ }
285
+ });
286
+ }
287
+ };
288
+ }
289
+ async writeTransaction(callback, options) {
290
+ return this.db.writeTransaction(callback, options);
291
+ }
292
+ /**
293
+ * Set a target checkpoint.
294
+ */
295
+ async setTargetCheckpoint(checkpoint) {
296
+ // No-op for now
297
+ }
298
+ async control(op, payload) {
299
+ return await this.writeTransaction(async (tx) => {
300
+ const [[raw]] = await tx.executeRaw('SELECT powersync_control(?, ?)', [op, payload]);
301
+ return raw;
302
+ });
303
+ }
304
+ async hasMigratedSubkeys() {
305
+ const { r } = await this.db.get('SELECT EXISTS(SELECT * FROM ps_kv WHERE key = ?) as r', [
306
+ SqliteBucketStorage._subkeyMigrationKey
307
+ ]);
308
+ return r != 0;
309
+ }
310
+ async migrateToFixedSubkeys() {
311
+ await this.writeTransaction(async (tx) => {
312
+ await tx.execute('UPDATE ps_oplog SET key = powersync_remove_duplicate_key_encoding(key);');
313
+ await tx.execute('INSERT OR REPLACE INTO ps_kv (key, value) VALUES (?, ?);', [
314
+ SqliteBucketStorage._subkeyMigrationKey,
315
+ '1'
316
+ ]);
317
+ });
318
+ }
319
+ static _subkeyMigrationKey = 'powersync_js_migrated_subkeys';
320
+ }
321
+ function hasMatchingPriority(priority, bucket) {
322
+ return bucket.priority != null && bucket.priority <= priority;
323
+ }
324
+ //# sourceMappingURL=SqliteBucketStorage.js.map