@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,459 @@
1
+ import { LockContext } from '../../db/DBAdapter.js';
2
+ /**
3
+ * SQLite operations to track changes for with {@link TriggerManager}
4
+ * @experimental
5
+ */
6
+ export declare enum DiffTriggerOperation {
7
+ INSERT = "INSERT",
8
+ UPDATE = "UPDATE",
9
+ DELETE = "DELETE"
10
+ }
11
+ /**
12
+ * @experimental
13
+ * Diffs created by {@link TriggerManager#createDiffTrigger} are stored in a temporary table.
14
+ * This is the base record structure for all diff records.
15
+ *
16
+ * @template TOperationId - The type for `operation_id`. Defaults to `number` as returned by default SQLite database queries.
17
+ * Use `string` for full 64-bit precision when using `{ castOperationIdAsText: true }` option.
18
+ */
19
+ export interface BaseTriggerDiffRecord<TOperationId extends string | number = number> {
20
+ /**
21
+ * The modified row's `id` column value.
22
+ */
23
+ id: string;
24
+ /**
25
+ * The operation performed which created this record.
26
+ */
27
+ operation: DiffTriggerOperation;
28
+ /**
29
+ * Auto-incrementing primary key for the operation.
30
+ * Defaults to number as returned by database queries (wa-sqlite returns lower 32 bits).
31
+ * Can be string for full 64-bit precision when using `{ castOperationIdAsText: true }` option.
32
+ */
33
+ operation_id: TOperationId;
34
+ /**
35
+ * Time the change operation was recorded.
36
+ * This is in ISO 8601 format, e.g. `2023-10-01T12:00:00.000Z`.
37
+ */
38
+ timestamp: string;
39
+ }
40
+ /**
41
+ * @experimental
42
+ * Represents a diff record for a SQLite UPDATE operation.
43
+ * This record contains the new value and optionally the previous value.
44
+ * Values are stored as JSON strings.
45
+ */
46
+ export interface TriggerDiffUpdateRecord<TOperationId extends string | number = number> extends BaseTriggerDiffRecord<TOperationId> {
47
+ operation: DiffTriggerOperation.UPDATE;
48
+ /**
49
+ * The updated state of the row in JSON string format.
50
+ */
51
+ value: string;
52
+ /**
53
+ * The previous value of the row in JSON string format.
54
+ */
55
+ previous_value: string;
56
+ }
57
+ /**
58
+ * @experimental
59
+ * Represents a diff record for a SQLite INSERT operation.
60
+ * This record contains the new value represented as a JSON string.
61
+ */
62
+ export interface TriggerDiffInsertRecord<TOperationId extends string | number = number> extends BaseTriggerDiffRecord<TOperationId> {
63
+ operation: DiffTriggerOperation.INSERT;
64
+ /**
65
+ * The value of the row, at the time of INSERT, in JSON string format.
66
+ */
67
+ value: string;
68
+ }
69
+ /**
70
+ * @experimental
71
+ * Represents a diff record for a SQLite DELETE operation.
72
+ * This record contains the new value represented as a JSON string.
73
+ */
74
+ export interface TriggerDiffDeleteRecord<TOperationId extends string | number = number> extends BaseTriggerDiffRecord<TOperationId> {
75
+ operation: DiffTriggerOperation.DELETE;
76
+ /**
77
+ * The value of the row, before the DELETE operation, in JSON string format.
78
+ */
79
+ value: string;
80
+ }
81
+ /**
82
+ * @experimental
83
+ * Diffs created by {@link TriggerManager#createDiffTrigger} are stored in a temporary table.
84
+ * This is the record structure for all diff records.
85
+ *
86
+ * Querying the DIFF table directly with {@link TriggerDiffHandlerContext#withDiff} will return records
87
+ * with the structure of this type.
88
+ *
89
+ * @template TOperationId - The type for `operation_id`. Defaults to `number` as returned by database queries.
90
+ * Use `string` for full 64-bit precision when using `{ castOperationIdAsText: true }` option.
91
+ *
92
+ * @example
93
+ * ```typescript
94
+ * // Default: operation_id is number
95
+ * const diffs = await context.withDiff<TriggerDiffRecord>('SELECT * FROM DIFF');
96
+ *
97
+ * // With string operation_id for full precision
98
+ * const diffsWithString = await context.withDiff<TriggerDiffRecord<string>>(
99
+ * 'SELECT * FROM DIFF',
100
+ * undefined,
101
+ * { castOperationIdAsText: true }
102
+ * );
103
+ * ```
104
+ */
105
+ export type TriggerDiffRecord<TOperationId extends string | number = number> = TriggerDiffUpdateRecord<TOperationId> | TriggerDiffInsertRecord<TOperationId> | TriggerDiffDeleteRecord<TOperationId>;
106
+ /**
107
+ * @experimental
108
+ * Querying the DIFF table directly with {@link TriggerDiffHandlerContext#withExtractedDiff} will return records
109
+ * with the tracked columns extracted from the JSON value.
110
+ * This type represents the structure of such records.
111
+ *
112
+ * @template T - The type for the extracted columns from the tracked JSON value.
113
+ * @template TOperationId - The type for `operation_id`. Defaults to `number` as returned by database queries.
114
+ * Use `string` for full 64-bit precision when using `{ castOperationIdAsText: true }` option.
115
+ *
116
+ * @example
117
+ * ```typescript
118
+ * // Default: operation_id is number
119
+ * const diffs = await context.withExtractedDiff<ExtractedTriggerDiffRecord<{id: string, name: string}>>('SELECT * FROM DIFF');
120
+ *
121
+ * // With string operation_id for full precision
122
+ * const diffsWithString = await context.withExtractedDiff<ExtractedTriggerDiffRecord<{id: string, name: string}, string>>(
123
+ * 'SELECT * FROM DIFF',
124
+ * undefined,
125
+ * { castOperationIdAsText: true }
126
+ * );
127
+ * ```
128
+ */
129
+ export type ExtractedTriggerDiffRecord<T, TOperationId extends string | number = number> = T & {
130
+ [K in keyof Omit<BaseTriggerDiffRecord<TOperationId>, 'id'> as `__${string & K}`]: TriggerDiffRecord<TOperationId>[K];
131
+ } & {
132
+ __previous_value?: string;
133
+ };
134
+ /**
135
+ * @experimental
136
+ * Hooks used in the creation of a table diff trigger.
137
+ */
138
+ export interface TriggerCreationHooks {
139
+ /**
140
+ * Executed inside a write lock before the trigger is created.
141
+ */
142
+ beforeCreate?: (context: LockContext) => Promise<void>;
143
+ }
144
+ /**
145
+ * Common interface for options used in creating a diff trigger.
146
+ */
147
+ interface BaseCreateDiffTriggerOptions {
148
+ /**
149
+ * PowerSync source table/view to trigger and track changes from.
150
+ * This should be present in the PowerSync database's schema.
151
+ */
152
+ source: string;
153
+ /**
154
+ * Columns to track and report changes for.
155
+ * Defaults to all columns in the source table.
156
+ * Use an empty array to track only the ID and operation.
157
+ */
158
+ columns?: string[];
159
+ /**
160
+ * Condition to filter when the triggers should fire.
161
+ * This corresponds to a SQLite [WHEN](https://sqlite.org/lang_createtrigger.html) clause in the trigger body.
162
+ * This is useful for only triggering on specific conditions.
163
+ * For example, you can use it to only trigger on certain values in the NEW row.
164
+ * Note that for PowerSync the row data is stored in a JSON column named `data`.
165
+ * The row id is available in the `id` column.
166
+ *
167
+ * NB! The WHEN clauses here are added directly to the SQLite trigger creation SQL.
168
+ * Any user input strings here should be sanitized externally. The {@link when} string template function performs
169
+ * some basic sanitization, extra external sanitization is recommended.
170
+ *
171
+ * @example
172
+ * {
173
+ * 'INSERT': sanitizeSQL`json_extract(NEW.data, '$.list_id') = ${sanitizeUUID(list.id)}`,
174
+ * 'INSERT': `TRUE`,
175
+ * 'UPDATE': sanitizeSQL`NEW.id = 'abcd' AND json_extract(NEW.data, '$.status') = 'active'`,
176
+ * 'DELETE': sanitizeSQL`json_extract(OLD.data, '$.list_id') = 'abcd'`
177
+ * }
178
+ */
179
+ when: Partial<Record<DiffTriggerOperation, string>>;
180
+ /**
181
+ * Hooks which allow execution during the trigger creation process.
182
+ */
183
+ hooks?: TriggerCreationHooks;
184
+ /**
185
+ * Use storage-backed (non-TEMP) tables and triggers that persist across sessions.
186
+ * These resources are still automatically disposed when no longer claimed.
187
+ */
188
+ useStorage?: boolean;
189
+ }
190
+ /**
191
+ * @experimental
192
+ * Options for {@link TriggerManager#createDiffTrigger}.
193
+ */
194
+ export interface CreateDiffTriggerOptions extends BaseCreateDiffTriggerOptions {
195
+ /**
196
+ * Destination table to send changes to.
197
+ * This table is created internally as a SQLite temporary table.
198
+ * This table will be dropped once the trigger is removed.
199
+ */
200
+ destination: string;
201
+ }
202
+ /**
203
+ * @experimental
204
+ * Callback to drop a trigger after it has been created.
205
+ */
206
+ export type TriggerRemoveCallback = () => Promise<void>;
207
+ /**
208
+ * @experimental
209
+ * Options for {@link TriggerDiffHandlerContext#withDiff}.
210
+ */
211
+ export interface WithDiffOptions {
212
+ /**
213
+ * If true, casts `operation_id` as TEXT in the internal CTE to preserve full 64-bit precision.
214
+ * Use this when you need to ensure `operation_id` is treated as a string to avoid precision loss
215
+ * for values exceeding JavaScript's Number.MAX_SAFE_INTEGER.
216
+ *
217
+ * When enabled, use {@link TriggerDiffRecord}<string> to type the result correctly.
218
+ */
219
+ castOperationIdAsText?: boolean;
220
+ }
221
+ /**
222
+ * @experimental
223
+ * Context for the `onChange` handler provided to {@link TriggerManager#trackTableDiff}.
224
+ */
225
+ export interface TriggerDiffHandlerContext extends LockContext {
226
+ /**
227
+ * The name of the temporary destination table created by the trigger.
228
+ */
229
+ destinationTable: string;
230
+ /**
231
+ * Allows querying the database with access to the table containing DIFF records.
232
+ * The diff table is accessible via the `DIFF` accessor.
233
+ *
234
+ * The `DIFF` table is of the form described in {@link TriggerManager#createDiffTrigger}
235
+ * ```sql
236
+ * CREATE TEMP DIFF (
237
+ * operation_id INTEGER PRIMARY KEY AUTOINCREMENT,
238
+ * id TEXT,
239
+ * operation TEXT,
240
+ * timestamp TEXT,
241
+ * value TEXT,
242
+ * previous_value TEXT
243
+ * );
244
+ * ```
245
+ *
246
+ * Note that the `value` and `previous_value` columns store the row state in JSON string format.
247
+ * To access the row state in an extracted form see {@link TriggerDiffHandlerContext#withExtractedDiff}.
248
+ *
249
+ * @example
250
+ * ```sql
251
+ * --- This fetches the current state of `todo` rows which have a diff operation present.
252
+ * --- The state of the row at the time of the operation is accessible in the DIFF records.
253
+ * SELECT
254
+ * todos.*
255
+ * FROM
256
+ * DIFF
257
+ * JOIN todos ON DIFF.id = todos.id
258
+ * WHERE json_extract(DIFF.value, '$.status') = 'active'
259
+ * ```
260
+ *
261
+ * @example
262
+ * ```typescript
263
+ * // With operation_id cast as TEXT for full precision
264
+ * const diffs = await context.withDiff<TriggerDiffRecord<string>>(
265
+ * 'SELECT * FROM DIFF',
266
+ * undefined,
267
+ * { castOperationIdAsText: true }
268
+ * );
269
+ * // diffs[0].operation_id is now typed as string
270
+ * ```
271
+ */
272
+ withDiff: <T = any>(query: string, params?: ReadonlyArray<Readonly<any>>, options?: WithDiffOptions) => Promise<T[]>;
273
+ /**
274
+ * Allows querying the database with access to the table containing diff records.
275
+ * The diff table is accessible via the `DIFF` accessor.
276
+ *
277
+ * This is similar to {@link withDiff} but extracts the row columns from the tracked JSON value. The diff operation
278
+ * data is aliased as `__` columns to avoid column conflicts.
279
+ *
280
+ * For {@link DiffTriggerOperation#DELETE} operations the previous_value columns are extracted for convenience.
281
+ *
282
+ *
283
+ * ```sql
284
+ * CREATE TEMP TABLE DIFF (
285
+ * id TEXT,
286
+ * replicated_column_1 COLUMN_TYPE,
287
+ * replicated_column_2 COLUMN_TYPE,
288
+ * __operation TEXT,
289
+ * __timestamp TEXT,
290
+ * __previous_value TEXT
291
+ * );
292
+ * ```
293
+ *
294
+ * @example
295
+ * ```sql
296
+ * SELECT
297
+ * todos.*
298
+ * FROM
299
+ * DIFF
300
+ * JOIN todos ON DIFF.id = todos.id
301
+ * --- The todo column names are extracted from json and are available as DIFF.name
302
+ * WHERE DIFF.name = 'example'
303
+ * ```
304
+ */
305
+ withExtractedDiff: <T = any>(query: string, params?: ReadonlyArray<Readonly<any>>) => Promise<T[]>;
306
+ }
307
+ /**
308
+ * @experimental
309
+ * Options for tracking changes to a table with {@link TriggerManager#trackTableDiff}.
310
+ */
311
+ export interface TrackDiffOptions extends BaseCreateDiffTriggerOptions {
312
+ /**
313
+ * Handler for processing diff operations.
314
+ * Automatically invoked once diff items are present.
315
+ * Diff items are automatically cleared after the handler is invoked.
316
+ */
317
+ onChange: (context: TriggerDiffHandlerContext) => Promise<void>;
318
+ /**
319
+ * The minimum interval, in milliseconds, between {@link onChange} invocations.
320
+ * @default {@link DEFAULT_WATCH_THROTTLE_MS}
321
+ */
322
+ throttleMs?: number;
323
+ }
324
+ /**
325
+ * @experimental
326
+ */
327
+ export interface TriggerManager {
328
+ /**
329
+ * @experimental
330
+ * Creates a temporary trigger which tracks changes to a source table
331
+ * and writes changes to a destination table.
332
+ * The temporary destination table is created internally and will be dropped when the trigger is removed.
333
+ * The temporary destination table is created with the structure:
334
+ *
335
+ * ```sql
336
+ * CREATE TEMP TABLE ${destination} (
337
+ * operation_id INTEGER PRIMARY KEY AUTOINCREMENT,
338
+ * id TEXT,
339
+ * operation TEXT,
340
+ * timestamp TEXT,
341
+ * value TEXT,
342
+ * previous_value TEXT
343
+ * );
344
+ * ```
345
+ * The `value` column contains the JSON representation of the row's value at the change.
346
+ *
347
+ * For {@link DiffTriggerOperation#UPDATE} operations the `previous_value` column contains the previous value of the changed row
348
+ * in a JSON format.
349
+ *
350
+ * NB: The triggers created by this method might be invalidated by {@link AbstractPowerSyncDatabase#updateSchema} calls.
351
+ * These triggers should manually be dropped and recreated when updating the schema.
352
+ *
353
+ * @returns A callback to remove the trigger and drop the destination table.
354
+ *
355
+ * @example
356
+ * ```javascript
357
+ * const dispose = await database.triggers.createDiffTrigger({
358
+ * source: 'lists',
359
+ * destination: 'ps_temp_lists_diff',
360
+ * columns: ['name'],
361
+ * when: {
362
+ * [DiffTriggerOperation.INSERT]: 'TRUE',
363
+ * [DiffTriggerOperation.UPDATE]: 'TRUE',
364
+ * [DiffTriggerOperation.DELETE]: 'TRUE'
365
+ * }
366
+ * });
367
+ * ```
368
+ */
369
+ createDiffTrigger(options: CreateDiffTriggerOptions): Promise<TriggerRemoveCallback>;
370
+ /**
371
+ * @experimental
372
+ * Tracks changes for a table. Triggering a provided handler on changes.
373
+ * Uses {@link createDiffTrigger} internally to create a temporary destination table.
374
+ *
375
+ * @returns A callback to cleanup the trigger and stop tracking changes.
376
+ *
377
+ * NB: The triggers created by this method might be invalidated by {@link AbstractPowerSyncDatabase#updateSchema} calls.
378
+ * These triggers should manually be dropped and recreated when updating the schema.
379
+ *
380
+ * @example
381
+ * ```javascript
382
+ * const dispose = database.triggers.trackTableDiff({
383
+ * source: 'todos',
384
+ * columns: ['list_id'],
385
+ * when: {
386
+ * [DiffTriggerOperation.INSERT]: sanitizeSQL`json_extract(NEW.data, '$.list_id') = ${sanitizeUUID(someIdVariable)}`
387
+ * },
388
+ * onChange: async (context) => {
389
+ * // Fetches the todo records that were inserted during this diff
390
+ * const newTodos = await context.withDiff<Database['todos']>(`
391
+ * SELECT
392
+ * todos.*
393
+ * FROM
394
+ * DIFF
395
+ * JOIN todos ON DIFF.id = todos.id
396
+ * `);
397
+ *
398
+ * // Process newly created todos
399
+ * },
400
+ * hooks: {
401
+ * beforeCreate: async (lockContext) => {
402
+ * // This hook is executed inside the write lock before the trigger is created.
403
+ * // It can be used to synchronize the current state of the table with processor logic.
404
+ * // Any changes after this callback are guaranteed to trigger the `onChange` handler.
405
+ *
406
+ * // Read the current state of the todos table
407
+ * const currentTodos = await lockContext.getAll<Database['todos']>(
408
+ * `
409
+ * SELECT
410
+ * *
411
+ * FROM
412
+ * todos
413
+ * WHERE
414
+ * list_id = ?
415
+ * `,
416
+ * ['123']
417
+ * );
418
+ *
419
+ * // Process existing todos
420
+ * }
421
+ * }
422
+ * });
423
+ * ```
424
+ */
425
+ trackTableDiff(options: TrackDiffOptions): Promise<TriggerRemoveCallback>;
426
+ }
427
+ /**
428
+ * @experimental
429
+ * @internal
430
+ * Manages claims on persisted SQLite triggers and destination tables to enable proper cleanup
431
+ * when they are no longer actively in use.
432
+ *
433
+ * When using persisted triggers (especially for OPFS multi-tab scenarios), we need a reliable way to determine which resources are still actively in use across different connections/tabs so stale resources can be safely cleaned up without interfering with active triggers.
434
+ *
435
+ * A cleanup process runs
436
+ * on database creation (and every 2 minutes) that:
437
+ * 1. Queries for existing managed persisted resources
438
+ * 2. Checks with the claim manager if any consumer is actively using those resources
439
+ * 3. Deletes unused resources
440
+ */
441
+ export interface TriggerClaimManager {
442
+ /**
443
+ * Obtains or marks a claim on a certain identifier.
444
+ * @returns a callback to release the claim.
445
+ */
446
+ obtainClaim: (identifier: string) => Promise<() => Promise<void>>;
447
+ /**
448
+ * Checks if a claim is present for an identifier.
449
+ */
450
+ checkClaim: (identifier: string) => Promise<boolean>;
451
+ }
452
+ /**
453
+ * @experimental
454
+ * @internal
455
+ */
456
+ export interface TriggerManagerConfig {
457
+ claimManager: TriggerClaimManager;
458
+ }
459
+ export {};
@@ -0,0 +1,11 @@
1
+ /**
2
+ * SQLite operations to track changes for with {@link TriggerManager}
3
+ * @experimental
4
+ */
5
+ export var DiffTriggerOperation;
6
+ (function (DiffTriggerOperation) {
7
+ DiffTriggerOperation["INSERT"] = "INSERT";
8
+ DiffTriggerOperation["UPDATE"] = "UPDATE";
9
+ DiffTriggerOperation["DELETE"] = "DELETE";
10
+ })(DiffTriggerOperation || (DiffTriggerOperation = {}));
11
+ //# sourceMappingURL=TriggerManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TriggerManager.js","sourceRoot":"","sources":["../../../src/client/triggers/TriggerManager.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,CAAN,IAAY,oBAIX;AAJD,WAAY,oBAAoB;IAC9B,yCAAiB,CAAA;IACjB,yCAAiB,CAAA;IACjB,yCAAiB,CAAA;AACnB,CAAC,EAJW,oBAAoB,KAApB,oBAAoB,QAI/B"}
@@ -0,0 +1,39 @@
1
+ import { LockContext } from '../../db/DBAdapter.js';
2
+ import { Schema } from '../../db/schema/Schema.js';
3
+ import type { AbstractPowerSyncDatabase } from '../AbstractPowerSyncDatabase.js';
4
+ import { CreateDiffTriggerOptions, DiffTriggerOperation, TrackDiffOptions, TriggerManager, TriggerManagerConfig, TriggerRemoveCallback } from './TriggerManager.js';
5
+ export type TriggerManagerImplOptions = TriggerManagerConfig & {
6
+ db: AbstractPowerSyncDatabase;
7
+ schema: Schema;
8
+ };
9
+ export type TriggerManagerImplConfiguration = {
10
+ useStorageByDefault: boolean;
11
+ };
12
+ export declare const DEFAULT_TRIGGER_MANAGER_CONFIGURATION: TriggerManagerImplConfiguration;
13
+ /**
14
+ * @internal
15
+ * @experimental
16
+ */
17
+ export declare class TriggerManagerImpl implements TriggerManager {
18
+ protected options: TriggerManagerImplOptions;
19
+ protected schema: Schema;
20
+ protected defaultConfig: TriggerManagerImplConfiguration;
21
+ protected cleanupTimeout: ReturnType<typeof setTimeout> | null;
22
+ protected isDisposed: boolean;
23
+ constructor(options: TriggerManagerImplOptions);
24
+ protected get db(): AbstractPowerSyncDatabase;
25
+ protected getUUID(): Promise<string>;
26
+ protected removeTriggers(tx: LockContext, triggerIds: string[]): Promise<void>;
27
+ dispose(): void;
28
+ /**
29
+ * Updates default config settings for platform specific use-cases.
30
+ */
31
+ updateDefaults(config: TriggerManagerImplConfiguration): void;
32
+ protected generateTriggerName(operation: DiffTriggerOperation, destinationTable: string, triggerId: string): string;
33
+ /**
34
+ * Cleanup any SQLite triggers or tables that are no longer in use.
35
+ */
36
+ cleanupResources(): Promise<void>;
37
+ createDiffTrigger(options: CreateDiffTriggerOptions): Promise<() => Promise<void>>;
38
+ trackTableDiff(options: TrackDiffOptions): Promise<TriggerRemoveCallback>;
39
+ }