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

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,393 @@
1
+ import { DEFAULT_WATCH_THROTTLE_MS } from '../watched/WatchedQuery.js';
2
+ import { DiffTriggerOperation } from './TriggerManager.js';
3
+ export const DEFAULT_TRIGGER_MANAGER_CONFIGURATION = {
4
+ useStorageByDefault: false
5
+ };
6
+ const TRIGGER_CLEANUP_INTERVAL_MS = 120_000; // 2 minutes
7
+ /**
8
+ * @internal
9
+ * @experimental
10
+ */
11
+ export class TriggerManagerImpl {
12
+ options;
13
+ schema;
14
+ defaultConfig;
15
+ cleanupTimeout;
16
+ isDisposed;
17
+ constructor(options) {
18
+ this.options = options;
19
+ this.schema = options.schema;
20
+ options.db.registerListener({
21
+ schemaChanged: (schema) => {
22
+ this.schema = schema;
23
+ }
24
+ });
25
+ this.isDisposed = false;
26
+ /**
27
+ * Configure a cleanup to run on an interval.
28
+ * The interval is configured using setTimeout to take the async
29
+ * execution time of the callback into account.
30
+ */
31
+ this.defaultConfig = DEFAULT_TRIGGER_MANAGER_CONFIGURATION;
32
+ const cleanupCallback = async () => {
33
+ this.cleanupTimeout = null;
34
+ if (this.isDisposed) {
35
+ return;
36
+ }
37
+ try {
38
+ await this.cleanupResources();
39
+ }
40
+ catch (ex) {
41
+ this.db.logger.error(`Caught error while attempting to cleanup triggers`, ex);
42
+ }
43
+ finally {
44
+ // if not closed, set another timeout
45
+ if (this.isDisposed) {
46
+ return;
47
+ }
48
+ this.cleanupTimeout = setTimeout(cleanupCallback, TRIGGER_CLEANUP_INTERVAL_MS);
49
+ }
50
+ };
51
+ this.cleanupTimeout = setTimeout(cleanupCallback, TRIGGER_CLEANUP_INTERVAL_MS);
52
+ }
53
+ get db() {
54
+ return this.options.db;
55
+ }
56
+ async getUUID() {
57
+ const { id: uuid } = await this.db.get(/* sql */ `
58
+ SELECT
59
+ uuid () as id
60
+ `);
61
+ // Replace dashes with underscores for SQLite table/trigger name compatibility
62
+ return uuid.replace(/-/g, '_');
63
+ }
64
+ async removeTriggers(tx, triggerIds) {
65
+ for (const triggerId of triggerIds) {
66
+ await tx.execute(/* sql */ `DROP TRIGGER IF EXISTS ${triggerId}; `);
67
+ }
68
+ }
69
+ dispose() {
70
+ this.isDisposed = true;
71
+ if (this.cleanupTimeout) {
72
+ clearTimeout(this.cleanupTimeout);
73
+ }
74
+ }
75
+ /**
76
+ * Updates default config settings for platform specific use-cases.
77
+ */
78
+ updateDefaults(config) {
79
+ this.defaultConfig = {
80
+ ...this.defaultConfig,
81
+ ...config
82
+ };
83
+ }
84
+ generateTriggerName(operation, destinationTable, triggerId) {
85
+ return `__ps_temp_trigger_${operation.toLowerCase()}__${destinationTable}__${triggerId}`;
86
+ }
87
+ /**
88
+ * Cleanup any SQLite triggers or tables that are no longer in use.
89
+ */
90
+ async cleanupResources() {
91
+ // we use the database here since cleanupResources is called during the PowerSyncDatabase initialization
92
+ await this.db.database.writeLock(async (ctx) => {
93
+ /**
94
+ * Note: We only cleanup persisted triggers. These are tracked in the sqlite_master table.
95
+ * temporary triggers will not be affected by this.
96
+ * Query all triggers that match our naming pattern
97
+ */
98
+ const triggers = await ctx.getAll(/* sql */ `
99
+ SELECT
100
+ name
101
+ FROM
102
+ sqlite_master
103
+ WHERE
104
+ type = 'trigger'
105
+ AND name LIKE '__ps_temp_trigger_%'
106
+ `);
107
+ /** Use regex to extract table names and IDs from trigger names
108
+ * Trigger naming convention: __ps_temp_trigger_<operation>__<destination_table>__<id>
109
+ */
110
+ const triggerPattern = /^__ps_temp_trigger_(?:insert|update|delete)__(.+)__([a-f0-9_]{36})$/i;
111
+ const trackedItems = new Map();
112
+ for (const trigger of triggers) {
113
+ const match = trigger.name.match(triggerPattern);
114
+ if (match) {
115
+ const [, table, id] = match;
116
+ // Collect all trigger names for each id combo
117
+ const existing = trackedItems.get(id);
118
+ if (existing) {
119
+ existing.triggerNames.push(trigger.name);
120
+ }
121
+ else {
122
+ trackedItems.set(id, { table, id, triggerNames: [trigger.name] });
123
+ }
124
+ }
125
+ }
126
+ for (const trackedItem of trackedItems.values()) {
127
+ // check if there is anything holding on to this item
128
+ const hasClaim = await this.options.claimManager.checkClaim(trackedItem.id);
129
+ if (hasClaim) {
130
+ // This does not require cleanup
131
+ continue;
132
+ }
133
+ this.db.logger.debug(`Clearing resources for trigger ${trackedItem.id} with table ${trackedItem.table}`);
134
+ // We need to delete the triggers and table
135
+ for (const triggerName of trackedItem.triggerNames) {
136
+ await ctx.execute(`DROP TRIGGER IF EXISTS ${triggerName}`);
137
+ }
138
+ await ctx.execute(`DROP TABLE IF EXISTS ${trackedItem.table}`);
139
+ }
140
+ });
141
+ }
142
+ async createDiffTrigger(options) {
143
+ await this.db.waitForReady();
144
+ const { source, destination, columns, when, hooks,
145
+ // Fall back to the provided default if not given on this level
146
+ useStorage = this.defaultConfig.useStorageByDefault } = options;
147
+ const operations = Object.keys(when);
148
+ if (operations.length == 0) {
149
+ throw new Error('At least one WHEN operation must be specified for the trigger.');
150
+ }
151
+ /**
152
+ * The clause to use when executing
153
+ * CREATE ${tableTriggerTypeClause} TABLE
154
+ * OR
155
+ * CREATE ${tableTriggerTypeClause} TRIGGER
156
+ */
157
+ const tableTriggerTypeClause = !useStorage ? 'TEMP' : '';
158
+ const whenClauses = Object.fromEntries(Object.entries(when).map(([operation, filter]) => [operation, `WHEN ${filter}`]));
159
+ /**
160
+ * Allow specifying the View name as the source.
161
+ * We can lookup the internal table name from the schema.
162
+ */
163
+ const sourceDefinition = this.schema.tables.find((table) => table.viewName == source);
164
+ if (!sourceDefinition) {
165
+ throw new Error(`Source table or view "${source}" not found in the schema.`);
166
+ }
167
+ const replicatedColumns = columns ?? sourceDefinition.columns.map((col) => col.name);
168
+ const internalSource = sourceDefinition.internalName;
169
+ const triggerIds = [];
170
+ const id = await this.getUUID();
171
+ const releaseStorageClaim = useStorage ? await this.options.claimManager.obtainClaim(id) : null;
172
+ /**
173
+ * We default to replicating all columns if no columns array is provided.
174
+ */
175
+ const jsonFragment = (source = 'NEW') => {
176
+ if (columns == null) {
177
+ // Track all columns
178
+ return `${source}.data`;
179
+ }
180
+ else if (columns.length == 0) {
181
+ // Don't track any columns except for the id
182
+ return `'{}'`;
183
+ }
184
+ else {
185
+ // Filter the data by the replicated columns
186
+ return `json_object(${replicatedColumns.map((col) => `'${col}', json_extract(${source}.data, '$.${col}')`).join(', ')})`;
187
+ }
188
+ };
189
+ const disposeWarningListener = this.db.registerListener({
190
+ schemaChanged: () => {
191
+ this.db.logger.warn(`The PowerSync schema has changed while previously configured triggers are still operational. This might cause unexpected results.`);
192
+ }
193
+ });
194
+ /**
195
+ * Declare the cleanup function early since if any of the init steps fail,
196
+ * we need to ensure we can cleanup the created resources.
197
+ * We unfortunately cannot rely on transaction rollback.
198
+ */
199
+ const cleanup = async () => {
200
+ disposeWarningListener();
201
+ return this.db.writeLock(async (tx) => {
202
+ await this.removeTriggers(tx, triggerIds);
203
+ await tx.execute(/* sql */ `DROP TABLE IF EXISTS ${destination};`);
204
+ await releaseStorageClaim?.();
205
+ });
206
+ };
207
+ const setup = async (tx) => {
208
+ // Allow user code to execute in this lock context before the trigger is created.
209
+ await hooks?.beforeCreate?.(tx);
210
+ await tx.execute(/* sql */ `
211
+ CREATE ${tableTriggerTypeClause} TABLE ${destination} (
212
+ operation_id INTEGER PRIMARY KEY AUTOINCREMENT,
213
+ id TEXT,
214
+ operation TEXT,
215
+ timestamp TEXT,
216
+ value TEXT,
217
+ previous_value TEXT
218
+ )
219
+ `);
220
+ if (operations.includes(DiffTriggerOperation.INSERT)) {
221
+ const insertTriggerId = this.generateTriggerName(DiffTriggerOperation.INSERT, destination, id);
222
+ triggerIds.push(insertTriggerId);
223
+ await tx.execute(/* sql */ `
224
+ CREATE ${tableTriggerTypeClause} TRIGGER ${insertTriggerId} AFTER INSERT ON ${internalSource} ${whenClauses[DiffTriggerOperation.INSERT]} BEGIN
225
+ INSERT INTO
226
+ ${destination} (id, operation, timestamp, value)
227
+ VALUES
228
+ (
229
+ NEW.id,
230
+ 'INSERT',
231
+ strftime ('%Y-%m-%dT%H:%M:%fZ', 'now'),
232
+ ${jsonFragment('NEW')}
233
+ );
234
+
235
+ END
236
+ `);
237
+ }
238
+ if (operations.includes(DiffTriggerOperation.UPDATE)) {
239
+ const updateTriggerId = this.generateTriggerName(DiffTriggerOperation.UPDATE, destination, id);
240
+ triggerIds.push(updateTriggerId);
241
+ await tx.execute(/* sql */ `
242
+ CREATE ${tableTriggerTypeClause} TRIGGER ${updateTriggerId} AFTER
243
+ UPDATE ON ${internalSource} ${whenClauses[DiffTriggerOperation.UPDATE]} BEGIN
244
+ INSERT INTO
245
+ ${destination} (id, operation, timestamp, value, previous_value)
246
+ VALUES
247
+ (
248
+ NEW.id,
249
+ 'UPDATE',
250
+ strftime ('%Y-%m-%dT%H:%M:%fZ', 'now'),
251
+ ${jsonFragment('NEW')},
252
+ ${jsonFragment('OLD')}
253
+ );
254
+
255
+ END;
256
+ `);
257
+ }
258
+ if (operations.includes(DiffTriggerOperation.DELETE)) {
259
+ const deleteTriggerId = this.generateTriggerName(DiffTriggerOperation.DELETE, destination, id);
260
+ triggerIds.push(deleteTriggerId);
261
+ // Create delete trigger for basic JSON
262
+ await tx.execute(/* sql */ `
263
+ CREATE ${tableTriggerTypeClause} TRIGGER ${deleteTriggerId} AFTER DELETE ON ${internalSource} ${whenClauses[DiffTriggerOperation.DELETE]} BEGIN
264
+ INSERT INTO
265
+ ${destination} (id, operation, timestamp, value)
266
+ VALUES
267
+ (
268
+ OLD.id,
269
+ 'DELETE',
270
+ strftime ('%Y-%m-%dT%H:%M:%fZ', 'now'),
271
+ ${jsonFragment('OLD')}
272
+ );
273
+
274
+ END;
275
+ `);
276
+ }
277
+ };
278
+ try {
279
+ await this.db.writeLock(setup);
280
+ return cleanup;
281
+ }
282
+ catch (error) {
283
+ try {
284
+ await cleanup();
285
+ }
286
+ catch (cleanupError) {
287
+ throw new AggregateError([error, cleanupError], 'Error during operation and cleanup');
288
+ }
289
+ throw error;
290
+ }
291
+ }
292
+ async trackTableDiff(options) {
293
+ const { source, when, columns, hooks, throttleMs = DEFAULT_WATCH_THROTTLE_MS } = options;
294
+ await this.db.waitForReady();
295
+ /**
296
+ * Allow specifying the View name as the source.
297
+ * We can lookup the internal table name from the schema.
298
+ */
299
+ const sourceDefinition = this.schema.tables.find((table) => table.viewName == source);
300
+ if (!sourceDefinition) {
301
+ throw new Error(`Source table or view "${source}" not found in the schema.`);
302
+ }
303
+ // The columns to present in the onChange context methods.
304
+ // If no array is provided, we use all columns from the source table.
305
+ const contextColumns = columns ?? sourceDefinition.columns.map((col) => col.name);
306
+ const id = await this.getUUID();
307
+ const destination = `__ps_temp_track_${source}_${id}`;
308
+ // register an onChange before the trigger is created
309
+ const abortController = new AbortController();
310
+ const abortOnChange = () => abortController.abort();
311
+ this.db.onChange({
312
+ // Note that the onChange events here have their execution scheduled.
313
+ // Callbacks are throttled and are sequential.
314
+ onChange: async () => {
315
+ if (abortController.signal.aborted)
316
+ return;
317
+ // Run the handler in a write lock to keep the state of the
318
+ // destination table consistent.
319
+ await this.db.writeTransaction(async (tx) => {
320
+ const callbackResult = await options.onChange({
321
+ ...tx,
322
+ destinationTable: destination,
323
+ withDiff: async (query, params, options) => {
324
+ // Wrap the query to expose the destination table
325
+ const operationIdSelect = options?.castOperationIdAsText
326
+ ? 'id, operation, CAST(operation_id AS TEXT) as operation_id, timestamp, value, previous_value'
327
+ : '*';
328
+ const wrappedQuery = /* sql */ `
329
+ WITH
330
+ DIFF AS (
331
+ SELECT
332
+ ${operationIdSelect}
333
+ FROM
334
+ ${destination}
335
+ ORDER BY
336
+ operation_id ASC
337
+ ) ${query}
338
+ `;
339
+ return tx.getAll(wrappedQuery, params);
340
+ },
341
+ withExtractedDiff: async (query, params) => {
342
+ // Wrap the query to expose the destination table
343
+ const wrappedQuery = /* sql */ `
344
+ WITH
345
+ DIFF AS (
346
+ SELECT
347
+ id,
348
+ ${contextColumns.length > 0
349
+ ? `${contextColumns.map((col) => `json_extract(value, '$.${col}') as ${col}`).join(', ')},`
350
+ : ''} operation_id as __operation_id,
351
+ operation as __operation,
352
+ timestamp as __timestamp,
353
+ previous_value as __previous_value
354
+ FROM
355
+ ${destination}
356
+ ORDER BY
357
+ __operation_id ASC
358
+ ) ${query}
359
+ `;
360
+ return tx.getAll(wrappedQuery, params);
361
+ }
362
+ });
363
+ // Clear the destination table after processing
364
+ await tx.execute(/* sql */ `DELETE FROM ${destination};`);
365
+ return callbackResult;
366
+ });
367
+ }
368
+ }, { tables: [destination], signal: abortController.signal, throttleMs });
369
+ try {
370
+ const removeTrigger = await this.createDiffTrigger({
371
+ source,
372
+ destination,
373
+ columns: contextColumns,
374
+ when,
375
+ hooks
376
+ });
377
+ return async () => {
378
+ abortOnChange();
379
+ await removeTrigger();
380
+ };
381
+ }
382
+ catch (error) {
383
+ try {
384
+ abortOnChange();
385
+ }
386
+ catch (cleanupError) {
387
+ throw new AggregateError([error, cleanupError], 'Error during operation and cleanup');
388
+ }
389
+ throw error;
390
+ }
391
+ }
392
+ }
393
+ //# sourceMappingURL=TriggerManagerImpl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TriggerManagerImpl.js","sourceRoot":"","sources":["../../../src/client/triggers/TriggerManagerImpl.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Helper function for sanitizing UUID input strings.
3
+ * Typically used with {@link sanitizeSQL}.
4
+ */
5
+ export declare function sanitizeUUID(uuid: string): string;
6
+ /**
7
+ * SQL string template function for {@link TrackDiffOptions#when} and {@link CreateDiffTriggerOptions#when}.
8
+ *
9
+ * This function performs basic string interpolation for SQLite WHEN clauses.
10
+ *
11
+ * **String placeholders:**
12
+ * - All string values passed as placeholders are automatically wrapped in single quotes (`'`).
13
+ * - Do not manually wrap placeholders in single quotes in your template string; the function will handle quoting and escaping for you.
14
+ * - Any single quotes within the string value are escaped by doubling them (`''`), as required by SQL syntax.
15
+ *
16
+ * **Other types:**
17
+ * - `null` and `undefined` are converted to SQL `NULL`.
18
+ * - Objects are stringified using `JSON.stringify()` and wrapped in single quotes, with any single quotes inside the stringified value escaped.
19
+ * - Numbers and other primitive types are inserted directly.
20
+ *
21
+ * **Usage example:**
22
+ * ```typescript
23
+ * const myID = "O'Reilly";
24
+ * const clause = sanitizeSQL`New.id = ${myID}`;
25
+ * // Result: "New.id = 'O''Reilly'"
26
+ * ```
27
+ *
28
+ * Avoid manually quoting placeholders:
29
+ * ```typescript
30
+ * // Incorrect:
31
+ * sanitizeSQL`New.id = '${myID}'` // Produces double quotes: New.id = ''O''Reilly''
32
+ * ```
33
+ */
34
+ export declare function sanitizeSQL(strings: TemplateStringsArray, ...values: any[]): string;
@@ -0,0 +1,69 @@
1
+ function sanitizeString(input) {
2
+ return `'${input.replace(/'/g, "''")}'`;
3
+ }
4
+ /**
5
+ * Helper function for sanitizing UUID input strings.
6
+ * Typically used with {@link sanitizeSQL}.
7
+ */
8
+ export function sanitizeUUID(uuid) {
9
+ const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
10
+ const isValid = uuidRegex.test(uuid);
11
+ if (!isValid) {
12
+ throw new Error(`${uuid} is not a valid UUID`);
13
+ }
14
+ return uuid;
15
+ }
16
+ /**
17
+ * SQL string template function for {@link TrackDiffOptions#when} and {@link CreateDiffTriggerOptions#when}.
18
+ *
19
+ * This function performs basic string interpolation for SQLite WHEN clauses.
20
+ *
21
+ * **String placeholders:**
22
+ * - All string values passed as placeholders are automatically wrapped in single quotes (`'`).
23
+ * - Do not manually wrap placeholders in single quotes in your template string; the function will handle quoting and escaping for you.
24
+ * - Any single quotes within the string value are escaped by doubling them (`''`), as required by SQL syntax.
25
+ *
26
+ * **Other types:**
27
+ * - `null` and `undefined` are converted to SQL `NULL`.
28
+ * - Objects are stringified using `JSON.stringify()` and wrapped in single quotes, with any single quotes inside the stringified value escaped.
29
+ * - Numbers and other primitive types are inserted directly.
30
+ *
31
+ * **Usage example:**
32
+ * ```typescript
33
+ * const myID = "O'Reilly";
34
+ * const clause = sanitizeSQL`New.id = ${myID}`;
35
+ * // Result: "New.id = 'O''Reilly'"
36
+ * ```
37
+ *
38
+ * Avoid manually quoting placeholders:
39
+ * ```typescript
40
+ * // Incorrect:
41
+ * sanitizeSQL`New.id = '${myID}'` // Produces double quotes: New.id = ''O''Reilly''
42
+ * ```
43
+ */
44
+ export function sanitizeSQL(strings, ...values) {
45
+ let result = '';
46
+ strings.forEach((str, i) => {
47
+ result += str;
48
+ if (i < values.length) {
49
+ // For SQL, escape single quotes in string values
50
+ const value = values[i];
51
+ if (typeof value == 'string') {
52
+ result += sanitizeString(value);
53
+ }
54
+ else if (value == null) {
55
+ result += 'NULL';
56
+ }
57
+ else if (typeof value == 'object') {
58
+ // Stringify the object and escape single quotes in the result
59
+ const stringified = JSON.stringify(value);
60
+ result += sanitizeString(stringified);
61
+ }
62
+ else {
63
+ result += value;
64
+ }
65
+ }
66
+ });
67
+ return result;
68
+ }
69
+ //# sourceMappingURL=sanitizeSQL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitizeSQL.js","sourceRoot":"","sources":["../../../src/client/triggers/sanitizeSQL.ts"],"names":[],"mappings":"AAAA,SAAS,cAAc,CAAC,KAAa;IACnC,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC;AAC1C,CAAC;AACD;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,MAAM,SAAS,GAAG,4EAA4E,CAAC;IAC/F,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,sBAAsB,CAAC,CAAC;IACjD,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,UAAU,WAAW,CAAC,OAA6B,EAAE,GAAG,MAAa;IACzE,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,OAAO,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;QACzB,MAAM,IAAI,GAAG,CAAC;QACd,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;YACtB,iDAAiD;YACjD,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;YACxB,IAAI,OAAO,KAAK,IAAI,QAAQ,EAAE,CAAC;gBAC7B,MAAM,IAAI,cAAc,CAAC,KAAK,CAAC,CAAC;YAClC,CAAC;iBAAM,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;gBACzB,MAAM,IAAI,MAAM,CAAC;YACnB,CAAC;iBAAM,IAAI,OAAO,KAAK,IAAI,QAAQ,EAAE,CAAC;gBACpC,8DAA8D;gBAC9D,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;gBAC1C,MAAM,IAAI,cAAc,CAAC,WAAW,CAAC,CAAC;YACxC,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAI,KAAK,CAAC;YAClB,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;IACH,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,32 @@
1
+ import { CompiledQuery } from '../../types/types.js';
2
+ import { AbstractPowerSyncDatabase } from '../AbstractPowerSyncDatabase.js';
3
+ import { WatchCompatibleQuery } from './WatchedQuery.js';
4
+ /**
5
+ * Options for {@link GetAllQuery}.
6
+ */
7
+ export type GetAllQueryOptions<RowType = unknown> = {
8
+ sql: string;
9
+ parameters?: ReadonlyArray<unknown>;
10
+ /**
11
+ * Optional mapper function to convert raw rows into the desired RowType.
12
+ * @example
13
+ * ```javascript
14
+ * (rawRow) => ({
15
+ * id: rawRow.id,
16
+ * created_at: new Date(rawRow.created_at),
17
+ * })
18
+ * ```
19
+ */
20
+ mapper?: (rawRow: Record<string, unknown>) => RowType;
21
+ };
22
+ /**
23
+ * Performs a {@link AbstractPowerSyncDatabase.getAll} operation for a watched query.
24
+ */
25
+ export declare class GetAllQuery<RowType = unknown> implements WatchCompatibleQuery<RowType[]> {
26
+ protected options: GetAllQueryOptions<RowType>;
27
+ constructor(options: GetAllQueryOptions<RowType>);
28
+ compile(): CompiledQuery;
29
+ execute(options: {
30
+ db: AbstractPowerSyncDatabase;
31
+ }): Promise<RowType[]>;
32
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Performs a {@link AbstractPowerSyncDatabase.getAll} operation for a watched query.
3
+ */
4
+ export class GetAllQuery {
5
+ options;
6
+ constructor(options) {
7
+ this.options = options;
8
+ }
9
+ compile() {
10
+ return {
11
+ sql: this.options.sql,
12
+ parameters: this.options.parameters ?? []
13
+ };
14
+ }
15
+ async execute(options) {
16
+ const { db } = options;
17
+ const { sql, parameters = [] } = this.compile();
18
+ const rawResult = await db.getAll(sql, [...parameters]);
19
+ if (this.options.mapper) {
20
+ return rawResult.map(this.options.mapper);
21
+ }
22
+ return rawResult;
23
+ }
24
+ }
25
+ //# sourceMappingURL=GetAllQuery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GetAllQuery.js","sourceRoot":"","sources":["../../../src/client/watched/GetAllQuery.ts"],"names":[],"mappings":"AAuBA;;GAEG;AACH,MAAM,OAAO,WAAW;IACA;IAAtB,YAAsB,OAAoC;QAApC,YAAO,GAAP,OAAO,CAA6B;IAAG,CAAC;IAE9D,OAAO;QACL,OAAO;YACL,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG;YACrB,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU,IAAI,EAAE;SAC1C,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,OAA0C;QACtD,MAAM,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC;QACvB,MAAM,EAAE,GAAG,EAAE,UAAU,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;QAChD,MAAM,SAAS,GAAG,MAAM,EAAE,CAAC,MAAM,CAAU,GAAG,EAAE,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC;QACjE,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;YACxB,OAAO,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC5C,CAAC;QACD,OAAO,SAAsB,CAAC;IAChC,CAAC;CACF"}