@powersync/common 0.0.0-dev-20260503073249 → 0.0.0-dev-20260630141119

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 (284) hide show
  1. package/lib/attachments/AttachmentContext.d.ts +9 -8
  2. package/lib/attachments/AttachmentContext.js +8 -3
  3. package/lib/attachments/AttachmentContext.js.map +1 -1
  4. package/lib/attachments/AttachmentErrorHandler.d.ts +6 -6
  5. package/lib/attachments/AttachmentQueue.d.ts +85 -36
  6. package/lib/attachments/AttachmentQueue.js +19 -21
  7. package/lib/attachments/AttachmentQueue.js.map +1 -1
  8. package/lib/attachments/AttachmentService.d.ts +3 -3
  9. package/lib/attachments/AttachmentService.js +4 -3
  10. package/lib/attachments/AttachmentService.js.map +1 -1
  11. package/lib/attachments/LocalStorageAdapter.d.ts +14 -8
  12. package/lib/attachments/LocalStorageAdapter.js +3 -0
  13. package/lib/attachments/LocalStorageAdapter.js.map +1 -1
  14. package/lib/attachments/RemoteStorageAdapter.d.ts +4 -4
  15. package/lib/attachments/Schema.d.ts +14 -6
  16. package/lib/attachments/Schema.js +8 -3
  17. package/lib/attachments/Schema.js.map +1 -1
  18. package/lib/attachments/SyncingService.d.ts +2 -2
  19. package/lib/attachments/SyncingService.js +8 -3
  20. package/lib/attachments/SyncingService.js.map +1 -1
  21. package/lib/attachments/WatchedAttachmentItem.d.ts +3 -1
  22. package/lib/client/{AbstractPowerSyncDatabase.d.ts → CommonPowerSyncDatabase.d.ts} +112 -238
  23. package/lib/client/CommonPowerSyncDatabase.js +2 -0
  24. package/lib/client/CommonPowerSyncDatabase.js.map +1 -0
  25. package/lib/client/Query.d.ts +9 -0
  26. package/lib/client/SQLOpenFactory.d.ts +44 -10
  27. package/lib/client/SQLOpenFactory.js +1 -19
  28. package/lib/client/SQLOpenFactory.js.map +1 -1
  29. package/lib/client/compilableQueryWatch.d.ts +8 -2
  30. package/lib/client/compilableQueryWatch.js +4 -2
  31. package/lib/client/compilableQueryWatch.js.map +1 -1
  32. package/lib/client/connection/PowerSyncBackendConnector.d.ts +6 -3
  33. package/lib/client/connection/PowerSyncCredentials.d.ts +3 -0
  34. package/lib/client/runOnSchemaChange.d.ts +5 -2
  35. package/lib/client/runOnSchemaChange.js +3 -0
  36. package/lib/client/runOnSchemaChange.js.map +1 -1
  37. package/lib/client/sync/bucket/CrudBatch.d.ts +2 -0
  38. package/lib/client/sync/bucket/CrudBatch.js +2 -0
  39. package/lib/client/sync/bucket/CrudBatch.js.map +1 -1
  40. package/lib/client/sync/bucket/CrudEntry.d.ts +9 -31
  41. package/lib/client/sync/bucket/CrudEntry.js +2 -97
  42. package/lib/client/sync/bucket/CrudEntry.js.map +1 -1
  43. package/lib/client/sync/bucket/CrudTransaction.d.ts +3 -0
  44. package/lib/client/sync/bucket/CrudTransaction.js +3 -0
  45. package/lib/client/sync/bucket/CrudTransaction.js.map +1 -1
  46. package/lib/client/sync/options.d.ts +65 -0
  47. package/lib/client/sync/options.js +25 -0
  48. package/lib/client/sync/options.js.map +1 -0
  49. package/lib/client/sync/stream/JsonValue.d.ts +10 -0
  50. package/lib/client/sync/stream/JsonValue.js +2 -0
  51. package/lib/client/sync/stream/JsonValue.js.map +1 -0
  52. package/lib/client/sync/sync-streams.d.ts +23 -8
  53. package/lib/client/triggers/TriggerManager.d.ts +28 -56
  54. package/lib/client/triggers/TriggerManager.js +2 -1
  55. package/lib/client/triggers/TriggerManager.js.map +1 -1
  56. package/lib/client/triggers/sanitizeSQL.d.ts +4 -0
  57. package/lib/client/triggers/sanitizeSQL.js +4 -0
  58. package/lib/client/triggers/sanitizeSQL.js.map +1 -1
  59. package/lib/client/watched/GetAllQuery.d.ts +7 -3
  60. package/lib/client/watched/GetAllQuery.js +3 -1
  61. package/lib/client/watched/GetAllQuery.js.map +1 -1
  62. package/lib/client/watched/WatchedQuery.d.ts +20 -6
  63. package/lib/client/watched/WatchedQuery.js +3 -5
  64. package/lib/client/watched/WatchedQuery.js.map +1 -1
  65. package/lib/client/watched/processors/DifferentialQueryProcessor.d.ts +15 -45
  66. package/lib/client/watched/processors/DifferentialQueryProcessor.js +1 -172
  67. package/lib/client/watched/processors/DifferentialQueryProcessor.js.map +1 -1
  68. package/lib/client/watched/processors/OnChangeQueryProcessor.d.ts +4 -22
  69. package/lib/client/watched/processors/OnChangeQueryProcessor.js +1 -82
  70. package/lib/client/watched/processors/OnChangeQueryProcessor.js.map +1 -1
  71. package/lib/client/watched/processors/comparators.d.ts +8 -0
  72. package/lib/client/watched/processors/comparators.js +4 -0
  73. package/lib/client/watched/processors/comparators.js.map +1 -1
  74. package/lib/db/DBAdapter.d.ts +90 -113
  75. package/lib/db/DBAdapter.js +70 -89
  76. package/lib/db/DBAdapter.js.map +1 -1
  77. package/lib/db/QueryResult.d.ts +104 -0
  78. package/lib/db/QueryResult.js +96 -0
  79. package/lib/db/QueryResult.js.map +1 -0
  80. package/lib/db/crud/SyncProgress.d.ts +7 -14
  81. package/lib/db/crud/SyncProgress.js +1 -60
  82. package/lib/db/crud/SyncProgress.js.map +1 -1
  83. package/lib/db/crud/SyncStatus.d.ts +54 -91
  84. package/lib/db/crud/SyncStatus.js +1 -245
  85. package/lib/db/crud/SyncStatus.js.map +1 -1
  86. package/lib/db/crud/UploadQueueStatus.d.ts +3 -0
  87. package/lib/db/crud/UploadQueueStatus.js +3 -0
  88. package/lib/db/crud/UploadQueueStatus.js.map +1 -1
  89. package/lib/db/schema/Column.d.ts +22 -1
  90. package/lib/db/schema/Column.js +10 -4
  91. package/lib/db/schema/Column.js.map +1 -1
  92. package/lib/db/schema/Index.d.ts +8 -3
  93. package/lib/db/schema/Index.js +4 -1
  94. package/lib/db/schema/Index.js.map +1 -1
  95. package/lib/db/schema/IndexedColumn.d.ts +8 -3
  96. package/lib/db/schema/IndexedColumn.js +4 -1
  97. package/lib/db/schema/IndexedColumn.js.map +1 -1
  98. package/lib/db/schema/RawTable.d.ts +7 -1
  99. package/lib/db/schema/Schema.d.ts +10 -29
  100. package/lib/db/schema/Schema.js +3 -1
  101. package/lib/db/schema/Schema.js.map +1 -1
  102. package/lib/db/schema/Table.d.ts +69 -91
  103. package/lib/db/schema/Table.js +88 -87
  104. package/lib/db/schema/Table.js.map +1 -1
  105. package/lib/index.d.ts +7 -27
  106. package/lib/index.js +6 -27
  107. package/lib/index.js.map +1 -1
  108. package/lib/types/types.d.ts +6 -0
  109. package/lib/utils/BaseObserver.d.ts +12 -0
  110. package/lib/utils/BaseObserver.js +3 -0
  111. package/lib/utils/BaseObserver.js.map +1 -1
  112. package/lib/utils/Logger.d.ts +60 -22
  113. package/lib/utils/Logger.js +38 -30
  114. package/lib/utils/Logger.js.map +1 -1
  115. package/lib/utils/MetaBaseObserver.d.ts +11 -11
  116. package/lib/utils/MetaBaseObserver.js +1 -50
  117. package/lib/utils/MetaBaseObserver.js.map +1 -1
  118. package/lib/utils/mutex.d.ts +3 -45
  119. package/lib/utils/mutex.js +1 -153
  120. package/lib/utils/mutex.js.map +1 -1
  121. package/package.json +8 -42
  122. package/src/attachments/AttachmentContext.ts +15 -13
  123. package/src/attachments/AttachmentErrorHandler.ts +6 -6
  124. package/src/attachments/AttachmentQueue.ts +99 -42
  125. package/src/attachments/AttachmentService.ts +7 -6
  126. package/src/attachments/LocalStorageAdapter.ts +14 -8
  127. package/src/attachments/README.md +2 -0
  128. package/src/attachments/RemoteStorageAdapter.ts +4 -4
  129. package/src/attachments/Schema.ts +14 -6
  130. package/src/attachments/SyncingService.ts +10 -6
  131. package/src/attachments/WatchedAttachmentItem.ts +3 -1
  132. package/src/client/CommonPowerSyncDatabase.ts +540 -0
  133. package/src/client/Query.ts +9 -0
  134. package/src/client/SQLOpenFactory.ts +47 -19
  135. package/src/client/compilableQueryWatch.ts +9 -4
  136. package/src/client/connection/PowerSyncBackendConnector.ts +6 -3
  137. package/src/client/connection/PowerSyncCredentials.ts +3 -0
  138. package/src/client/runOnSchemaChange.ts +5 -2
  139. package/src/client/sync/bucket/CrudBatch.ts +2 -0
  140. package/src/client/sync/bucket/CrudEntry.ts +10 -101
  141. package/src/client/sync/bucket/CrudTransaction.ts +3 -0
  142. package/src/client/sync/options.ts +77 -0
  143. package/src/client/sync/stream/JsonValue.ts +11 -0
  144. package/src/client/sync/sync-streams.ts +23 -10
  145. package/src/client/triggers/TriggerManager.ts +29 -59
  146. package/src/client/triggers/sanitizeSQL.ts +5 -0
  147. package/src/client/watched/GetAllQuery.ts +8 -4
  148. package/src/client/watched/WatchedQuery.ts +20 -11
  149. package/src/client/watched/processors/DifferentialQueryProcessor.ts +19 -219
  150. package/src/client/watched/processors/OnChangeQueryProcessor.ts +4 -109
  151. package/src/client/watched/processors/comparators.ts +8 -0
  152. package/src/db/DBAdapter.ts +160 -175
  153. package/src/db/QueryResult.ts +195 -0
  154. package/src/db/crud/SyncProgress.ts +8 -43
  155. package/src/db/crud/SyncStatus.ts +66 -216
  156. package/src/db/crud/UploadQueueStatus.ts +3 -0
  157. package/src/db/schema/Column.ts +22 -5
  158. package/src/db/schema/Index.ts +9 -3
  159. package/src/db/schema/IndexedColumn.ts +9 -3
  160. package/src/db/schema/RawTable.ts +7 -1
  161. package/src/db/schema/Schema.ts +12 -7
  162. package/src/db/schema/Table.ts +130 -180
  163. package/src/index.ts +7 -27
  164. package/src/types/types.ts +6 -0
  165. package/src/utils/BaseObserver.ts +12 -0
  166. package/src/utils/Logger.ts +86 -31
  167. package/src/utils/MetaBaseObserver.ts +14 -60
  168. package/src/utils/mutex.ts +4 -189
  169. package/dist/bundle.cjs +0 -14781
  170. package/dist/bundle.cjs.map +0 -1
  171. package/dist/bundle.mjs +0 -14689
  172. package/dist/bundle.mjs.map +0 -1
  173. package/dist/bundle.node.cjs +0 -12258
  174. package/dist/bundle.node.cjs.map +0 -1
  175. package/dist/bundle.node.mjs +0 -12166
  176. package/dist/bundle.node.mjs.map +0 -1
  177. package/dist/index.d.cts +0 -4391
  178. package/lib/client/AbstractPowerSyncDatabase.js +0 -987
  179. package/lib/client/AbstractPowerSyncDatabase.js.map +0 -1
  180. package/lib/client/AbstractPowerSyncOpenFactory.d.ts +0 -22
  181. package/lib/client/AbstractPowerSyncOpenFactory.js +0 -25
  182. package/lib/client/AbstractPowerSyncOpenFactory.js.map +0 -1
  183. package/lib/client/ConnectionManager.d.ts +0 -112
  184. package/lib/client/ConnectionManager.js +0 -294
  185. package/lib/client/ConnectionManager.js.map +0 -1
  186. package/lib/client/CustomQuery.d.ts +0 -22
  187. package/lib/client/CustomQuery.js +0 -43
  188. package/lib/client/CustomQuery.js.map +0 -1
  189. package/lib/client/constants.d.ts +0 -1
  190. package/lib/client/constants.js +0 -2
  191. package/lib/client/constants.js.map +0 -1
  192. package/lib/client/sync/bucket/BucketStorageAdapter.d.ts +0 -102
  193. package/lib/client/sync/bucket/BucketStorageAdapter.js +0 -19
  194. package/lib/client/sync/bucket/BucketStorageAdapter.js.map +0 -1
  195. package/lib/client/sync/bucket/OpType.d.ts +0 -16
  196. package/lib/client/sync/bucket/OpType.js +0 -23
  197. package/lib/client/sync/bucket/OpType.js.map +0 -1
  198. package/lib/client/sync/bucket/OplogEntry.d.ts +0 -23
  199. package/lib/client/sync/bucket/OplogEntry.js +0 -36
  200. package/lib/client/sync/bucket/OplogEntry.js.map +0 -1
  201. package/lib/client/sync/bucket/SqliteBucketStorage.d.ts +0 -61
  202. package/lib/client/sync/bucket/SqliteBucketStorage.js +0 -324
  203. package/lib/client/sync/bucket/SqliteBucketStorage.js.map +0 -1
  204. package/lib/client/sync/bucket/SyncDataBatch.d.ts +0 -6
  205. package/lib/client/sync/bucket/SyncDataBatch.js +0 -12
  206. package/lib/client/sync/bucket/SyncDataBatch.js.map +0 -1
  207. package/lib/client/sync/bucket/SyncDataBucket.d.ts +0 -40
  208. package/lib/client/sync/bucket/SyncDataBucket.js +0 -40
  209. package/lib/client/sync/bucket/SyncDataBucket.js.map +0 -1
  210. package/lib/client/sync/stream/AbstractRemote.d.ts +0 -161
  211. package/lib/client/sync/stream/AbstractRemote.js +0 -483
  212. package/lib/client/sync/stream/AbstractRemote.js.map +0 -1
  213. package/lib/client/sync/stream/AbstractStreamingSyncImplementation.d.ts +0 -244
  214. package/lib/client/sync/stream/AbstractStreamingSyncImplementation.js +0 -990
  215. package/lib/client/sync/stream/AbstractStreamingSyncImplementation.js.map +0 -1
  216. package/lib/client/sync/stream/WebsocketClientTransport.d.ts +0 -15
  217. package/lib/client/sync/stream/WebsocketClientTransport.js +0 -61
  218. package/lib/client/sync/stream/WebsocketClientTransport.js.map +0 -1
  219. package/lib/client/sync/stream/core-instruction.d.ts +0 -72
  220. package/lib/client/sync/stream/core-instruction.js +0 -27
  221. package/lib/client/sync/stream/core-instruction.js.map +0 -1
  222. package/lib/client/sync/stream/streaming-sync-types.d.ts +0 -143
  223. package/lib/client/sync/stream/streaming-sync-types.js +0 -26
  224. package/lib/client/sync/stream/streaming-sync-types.js.map +0 -1
  225. package/lib/client/triggers/MemoryTriggerClaimManager.d.ts +0 -6
  226. package/lib/client/triggers/MemoryTriggerClaimManager.js +0 -21
  227. package/lib/client/triggers/MemoryTriggerClaimManager.js.map +0 -1
  228. package/lib/client/triggers/TriggerManagerImpl.d.ts +0 -39
  229. package/lib/client/triggers/TriggerManagerImpl.js +0 -405
  230. package/lib/client/triggers/TriggerManagerImpl.js.map +0 -1
  231. package/lib/client/watched/processors/AbstractQueryProcessor.d.ts +0 -68
  232. package/lib/client/watched/processors/AbstractQueryProcessor.js +0 -151
  233. package/lib/client/watched/processors/AbstractQueryProcessor.js.map +0 -1
  234. package/lib/db/ConnectionClosedError.d.ts +0 -10
  235. package/lib/db/ConnectionClosedError.js +0 -21
  236. package/lib/db/ConnectionClosedError.js.map +0 -1
  237. package/lib/db/schema/TableV2.d.ts +0 -9
  238. package/lib/db/schema/TableV2.js +0 -9
  239. package/lib/db/schema/TableV2.js.map +0 -1
  240. package/lib/utils/AbortOperation.d.ts +0 -9
  241. package/lib/utils/AbortOperation.js +0 -19
  242. package/lib/utils/AbortOperation.js.map +0 -1
  243. package/lib/utils/ControlledExecutor.d.ts +0 -25
  244. package/lib/utils/ControlledExecutor.js +0 -51
  245. package/lib/utils/ControlledExecutor.js.map +0 -1
  246. package/lib/utils/async.d.ts +0 -14
  247. package/lib/utils/async.js +0 -46
  248. package/lib/utils/async.js.map +0 -1
  249. package/lib/utils/parseQuery.d.ts +0 -6
  250. package/lib/utils/parseQuery.js +0 -17
  251. package/lib/utils/parseQuery.js.map +0 -1
  252. package/lib/utils/queue.d.ts +0 -16
  253. package/lib/utils/queue.js +0 -42
  254. package/lib/utils/queue.js.map +0 -1
  255. package/lib/utils/stream_transform.d.ts +0 -39
  256. package/lib/utils/stream_transform.js +0 -206
  257. package/lib/utils/stream_transform.js.map +0 -1
  258. package/src/client/AbstractPowerSyncDatabase.ts +0 -1362
  259. package/src/client/AbstractPowerSyncOpenFactory.ts +0 -39
  260. package/src/client/ConnectionManager.ts +0 -402
  261. package/src/client/CustomQuery.ts +0 -56
  262. package/src/client/constants.ts +0 -1
  263. package/src/client/sync/bucket/BucketStorageAdapter.ts +0 -118
  264. package/src/client/sync/bucket/OpType.ts +0 -23
  265. package/src/client/sync/bucket/OplogEntry.ts +0 -50
  266. package/src/client/sync/bucket/SqliteBucketStorage.ts +0 -395
  267. package/src/client/sync/bucket/SyncDataBatch.ts +0 -11
  268. package/src/client/sync/bucket/SyncDataBucket.ts +0 -49
  269. package/src/client/sync/stream/AbstractRemote.ts +0 -624
  270. package/src/client/sync/stream/AbstractStreamingSyncImplementation.ts +0 -1285
  271. package/src/client/sync/stream/WebsocketClientTransport.ts +0 -80
  272. package/src/client/sync/stream/core-instruction.ts +0 -99
  273. package/src/client/sync/stream/streaming-sync-types.ts +0 -210
  274. package/src/client/triggers/MemoryTriggerClaimManager.ts +0 -25
  275. package/src/client/triggers/TriggerManagerImpl.ts +0 -496
  276. package/src/client/watched/processors/AbstractQueryProcessor.ts +0 -226
  277. package/src/db/ConnectionClosedError.ts +0 -23
  278. package/src/db/schema/TableV2.ts +0 -9
  279. package/src/utils/AbortOperation.ts +0 -17
  280. package/src/utils/ControlledExecutor.ts +0 -72
  281. package/src/utils/async.ts +0 -50
  282. package/src/utils/parseQuery.ts +0 -25
  283. package/src/utils/queue.ts +0 -48
  284. package/src/utils/stream_transform.ts +0 -252
@@ -3,157 +3,157 @@
3
3
  * different SQLite DB implementations.
4
4
  */
5
5
 
6
- import { BaseListener, BaseObserverInterface } from '../utils/BaseObserver.js';
6
+ import { BaseListener, BaseObserver } from '../utils/BaseObserver.js';
7
+ import {
8
+ QueryResult,
9
+ queryResultFromRaw,
10
+ queryResultWithoutRows,
11
+ RawQueryResult,
12
+ SqliteRecord
13
+ } from './QueryResult.js';
7
14
 
8
15
  /**
9
- * TODO most of these types could be exported to a common `types` package
10
- * which is used by the DB adapter libraries as well.
16
+ * @public
11
17
  */
12
-
13
- /**
14
- * Object returned by SQL Query executions.
15
- */
16
- export type QueryResult = {
17
- /** Represents the auto-generated row id if applicable. */
18
- insertId?: number;
18
+ export interface DBGetUtils {
19
19
  /**
20
- * Number of affected rows reported by SQLite for a write query.
20
+ * Execute a read-only query and return results.
21
21
  *
22
- * When using the default client-side [JSON-based view system](https://docs.powersync.com/architecture/client-architecture#client-side-schema-and-sqlite-database-structure),
23
- * `rowsAffected` may be `0` for successful `UPDATE` and `DELETE` statements.
24
- * Use a `RETURNING` clause and inspect `rows` when you need to confirm which rows changed.
22
+ * @param sql - The SQL query to execute
23
+ * @param parameters - Optional array of parameters to bind to the query
24
+ * @returns An array of results
25
25
  */
26
- rowsAffected: number;
27
- /** if status is undefined or 0 this object will contain the query results */
28
- rows?: {
29
- /** Raw array with all dataset */
30
- _array: any[];
31
- /** The length of the dataset */
32
- length: number;
33
- /** A convenience function to acess the index based the row object
34
- * @param idx the row index
35
- * @returns the row structure identified by column names
36
- */
37
- item: (idx: number) => any;
38
- };
39
- };
40
-
41
- export interface DBGetUtils {
42
- /** Execute a read-only query and return results. */
43
26
  getAll<T>(sql: string, parameters?: any[]): Promise<T[]>;
44
- /** Execute a read-only query and return the first result, or null if the ResultSet is empty. */
27
+ /**
28
+ * Execute a read-only query and return the first result, or null if the ResultSet is empty.
29
+ *
30
+ * @param sql - The SQL query to execute
31
+ * @param parameters - Optional array of parameters to bind to the query
32
+ * @returns The first result if found, or null if no results are returned
33
+ */
45
34
  getOptional<T>(sql: string, parameters?: any[]): Promise<T | null>;
46
- /** Execute a read-only query and return the first result, error if the ResultSet is empty. */
35
+ /**
36
+ * Execute a read-only query and return the first result, error if the ResultSet is empty.
37
+ *
38
+ * @param sql - The SQL query to execute
39
+ * @param parameters - Optional array of parameters to bind to the query
40
+ * @returns The first result matching the query
41
+ * @throws Error if no rows are returned
42
+ */
47
43
  get<T>(sql: string, parameters?: any[]): Promise<T>;
48
44
  }
49
45
 
46
+ /**
47
+ * @public
48
+ */
50
49
  export interface SqlExecutor {
51
- /** Execute a single write statement. */
52
- execute: (query: string, params?: any[] | undefined) => Promise<QueryResult>;
53
50
  /**
54
- * Execute a single write statement and return raw results.
55
- * Unlike `execute`, which returns an object with structured key-value pairs,
56
- * `executeRaw` returns a nested array of raw values, where each row is
57
- * represented as an array of column values without field names.
51
+ * Execute a SQL write (INSERT/UPDATE/DELETE) query
52
+ * and optionally return results.
58
53
  *
59
- * Example result:
60
- *
61
- * ```[ [ '1', 'list 1', '33', 'Post content', '1' ] ]```
54
+ * When using the default client-side [JSON-based view system](https://docs.powersync.com/architecture/client-architecture#client-side-schema-and-sqlite-database-structure),
55
+ * the returned result's `rowsAffected` may be `0` for successful `UPDATE` and `DELETE` statements.
56
+ * Use a `RETURNING` clause and inspect `result.rows` when you need to confirm which rows changed.
62
57
  *
63
- * Where as `execute`'s `rows._array` would have been:
58
+ * @param sql - The SQL query to execute
59
+ * @param parameters - Optional array of parameters to bind to the query
60
+ * @returns The query result as an object with structured key-value pairs
61
+ */
62
+ execute: <T = SqliteRecord>(query: string, params?: any[] | undefined) => Promise<QueryResult<T>>;
63
+
64
+ /**
65
+ * Execute a SQL write (INSERT/UPDATE/DELETE) query directly on the database without any PowerSync processing.
66
+ * This bypasses certain PowerSync abstractions and is useful for accessing the raw database results.
64
67
  *
65
- * ```[ { id: '33', name: 'list 1', content: 'Post content', list_id: '1' } ]```
68
+ * @param sql - The SQL query to execute
69
+ * @param parameters - Optional array of parameters to bind to the query
70
+ * @returns The {@link RawQueryResult} representing each row as an array.
66
71
  */
67
- executeRaw: (query: string, params?: any[] | undefined) => Promise<any[][]>;
72
+ executeRaw: (query: string, params?: any[] | undefined) => Promise<RawQueryResult>;
68
73
 
69
- executeBatch: (query: string, params?: any[][]) => Promise<QueryResult>;
74
+ /**
75
+ * Execute a write query (INSERT/UPDATE/DELETE) multiple times with each parameter set
76
+ * and optionally return results.
77
+ * This is faster than executing separately with each parameter set.
78
+ *
79
+ * @param sql - The SQL query to execute
80
+ * @param parameters - Optional 2D array of parameter sets, where each inner array is a set of parameters for one execution
81
+ * @returns The query result
82
+ */
83
+ executeBatch: (query: string, params?: any[][]) => Promise<QueryResult<never>>;
70
84
  }
71
85
 
72
- export interface LockContext extends SqlExecutor, DBGetUtils {}
73
-
74
86
  /**
75
- * Implements {@link DBGetUtils} on a {@link SqlRunner}.
87
+ * @public
76
88
  */
77
- export function DBGetUtilsDefaultMixin<TBase extends new (...args: any[]) => Omit<SqlExecutor, 'executeBatch'>>(
78
- Base: TBase
79
- ) {
80
- return class extends Base implements DBGetUtils, SqlExecutor {
81
- async getAll<T>(sql: string, parameters?: any[]): Promise<T[]> {
82
- const res = await this.execute(sql, parameters);
83
- return res.rows?._array ?? [];
84
- }
89
+ export abstract class LockContext implements SqlExecutor, DBGetUtils {
90
+ abstract executeRaw<T>(query: string, params?: any[] | undefined): Promise<RawQueryResult>;
85
91
 
86
- async getOptional<T>(sql: string, parameters?: any[]): Promise<T | null> {
87
- const res = await this.execute(sql, parameters);
88
- return res.rows?.item(0) ?? null;
92
+ async getAll<T>(sql: string, parameters?: any[]): Promise<T[]> {
93
+ const rs = await this.execute<T>(sql, parameters);
94
+ return Array.from(rs);
95
+ }
96
+
97
+ async getOptional<T>(sql: string, parameters?: any[]): Promise<T | null> {
98
+ const { array } = await this.execute<T>(sql, parameters);
99
+ if (array.length > 0) {
100
+ return array[0];
89
101
  }
90
102
 
91
- async get<T>(sql: string, parameters?: any[]): Promise<T> {
92
- const res = await this.execute(sql, parameters);
93
- const first = res.rows?.item(0);
94
- if (!first) {
95
- throw new Error('Result set is empty');
96
- }
97
- return first;
103
+ return null;
104
+ }
105
+
106
+ async get<T>(sql: string, parameters?: any[]): Promise<T> {
107
+ const row = await this.getOptional<T>(sql, parameters);
108
+ if (row == null) {
109
+ throw new Error('Result set is empty');
98
110
  }
99
111
 
100
- async executeBatch(query: string, params: any[][] = []): Promise<QueryResult> {
101
- // If this context can run batch statements natively, use that.
102
- // @ts-ignore
103
- if (super.executeBatch) {
104
- // @ts-ignore
105
- return super.executeBatch(query, params);
106
- }
112
+ return row;
113
+ }
107
114
 
108
- // Emulate executeBatch by running statements individually.
109
- let lastInsertId: number | undefined;
110
- let rowsAffected = 0;
111
- for (const set of params) {
112
- const result = await this.execute(query, set);
113
- lastInsertId = result.insertId;
114
- rowsAffected += result.rowsAffected;
115
- }
115
+ async execute<T = SqliteRecord>(query: string, params?: any[] | undefined): Promise<QueryResult<T>> {
116
+ const raw = await this.executeRaw(query, params);
117
+ return queryResultFromRaw(raw);
118
+ }
116
119
 
117
- return {
118
- rowsAffected,
119
- insertId: lastInsertId
120
- };
120
+ async executeBatch(query: string, params: any[][] = []): Promise<QueryResult<never>> {
121
+ // Emulate executeBatch by running statements individually.
122
+ let lastInsertId: number | undefined;
123
+ let rowsAffected = 0;
124
+ for (const set of params) {
125
+ const result = await this.execute(query, set);
126
+ lastInsertId = result.insertId;
127
+ rowsAffected += result.rowsAffected ?? 0;
121
128
  }
122
- };
129
+
130
+ return queryResultWithoutRows({
131
+ rowsAffected,
132
+ insertId: lastInsertId
133
+ });
134
+ }
123
135
  }
124
136
 
137
+ /**
138
+ * @public
139
+ */
125
140
  export interface Transaction extends LockContext {
126
141
  /** Commit multiple changes to the local DB using the Transaction context. */
127
- commit: () => Promise<QueryResult>;
142
+ commit: () => Promise<void>;
128
143
  /** Roll back multiple attempted changes using the Transaction context. */
129
- rollback: () => Promise<QueryResult>;
144
+ rollback: () => Promise<void>;
130
145
  }
131
146
 
132
147
  /**
133
- * Update table operation numbers from SQLite
148
+ * @public
134
149
  */
135
- export enum RowUpdateType {
136
- SQLITE_INSERT = 18,
137
- SQLITE_DELETE = 9,
138
- SQLITE_UPDATE = 23
139
- }
140
- export interface TableUpdateOperation {
141
- opType: RowUpdateType;
142
- rowId: number;
143
- }
144
- /**
145
- * Notification of an update to one or more tables, for the purpose of realtime change notifications.
146
- */
147
- export interface UpdateNotification extends TableUpdateOperation {
148
- table: string;
149
- }
150
-
151
150
  export interface BatchedUpdateNotification {
152
- rawUpdates: UpdateNotification[];
153
151
  tables: string[];
154
- groupedUpdates: Record<string, TableUpdateOperation[]>;
155
152
  }
156
153
 
154
+ /**
155
+ * @public
156
+ */
157
157
  export interface DBAdapterListener extends BaseListener {
158
158
  /**
159
159
  * Listener for table updates.
@@ -161,105 +161,100 @@ export interface DBAdapterListener extends BaseListener {
161
161
  * without the need for a major version bump
162
162
  * The DB adapter can also batch update notifications if supported.
163
163
  */
164
- tablesUpdated: (updateNotification: BatchedUpdateNotification | UpdateNotification) => void;
164
+ tablesUpdated: (updateNotification: BatchedUpdateNotification) => void;
165
165
  }
166
166
 
167
+ /**
168
+ * @public
169
+ */
167
170
  export interface DBLockOptions {
168
171
  timeoutMs?: number;
169
172
  }
170
173
 
171
- export interface ConnectionPool extends BaseObserverInterface<DBAdapterListener> {
172
- name: string;
173
- close: () => void | Promise<void>;
174
- readLock: <T>(fn: (tx: LockContext) => Promise<T>, options?: DBLockOptions) => Promise<T>;
175
- writeLock: <T>(fn: (tx: LockContext) => Promise<T>, options?: DBLockOptions) => Promise<T>;
174
+ /**
175
+ * @public
176
+ */
177
+ export abstract class DBAdapter extends BaseObserver<DBAdapterListener> implements SqlExecutor, DBGetUtils {
178
+ abstract get name(): string;
179
+
180
+ abstract close(): void | Promise<void>;
181
+
182
+ abstract readLock<T>(fn: (tx: LockContext) => Promise<T>, options?: DBLockOptions): Promise<T>;
183
+ abstract writeLock<T>(fn: (tx: LockContext) => Promise<T>, options?: DBLockOptions): Promise<T>;
176
184
 
177
185
  /**
178
186
  * This method refreshes the schema information across all connections. This is for advanced use cases, and should generally not be needed.
179
187
  */
180
- refreshSchema: () => Promise<void>;
181
- }
182
-
183
- export interface DBAdapter extends ConnectionPool, SqlExecutor, DBGetUtils {
184
- readTransaction: <T>(fn: (tx: Transaction) => Promise<T>, options?: DBLockOptions) => Promise<T>;
185
- writeTransaction: <T>(fn: (tx: Transaction) => Promise<T>, options?: DBLockOptions) => Promise<T>;
186
- }
188
+ abstract refreshSchema(): Promise<void>;
187
189
 
188
- /**
189
- * A mixin to implement {@link DBAdapter} by delegating to {@link ConnectionPool.readLock} and
190
- * {@link ConnectionPool.writeLock}.
191
- */
192
- export function DBAdapterDefaultMixin<TBase extends new (...args: any[]) => ConnectionPool>(Base: TBase) {
193
- return class extends Base implements DBAdapter {
194
- readTransaction<T>(fn: (tx: Transaction) => Promise<T>, options?: DBLockOptions): Promise<T> {
195
- return this.readLock((ctx) => TransactionImplementation.runWith(ctx, fn), options);
196
- }
190
+ readTransaction<T>(fn: (tx: Transaction) => Promise<T>, options?: DBLockOptions): Promise<T> {
191
+ return this.readLock((ctx) => TransactionImplementation.runWith(ctx, fn), options);
192
+ }
197
193
 
198
- writeTransaction<T>(fn: (tx: Transaction) => Promise<T>, options?: DBLockOptions): Promise<T> {
199
- return this.writeLock((ctx) => TransactionImplementation.runWith(ctx, fn), options);
200
- }
194
+ writeTransaction<T>(fn: (tx: Transaction) => Promise<T>, options?: DBLockOptions): Promise<T> {
195
+ return this.writeLock((ctx) => TransactionImplementation.runWith(ctx, fn), options);
196
+ }
201
197
 
202
- getAll<T>(sql: string, parameters?: any[]): Promise<T[]> {
203
- return this.readLock((ctx) => ctx.getAll(sql, parameters));
204
- }
198
+ getAll<T>(sql: string, parameters?: any[]): Promise<T[]> {
199
+ return this.readLock((ctx) => ctx.getAll(sql, parameters));
200
+ }
205
201
 
206
- getOptional<T>(sql: string, parameters?: any[]): Promise<T | null> {
207
- return this.readLock((ctx) => ctx.getOptional(sql, parameters));
208
- }
202
+ getOptional<T>(sql: string, parameters?: any[]): Promise<T | null> {
203
+ return this.readLock((ctx) => ctx.getOptional(sql, parameters));
204
+ }
209
205
 
210
- get<T>(sql: string, parameters?: any[]): Promise<T> {
211
- return this.readLock((ctx) => ctx.get(sql, parameters));
212
- }
206
+ get<T>(sql: string, parameters?: any[]): Promise<T> {
207
+ return this.readLock((ctx) => ctx.get(sql, parameters));
208
+ }
213
209
 
214
- execute(query: string, params?: any[]): Promise<QueryResult> {
215
- return this.writeLock((ctx) => ctx.execute(query, params));
216
- }
210
+ execute<T>(query: string, params?: any[]): Promise<QueryResult<T>> {
211
+ return this.writeLock((ctx) => ctx.execute(query, params));
212
+ }
217
213
 
218
- executeRaw(query: string, params?: any[]): Promise<any[][]> {
219
- return this.writeLock((ctx) => ctx.executeRaw(query, params));
220
- }
214
+ executeRaw(query: string, params?: any[]): Promise<RawQueryResult> {
215
+ return this.writeLock((ctx) => ctx.executeRaw(query, params));
216
+ }
221
217
 
222
- executeBatch(query: string, params?: any[][]): Promise<QueryResult> {
223
- return this.writeTransaction((tx) => tx.executeBatch(query, params));
224
- }
225
- };
218
+ executeBatch(query: string, params?: any[][]): Promise<QueryResult<never>> {
219
+ return this.writeTransaction((tx) => tx.executeBatch(query, params));
220
+ }
226
221
  }
227
222
 
228
- class BaseTransaction implements SqlExecutor {
223
+ class TransactionImplementation extends LockContext {
229
224
  private finalized = false;
230
225
 
231
- constructor(private inner: SqlExecutor) {}
226
+ constructor(private inner: LockContext) {
227
+ super();
228
+ }
232
229
 
233
- async commit(): Promise<QueryResult> {
230
+ async commit(): Promise<void> {
234
231
  if (this.finalized) {
235
- return { rowsAffected: 0 };
232
+ return;
236
233
  }
237
234
  this.finalized = true;
238
- return this.inner.execute('COMMIT');
235
+ await this.inner.execute('COMMIT');
239
236
  }
240
237
 
241
- async rollback(): Promise<QueryResult> {
238
+ async rollback(): Promise<void> {
242
239
  if (this.finalized) {
243
- return { rowsAffected: 0 };
240
+ return;
244
241
  }
245
242
  this.finalized = true;
246
- return this.inner.execute('ROLLBACK');
243
+ await this.inner.execute('ROLLBACK');
247
244
  }
248
245
 
249
- execute(query: string, params?: any[] | undefined): Promise<QueryResult> {
246
+ execute<T>(query: string, params?: any[] | undefined): Promise<QueryResult<T>> {
250
247
  return this.inner.execute(query, params);
251
248
  }
252
249
 
253
- executeRaw(query: string, params?: any[] | undefined): Promise<any[][]> {
250
+ executeRaw(query: string, params?: any[] | undefined): Promise<RawQueryResult> {
254
251
  return this.inner.executeRaw(query, params);
255
252
  }
256
253
 
257
- executeBatch(query: string, params?: any[][]): Promise<QueryResult> {
254
+ executeBatch(query: string, params?: any[][]): Promise<QueryResult<never>> {
258
255
  return this.inner.executeBatch(query, params);
259
256
  }
260
- }
261
257
 
262
- class TransactionImplementation extends DBGetUtilsDefaultMixin(BaseTransaction) {
263
258
  static async runWith<T>(ctx: LockContext, fn: (tx: Transaction) => Promise<T>): Promise<T> {
264
259
  let tx = new TransactionImplementation(ctx);
265
260
 
@@ -280,13 +275,3 @@ class TransactionImplementation extends DBGetUtilsDefaultMixin(BaseTransaction)
280
275
  }
281
276
  }
282
277
  }
283
-
284
- export function isBatchedUpdateNotification(
285
- update: BatchedUpdateNotification | UpdateNotification
286
- ): update is BatchedUpdateNotification {
287
- return 'tables' in update;
288
- }
289
-
290
- export function extractTableUpdates(update: BatchedUpdateNotification | UpdateNotification) {
291
- return isBatchedUpdateNotification(update) ? update.tables : [update.table];
292
- }
@@ -0,0 +1,195 @@
1
+ /**
2
+ * A SQLite value, either text, a number, a blob value or null.
3
+ *
4
+ * @public
5
+ */
6
+ export type SqliteValue = string | number | bigint | number[] | Uint8Array | null;
7
+
8
+ /**
9
+ * A record of SQLite values representing a row.
10
+ *
11
+ * @public
12
+ */
13
+ export type SqliteRecord = Record<string, SqliteValue>;
14
+
15
+ /**
16
+ * A representation of query results as JavaScript object.
17
+ *
18
+ * @public
19
+ */
20
+ export interface ResultSet {
21
+ /**
22
+ * The amount of rows in the result set.
23
+ */
24
+ get length(): number;
25
+
26
+ /**
27
+ * @deprecated Use {@link QueryResult.array} instead.
28
+ */
29
+ get _array(): any[];
30
+
31
+ /**
32
+ * @deprecated Use {@link QueryResult.array} instead.
33
+ */
34
+ item<T>(idx: number): T;
35
+ }
36
+
37
+ /**
38
+ * Shared superinterface for {@link QueryResult} and {@link RawQueryResult}.
39
+ *
40
+ * @public
41
+ */
42
+ export interface BaseQueryResult {
43
+ /** Represents the auto-generated row id if applicable. */
44
+ insertId?: number;
45
+ /**
46
+ * Number of affected rows reported by SQLite for a write query.
47
+ *
48
+ * When using the default client-side [JSON-based view system](https://docs.powersync.com/architecture/client-architecture#client-side-schema-and-sqlite-database-structure),
49
+ * `rowsAffected` may be `0` for successful `UPDATE` and `DELETE` statements.
50
+ * Use a `RETURNING` clause and inspect `rows` when you need to confirm which rows changed.
51
+ */
52
+ rowsAffected?: number;
53
+ }
54
+
55
+ /**
56
+ * Object returned by SQL Query executions.
57
+ *
58
+ * @public
59
+ */
60
+ export interface QueryResult<T = SqliteRecord> extends BaseQueryResult, Iterable<T, undefined> {
61
+ /**
62
+ * If the query returned rows, the result set containing returned values.
63
+ */
64
+ rows?: ResultSet;
65
+ /**
66
+ * Rows in this result set.
67
+ */
68
+ array: T[];
69
+ }
70
+
71
+ /**
72
+ * A raw array-based result set representing rows returned by SQLite.
73
+ *
74
+ * @public
75
+ */
76
+ export interface RawQueryResult extends BaseQueryResult {
77
+ /**
78
+ * Names of columns in this result set. Every column has a name, so the length of this array is always equal to the
79
+ * amount of columns in the result set.
80
+ *
81
+ * Note that column names are not necessarily unique, e.g. a `SELECT foo.user, bar.user FROM ...` will have
82
+ * `['user', 'user']` in this array.
83
+ */
84
+ columnNames: string[];
85
+
86
+ /**
87
+ * Rows in the result set.
88
+ *
89
+ * Each row has a length equal to {@link RawQueryResult.columnNames}.
90
+ */
91
+ rawRows: SqliteValue[][];
92
+ }
93
+
94
+ function rowToRecord<T>(columnNames: string[], row: SqliteValue[]) {
95
+ const record: SqliteRecord = {};
96
+ columnNames.forEach((name, idx) => (record[name] = row[idx]));
97
+ return record as T;
98
+ }
99
+
100
+ /**
101
+ * Creates a query result by mapping raw rows to JavaScript.
102
+ *
103
+ * This should not be used with libraries doing this mapping natively, as that is typically more performant.
104
+ *
105
+ * @public
106
+ */
107
+ export function queryResultFromRaw<T>(raw: RawQueryResult): QueryResult<T> {
108
+ const { insertId, rowsAffected, columnNames, rawRows } = raw;
109
+ let array: any[] | undefined;
110
+
111
+ function loadAsArray() {
112
+ if (array) return array;
113
+
114
+ return (array = rawRows.map((row) => rowToRecord(columnNames, row)));
115
+ }
116
+
117
+ function getRow<T>(idx: number) {
118
+ if (array) return array[idx];
119
+ return rowToRecord(columnNames, rawRows[idx]);
120
+ }
121
+
122
+ return {
123
+ insertId,
124
+ rowsAffected,
125
+ get array() {
126
+ return loadAsArray();
127
+ },
128
+ rows: {
129
+ length: rawRows.length,
130
+ get _array() {
131
+ return loadAsArray();
132
+ },
133
+ item: getRow
134
+ } satisfies ResultSet,
135
+ [Symbol.iterator](): Iterator<T> {
136
+ let nextIndex = 0;
137
+
138
+ return {
139
+ next: function (): IteratorResult<T, any> {
140
+ if (nextIndex >= rawRows.length) {
141
+ return { done: true, value: undefined };
142
+ }
143
+
144
+ const row = getRow(nextIndex);
145
+ nextIndex++;
146
+ return { done: false, value: row };
147
+ }
148
+ };
149
+ }
150
+ };
151
+ }
152
+
153
+ /**
154
+ * Creates a query result from rows that have already been mapped to JavaScript.
155
+ *
156
+ * @public
157
+ */
158
+ export function queryResultFromMapped<T>(base: BaseQueryResult, rows?: T[]): QueryResult<T> {
159
+ if (rows == null) return queryResultWithoutRows(base);
160
+
161
+ return {
162
+ insertId: base.insertId,
163
+ rowsAffected: base.rowsAffected,
164
+ array: rows ?? [],
165
+ rows: {
166
+ length: rows.length,
167
+ _array: rows,
168
+ item(i: number) {
169
+ return rows[i] as any;
170
+ }
171
+ } satisfies ResultSet,
172
+ [Symbol.iterator](): Iterator<T> {
173
+ return rows[Symbol.iterator]();
174
+ }
175
+ };
176
+ }
177
+
178
+ /**
179
+ * Creates a {@link QueryResult} not containing any rows.
180
+ *
181
+ * @public
182
+ */
183
+ export function queryResultWithoutRows(result: BaseQueryResult): QueryResult<never> {
184
+ return {
185
+ ...result,
186
+ array: [],
187
+ [Symbol.iterator](): Iterator<never> {
188
+ return {
189
+ next() {
190
+ return { done: true, value: undefined };
191
+ }
192
+ };
193
+ }
194
+ };
195
+ }