@powersync/common 0.0.0-dev-20260504100448 → 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 (263) 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 +3 -0
  50. package/lib/client/sync/sync-streams.d.ts +23 -8
  51. package/lib/client/triggers/TriggerManager.d.ts +28 -56
  52. package/lib/client/triggers/TriggerManager.js +2 -1
  53. package/lib/client/triggers/TriggerManager.js.map +1 -1
  54. package/lib/client/triggers/sanitizeSQL.d.ts +4 -0
  55. package/lib/client/triggers/sanitizeSQL.js +4 -0
  56. package/lib/client/triggers/sanitizeSQL.js.map +1 -1
  57. package/lib/client/watched/GetAllQuery.d.ts +7 -3
  58. package/lib/client/watched/GetAllQuery.js +3 -1
  59. package/lib/client/watched/GetAllQuery.js.map +1 -1
  60. package/lib/client/watched/WatchedQuery.d.ts +20 -6
  61. package/lib/client/watched/WatchedQuery.js +3 -5
  62. package/lib/client/watched/WatchedQuery.js.map +1 -1
  63. package/lib/client/watched/processors/DifferentialQueryProcessor.d.ts +15 -45
  64. package/lib/client/watched/processors/DifferentialQueryProcessor.js +1 -172
  65. package/lib/client/watched/processors/DifferentialQueryProcessor.js.map +1 -1
  66. package/lib/client/watched/processors/OnChangeQueryProcessor.d.ts +4 -22
  67. package/lib/client/watched/processors/OnChangeQueryProcessor.js +1 -82
  68. package/lib/client/watched/processors/OnChangeQueryProcessor.js.map +1 -1
  69. package/lib/client/watched/processors/comparators.d.ts +8 -0
  70. package/lib/client/watched/processors/comparators.js +4 -0
  71. package/lib/client/watched/processors/comparators.js.map +1 -1
  72. package/lib/db/DBAdapter.d.ts +90 -113
  73. package/lib/db/DBAdapter.js +70 -89
  74. package/lib/db/DBAdapter.js.map +1 -1
  75. package/lib/db/QueryResult.d.ts +104 -0
  76. package/lib/db/QueryResult.js +96 -0
  77. package/lib/db/QueryResult.js.map +1 -0
  78. package/lib/db/crud/SyncProgress.d.ts +7 -14
  79. package/lib/db/crud/SyncProgress.js +1 -60
  80. package/lib/db/crud/SyncProgress.js.map +1 -1
  81. package/lib/db/crud/SyncStatus.d.ts +54 -91
  82. package/lib/db/crud/SyncStatus.js +1 -245
  83. package/lib/db/crud/SyncStatus.js.map +1 -1
  84. package/lib/db/crud/UploadQueueStatus.d.ts +3 -0
  85. package/lib/db/crud/UploadQueueStatus.js +3 -0
  86. package/lib/db/crud/UploadQueueStatus.js.map +1 -1
  87. package/lib/db/schema/Column.d.ts +22 -1
  88. package/lib/db/schema/Column.js +10 -4
  89. package/lib/db/schema/Column.js.map +1 -1
  90. package/lib/db/schema/Index.d.ts +8 -3
  91. package/lib/db/schema/Index.js +4 -1
  92. package/lib/db/schema/Index.js.map +1 -1
  93. package/lib/db/schema/IndexedColumn.d.ts +8 -3
  94. package/lib/db/schema/IndexedColumn.js +4 -1
  95. package/lib/db/schema/IndexedColumn.js.map +1 -1
  96. package/lib/db/schema/RawTable.d.ts +7 -1
  97. package/lib/db/schema/Schema.d.ts +10 -29
  98. package/lib/db/schema/Schema.js +3 -1
  99. package/lib/db/schema/Schema.js.map +1 -1
  100. package/lib/db/schema/Table.d.ts +69 -91
  101. package/lib/db/schema/Table.js +88 -87
  102. package/lib/db/schema/Table.js.map +1 -1
  103. package/lib/index.d.ts +6 -22
  104. package/lib/index.js +5 -22
  105. package/lib/index.js.map +1 -1
  106. package/lib/types/types.d.ts +6 -0
  107. package/lib/utils/BaseObserver.d.ts +12 -0
  108. package/lib/utils/BaseObserver.js +3 -0
  109. package/lib/utils/BaseObserver.js.map +1 -1
  110. package/lib/utils/Logger.d.ts +60 -22
  111. package/lib/utils/Logger.js +38 -30
  112. package/lib/utils/Logger.js.map +1 -1
  113. package/lib/utils/MetaBaseObserver.d.ts +11 -11
  114. package/lib/utils/MetaBaseObserver.js +1 -50
  115. package/lib/utils/MetaBaseObserver.js.map +1 -1
  116. package/lib/utils/mutex.d.ts +3 -45
  117. package/lib/utils/mutex.js +1 -153
  118. package/lib/utils/mutex.js.map +1 -1
  119. package/package.json +9 -46
  120. package/src/attachments/AttachmentContext.ts +15 -13
  121. package/src/attachments/AttachmentErrorHandler.ts +6 -6
  122. package/src/attachments/AttachmentQueue.ts +99 -42
  123. package/src/attachments/AttachmentService.ts +7 -6
  124. package/src/attachments/LocalStorageAdapter.ts +14 -8
  125. package/src/attachments/README.md +2 -0
  126. package/src/attachments/RemoteStorageAdapter.ts +4 -4
  127. package/src/attachments/Schema.ts +14 -6
  128. package/src/attachments/SyncingService.ts +10 -6
  129. package/src/attachments/WatchedAttachmentItem.ts +3 -1
  130. package/src/client/CommonPowerSyncDatabase.ts +540 -0
  131. package/src/client/Query.ts +9 -0
  132. package/src/client/SQLOpenFactory.ts +47 -19
  133. package/src/client/compilableQueryWatch.ts +9 -4
  134. package/src/client/connection/PowerSyncBackendConnector.ts +6 -3
  135. package/src/client/connection/PowerSyncCredentials.ts +3 -0
  136. package/src/client/runOnSchemaChange.ts +5 -2
  137. package/src/client/sync/bucket/CrudBatch.ts +2 -0
  138. package/src/client/sync/bucket/CrudEntry.ts +10 -101
  139. package/src/client/sync/bucket/CrudTransaction.ts +3 -0
  140. package/src/client/sync/options.ts +77 -0
  141. package/src/client/sync/stream/JsonValue.ts +3 -0
  142. package/src/client/sync/sync-streams.ts +23 -10
  143. package/src/client/triggers/TriggerManager.ts +29 -59
  144. package/src/client/triggers/sanitizeSQL.ts +5 -0
  145. package/src/client/watched/GetAllQuery.ts +8 -4
  146. package/src/client/watched/WatchedQuery.ts +20 -11
  147. package/src/client/watched/processors/DifferentialQueryProcessor.ts +19 -219
  148. package/src/client/watched/processors/OnChangeQueryProcessor.ts +4 -109
  149. package/src/client/watched/processors/comparators.ts +8 -0
  150. package/src/db/DBAdapter.ts +160 -175
  151. package/src/db/QueryResult.ts +195 -0
  152. package/src/db/crud/SyncProgress.ts +8 -43
  153. package/src/db/crud/SyncStatus.ts +66 -216
  154. package/src/db/crud/UploadQueueStatus.ts +3 -0
  155. package/src/db/schema/Column.ts +22 -5
  156. package/src/db/schema/Index.ts +9 -3
  157. package/src/db/schema/IndexedColumn.ts +9 -3
  158. package/src/db/schema/RawTable.ts +7 -1
  159. package/src/db/schema/Schema.ts +12 -7
  160. package/src/db/schema/Table.ts +130 -180
  161. package/src/index.ts +6 -22
  162. package/src/types/types.ts +6 -0
  163. package/src/utils/BaseObserver.ts +12 -0
  164. package/src/utils/Logger.ts +86 -31
  165. package/src/utils/MetaBaseObserver.ts +14 -60
  166. package/src/utils/mutex.ts +4 -189
  167. package/dist/bundle.cjs +0 -14136
  168. package/dist/bundle.cjs.map +0 -1
  169. package/dist/bundle.mjs +0 -14056
  170. package/dist/bundle.mjs.map +0 -1
  171. package/dist/bundle.node.cjs +0 -11613
  172. package/dist/bundle.node.cjs.map +0 -1
  173. package/dist/bundle.node.mjs +0 -11533
  174. package/dist/bundle.node.mjs.map +0 -1
  175. package/dist/index.d.cts +0 -4052
  176. package/legacy/sync_protocol.d.ts +0 -103
  177. package/lib/client/AbstractPowerSyncDatabase.js +0 -987
  178. package/lib/client/AbstractPowerSyncDatabase.js.map +0 -1
  179. package/lib/client/AbstractPowerSyncOpenFactory.d.ts +0 -22
  180. package/lib/client/AbstractPowerSyncOpenFactory.js +0 -25
  181. package/lib/client/AbstractPowerSyncOpenFactory.js.map +0 -1
  182. package/lib/client/ConnectionManager.d.ts +0 -112
  183. package/lib/client/ConnectionManager.js +0 -294
  184. package/lib/client/ConnectionManager.js.map +0 -1
  185. package/lib/client/CustomQuery.d.ts +0 -22
  186. package/lib/client/CustomQuery.js +0 -43
  187. package/lib/client/CustomQuery.js.map +0 -1
  188. package/lib/client/constants.d.ts +0 -1
  189. package/lib/client/constants.js +0 -2
  190. package/lib/client/constants.js.map +0 -1
  191. package/lib/client/sync/bucket/BucketStorageAdapter.d.ts +0 -40
  192. package/lib/client/sync/bucket/BucketStorageAdapter.js +0 -19
  193. package/lib/client/sync/bucket/BucketStorageAdapter.js.map +0 -1
  194. package/lib/client/sync/bucket/SqliteBucketStorage.d.ts +0 -34
  195. package/lib/client/sync/bucket/SqliteBucketStorage.js +0 -162
  196. package/lib/client/sync/bucket/SqliteBucketStorage.js.map +0 -1
  197. package/lib/client/sync/stream/AbstractRemote.d.ts +0 -151
  198. package/lib/client/sync/stream/AbstractRemote.js +0 -473
  199. package/lib/client/sync/stream/AbstractRemote.js.map +0 -1
  200. package/lib/client/sync/stream/AbstractStreamingSyncImplementation.d.ts +0 -218
  201. package/lib/client/sync/stream/AbstractStreamingSyncImplementation.js +0 -663
  202. package/lib/client/sync/stream/AbstractStreamingSyncImplementation.js.map +0 -1
  203. package/lib/client/sync/stream/WebsocketClientTransport.d.ts +0 -15
  204. package/lib/client/sync/stream/WebsocketClientTransport.js +0 -61
  205. package/lib/client/sync/stream/WebsocketClientTransport.js.map +0 -1
  206. package/lib/client/sync/stream/core-instruction.d.ts +0 -71
  207. package/lib/client/sync/stream/core-instruction.js +0 -27
  208. package/lib/client/sync/stream/core-instruction.js.map +0 -1
  209. package/lib/client/triggers/MemoryTriggerClaimManager.d.ts +0 -6
  210. package/lib/client/triggers/MemoryTriggerClaimManager.js +0 -21
  211. package/lib/client/triggers/MemoryTriggerClaimManager.js.map +0 -1
  212. package/lib/client/triggers/TriggerManagerImpl.d.ts +0 -39
  213. package/lib/client/triggers/TriggerManagerImpl.js +0 -405
  214. package/lib/client/triggers/TriggerManagerImpl.js.map +0 -1
  215. package/lib/client/watched/processors/AbstractQueryProcessor.d.ts +0 -68
  216. package/lib/client/watched/processors/AbstractQueryProcessor.js +0 -151
  217. package/lib/client/watched/processors/AbstractQueryProcessor.js.map +0 -1
  218. package/lib/db/ConnectionClosedError.d.ts +0 -10
  219. package/lib/db/ConnectionClosedError.js +0 -21
  220. package/lib/db/ConnectionClosedError.js.map +0 -1
  221. package/lib/db/schema/TableV2.d.ts +0 -9
  222. package/lib/db/schema/TableV2.js +0 -9
  223. package/lib/db/schema/TableV2.js.map +0 -1
  224. package/lib/utils/AbortOperation.d.ts +0 -9
  225. package/lib/utils/AbortOperation.js +0 -19
  226. package/lib/utils/AbortOperation.js.map +0 -1
  227. package/lib/utils/ControlledExecutor.d.ts +0 -25
  228. package/lib/utils/ControlledExecutor.js +0 -51
  229. package/lib/utils/ControlledExecutor.js.map +0 -1
  230. package/lib/utils/async.d.ts +0 -14
  231. package/lib/utils/async.js +0 -46
  232. package/lib/utils/async.js.map +0 -1
  233. package/lib/utils/parseQuery.d.ts +0 -6
  234. package/lib/utils/parseQuery.js +0 -17
  235. package/lib/utils/parseQuery.js.map +0 -1
  236. package/lib/utils/queue.d.ts +0 -16
  237. package/lib/utils/queue.js +0 -42
  238. package/lib/utils/queue.js.map +0 -1
  239. package/lib/utils/stream_transform.d.ts +0 -39
  240. package/lib/utils/stream_transform.js +0 -206
  241. package/lib/utils/stream_transform.js.map +0 -1
  242. package/src/client/AbstractPowerSyncDatabase.ts +0 -1362
  243. package/src/client/AbstractPowerSyncOpenFactory.ts +0 -39
  244. package/src/client/ConnectionManager.ts +0 -402
  245. package/src/client/CustomQuery.ts +0 -56
  246. package/src/client/constants.ts +0 -1
  247. package/src/client/sync/bucket/BucketStorageAdapter.ts +0 -49
  248. package/src/client/sync/bucket/SqliteBucketStorage.ts +0 -199
  249. package/src/client/sync/stream/AbstractRemote.ts +0 -602
  250. package/src/client/sync/stream/AbstractStreamingSyncImplementation.ts +0 -905
  251. package/src/client/sync/stream/WebsocketClientTransport.ts +0 -80
  252. package/src/client/sync/stream/core-instruction.ts +0 -98
  253. package/src/client/triggers/MemoryTriggerClaimManager.ts +0 -25
  254. package/src/client/triggers/TriggerManagerImpl.ts +0 -496
  255. package/src/client/watched/processors/AbstractQueryProcessor.ts +0 -226
  256. package/src/db/ConnectionClosedError.ts +0 -23
  257. package/src/db/schema/TableV2.ts +0 -9
  258. package/src/utils/AbortOperation.ts +0 -17
  259. package/src/utils/ControlledExecutor.ts +0 -72
  260. package/src/utils/async.ts +0 -50
  261. package/src/utils/parseQuery.ts +0 -25
  262. package/src/utils/queue.ts +0 -48
  263. package/src/utils/stream_transform.ts +0 -252
package/package.json CHANGED
@@ -1,38 +1,17 @@
1
1
  {
2
2
  "name": "@powersync/common",
3
- "version": "0.0.0-dev-20260504100448",
3
+ "version": "0.0.0-dev-20260630141119",
4
4
  "publishConfig": {
5
5
  "registry": "https://registry.npmjs.org/",
6
6
  "access": "public"
7
7
  },
8
8
  "description": "API definitions for PowerSync",
9
9
  "type": "module",
10
- "main": "dist/bundle.mjs",
11
- "module": "dist/bundle.mjs",
12
- "types": "lib/index.d.ts",
10
+ "types": "./lib/index.d.ts",
13
11
  "exports": {
14
12
  ".": {
15
- "node": {
16
- "import": {
17
- "types": "./lib/index.d.ts",
18
- "default": "./dist/bundle.node.mjs"
19
- },
20
- "require": {
21
- "types": "./dist/index.d.cts",
22
- "require": "./dist/bundle.node.cjs"
23
- }
24
- },
25
- "import": {
26
- "types": "./lib/index.d.ts",
27
- "default": "./dist/bundle.mjs"
28
- },
29
- "require": {
30
- "types": "./dist/index.d.cts",
31
- "require": "./dist/bundle.cjs"
32
- }
33
- },
34
- "./internal/sync_protocol": {
35
- "types": "./legacy/sync_protocol.d.ts"
13
+ "types": "./lib/index.d.ts",
14
+ "default": "./lib/index.js"
36
15
  }
37
16
  },
38
17
  "author": "PowerSync",
@@ -40,8 +19,7 @@
40
19
  "files": [
41
20
  "lib",
42
21
  "dist",
43
- "src",
44
- "legacy"
22
+ "src"
45
23
  ],
46
24
  "repository": {
47
25
  "type": "git",
@@ -51,31 +29,16 @@
51
29
  "url": "https://github.com/powersync-ja/powersync-js/issues"
52
30
  },
53
31
  "homepage": "https://docs.powersync.com",
54
- "dependencies": {
55
- "event-iterator": "^2.0.0"
56
- },
57
32
  "devDependencies": {
58
- "@rollup/plugin-commonjs": "^29.0.0",
59
- "@rollup/plugin-inject": "^5.0.5",
60
- "@rollup/plugin-json": "^6.1.0",
61
- "@rollup/plugin-node-resolve": "^16.0.3",
62
33
  "@types/node": "^24.0.0",
63
34
  "@types/uuid": "^9.0.6",
64
- "buffer": "^6.0.3",
65
- "cross-fetch": "^4.1.0",
66
- "estree-walker": "^3.0.3",
67
- "js-logger": "^1.6.1",
68
- "magic-string": "^0.30.21",
69
- "rollup": "^4.52.5",
70
- "rollup-plugin-dts": "^6.2.1",
71
- "rsocket-core": "1.0.0-alpha.3",
72
- "rsocket-websocket-client": "1.0.0-alpha.3"
35
+ "@microsoft/api-extractor": "^7.58.7"
73
36
  },
74
37
  "scripts": {
75
- "build": "tsc -b && rollup -c rollup.config.mjs",
76
- "build:prod": "tsc -b && rollup -c rollup.config.mjs",
38
+ "build": "tsc -b",
39
+ "build:prod": "tsc -b",
77
40
  "clean": "rm -rf lib dist tsconfig.tsbuildinfo",
78
41
  "test": "vitest",
79
- "test:exports": "attw --pack . --exclude-entrypoints internal/sync_protocol"
42
+ "test:exports": "attw --pack . --ignore-rules no-resolution cjs-resolves-to-esm"
80
43
  }
81
44
  }
@@ -1,7 +1,7 @@
1
- import { AbstractPowerSyncDatabase } from '../client/AbstractPowerSyncDatabase.js';
2
- import { ILogger } from '../utils/Logger.js';
1
+ import { LogLevels, PowerSyncLogger } from '../utils/Logger.js';
3
2
  import { Transaction } from '../db/DBAdapter.js';
4
3
  import { AttachmentRecord, AttachmentState, attachmentFromSql } from './Schema.js';
4
+ import { CommonPowerSyncDatabase } from '../client/CommonPowerSyncDatabase.js';
5
5
 
6
6
  /**
7
7
  * AttachmentContext provides database operations for managing attachment records.
@@ -9,20 +9,21 @@ import { AttachmentRecord, AttachmentState, attachmentFromSql } from './Schema.j
9
9
  * Provides methods to query, insert, update, and delete attachment records with
10
10
  * proper transaction management through PowerSync.
11
11
  *
12
- * @internal
12
+ * @experimental
13
+ * @alpha
13
14
  */
14
15
  export class AttachmentContext {
15
16
  /** PowerSync database instance for executing queries */
16
- db: AbstractPowerSyncDatabase;
17
+ readonly db: CommonPowerSyncDatabase;
17
18
 
18
19
  /** Name of the database table storing attachment records */
19
- tableName: string;
20
+ readonly tableName: string;
20
21
 
21
22
  /** Logger instance for diagnostic information */
22
- logger: ILogger;
23
+ readonly logger: PowerSyncLogger;
23
24
 
24
25
  /** Maximum number of archived attachments to keep before cleanup */
25
- archivedCacheLimit: number = 100;
26
+ readonly archivedCacheLimit: number = 100;
26
27
 
27
28
  /**
28
29
  * Creates a new AttachmentContext instance.
@@ -32,9 +33,9 @@ export class AttachmentContext {
32
33
  * @param logger - Logger instance for diagnostic output
33
34
  */
34
35
  constructor(
35
- db: AbstractPowerSyncDatabase,
36
+ db: CommonPowerSyncDatabase,
36
37
  tableName: string = 'attachments',
37
- logger: ILogger,
38
+ logger: PowerSyncLogger,
38
39
  archivedCacheLimit: number
39
40
  ) {
40
41
  this.db = db;
@@ -233,9 +234,10 @@ export class AttachmentContext {
233
234
  if (archivedAttachments.length === 0) return false;
234
235
 
235
236
  await callback?.(archivedAttachments);
236
- this.logger.info(
237
- `Deleting ${archivedAttachments.length} archived attachments. Archived attachment exceeds cache archiveCacheLimit of ${this.archivedCacheLimit}.`
238
- );
237
+ this.logger.log({
238
+ level: LogLevels.info,
239
+ message: `Deleting ${archivedAttachments.length} archived attachments. Archived attachment exceeds cache archiveCacheLimit of ${this.archivedCacheLimit}.`
240
+ });
239
241
 
240
242
  const ids = archivedAttachments.map((attachment) => attachment.id);
241
243
 
@@ -254,7 +256,7 @@ export class AttachmentContext {
254
256
  [JSON.stringify(ids)]
255
257
  );
256
258
 
257
- this.logger.info(`Deleted ${archivedAttachments.length} archived attachments`);
259
+ this.logger.log({ level: LogLevels.info, message: `Deleted ${archivedAttachments.length} archived attachments` });
258
260
  return archivedAttachments.length < limit;
259
261
  }
260
262
 
@@ -10,24 +10,24 @@ import { AttachmentRecord } from './Schema.js';
10
10
  export interface AttachmentErrorHandler {
11
11
  /**
12
12
  * Handles a download error for a specific attachment.
13
- * @param attachment The attachment that failed to download
14
- * @param error The error encountered during the download
13
+ * @param attachment - The attachment that failed to download
14
+ * @param error - The error encountered during the download
15
15
  * @returns `true` to retry the operation, `false` to archive the attachment
16
16
  */
17
17
  onDownloadError(attachment: AttachmentRecord, error: unknown): Promise<boolean>;
18
18
 
19
19
  /**
20
20
  * Handles an upload error for a specific attachment.
21
- * @param attachment The attachment that failed to upload
22
- * @param error The error encountered during the upload
21
+ * @param attachment - The attachment that failed to upload
22
+ * @param error - The error encountered during the upload
23
23
  * @returns `true` to retry the operation, `false` to archive the attachment
24
24
  */
25
25
  onUploadError(attachment: AttachmentRecord, error: unknown): Promise<boolean>;
26
26
 
27
27
  /**
28
28
  * Handles a delete error for a specific attachment.
29
- * @param attachment The attachment that failed to delete
30
- * @param error The error encountered during the delete
29
+ * @param attachment - The attachment that failed to delete
30
+ * @param error - The error encountered during the delete
31
31
  * @returns `true` to retry the operation, `false` to archive the attachment
32
32
  */
33
33
  onDeleteError(attachment: AttachmentRecord, error: unknown): Promise<boolean>;
@@ -1,15 +1,67 @@
1
- import { AbstractPowerSyncDatabase } from '../client/AbstractPowerSyncDatabase.js';
2
- import { DEFAULT_WATCH_THROTTLE_MS } from '../client/watched/WatchedQuery.js';
3
1
  import { DifferentialWatchedQuery } from '../client/watched/processors/DifferentialQueryProcessor.js';
4
- import { ILogger } from '../utils/Logger.js';
2
+ import { LogLevels, PowerSyncLogger } from '../utils/Logger.js';
5
3
  import { Transaction } from '../db/DBAdapter.js';
4
+ import { AttachmentContext } from './AttachmentContext.js';
5
+ import { AttachmentErrorHandler } from './AttachmentErrorHandler.js';
6
+ import { AttachmentService } from './AttachmentService.js';
6
7
  import { AttachmentData, LocalStorageAdapter } from './LocalStorageAdapter.js';
7
8
  import { RemoteStorageAdapter } from './RemoteStorageAdapter.js';
8
9
  import { ATTACHMENT_TABLE, AttachmentRecord, AttachmentState } from './Schema.js';
9
10
  import { SyncingService } from './SyncingService.js';
10
11
  import { WatchedAttachmentItem } from './WatchedAttachmentItem.js';
11
- import { AttachmentService } from './AttachmentService.js';
12
- import { AttachmentErrorHandler } from './AttachmentErrorHandler.js';
12
+ import { CommonPowerSyncDatabase } from '../client/CommonPowerSyncDatabase.js';
13
+
14
+ /**
15
+ * Configuration options for {@link AttachmentQueue}.
16
+ *
17
+ * @experimental
18
+ * @alpha This is currently experimental and may change without a major version bump.
19
+ */
20
+ export interface AttachmentQueueOptions {
21
+ /**
22
+ * PowerSync database instance
23
+ */
24
+ db: CommonPowerSyncDatabase;
25
+ /**
26
+ * Remote storage adapter for upload/download operations
27
+ */
28
+ remoteStorage: RemoteStorageAdapter;
29
+ /**
30
+ * Local storage adapter for file persistence
31
+ */
32
+ localStorage: LocalStorageAdapter;
33
+ /**
34
+ * Callback for monitoring attachment changes in your data model
35
+ */
36
+ watchAttachments: (onUpdate: (attachment: WatchedAttachmentItem[]) => Promise<void>, signal: AbortSignal) => void;
37
+ /**
38
+ * Name of the table to store attachment records. Default: 'ps_attachment_queue'
39
+ */
40
+ tableName?: string;
41
+ /**
42
+ * Logger instance. Defaults to db.logger
43
+ */
44
+ logger?: PowerSyncLogger;
45
+ /**
46
+ * Periodic polling interval in milliseconds for retrying failed uploads/downloads. Default: 30000
47
+ */
48
+ syncIntervalMs?: number;
49
+ /**
50
+ * Throttle duration in milliseconds for the reactive watch query that detects attachment changes. Prevents rapid-fire syncs during bulk changes. Default: 30
51
+ */
52
+ syncThrottleDuration?: number;
53
+ /**
54
+ * Whether to automatically download remote attachments. Default: true
55
+ */
56
+ downloadAttachments?: boolean;
57
+ /**
58
+ * Maximum archived attachments before cleanup. Default: 100
59
+ */
60
+ archivedCacheLimit?: number;
61
+
62
+ /** Handler for upload, download and delete errors */
63
+ errorHandler?: AttachmentErrorHandler;
64
+ }
13
65
 
14
66
  /**
15
67
  * AttachmentQueue manages the lifecycle and synchronization of attachments
@@ -49,7 +101,7 @@ export class AttachmentQueue {
49
101
  readonly tableName: string;
50
102
 
51
103
  /** Logger instance for diagnostic information */
52
- readonly logger: ILogger;
104
+ readonly logger: PowerSyncLogger;
53
105
 
54
106
  /** Interval in milliseconds between periodic sync operations. Acts as a polling timer to retry
55
107
  * failed uploads/downloads, especially after the app goes offline. Default: 30000 (30 seconds) */
@@ -61,7 +113,7 @@ export class AttachmentQueue {
61
113
  * quick succession (e.g., bulk inserts). This is distinct from syncIntervalMs — it controls
62
114
  * how quickly the queue reacts to changes, while syncIntervalMs controls how often it polls
63
115
  * for retries. Default: 30 (from DEFAULT_WATCH_THROTTLE_MS) */
64
- readonly syncThrottleDuration: number;
116
+ readonly syncThrottleDuration?: number;
65
117
 
66
118
  /** Whether to automatically download remote attachments. Default: true */
67
119
  readonly downloadAttachments: boolean = true;
@@ -73,29 +125,19 @@ export class AttachmentQueue {
73
125
  private readonly attachmentService: AttachmentService;
74
126
 
75
127
  /** PowerSync database instance */
76
- private readonly db: AbstractPowerSyncDatabase;
128
+ private readonly db: CommonPowerSyncDatabase;
77
129
 
78
130
  /** Cleanup function for status change listener */
79
131
  private statusListenerDispose?: () => void;
80
132
 
81
- private watchActiveAttachments: DifferentialWatchedQuery<AttachmentRecord>;
133
+ private watchActiveAttachments!: DifferentialWatchedQuery<AttachmentRecord>;
82
134
 
83
- private watchAttachmentsAbortController: AbortController;
135
+ private watchAttachmentsAbortController!: AbortController;
84
136
 
85
137
  /**
86
138
  * Creates a new AttachmentQueue instance.
87
139
  *
88
140
  * @param options - Configuration options
89
- * @param options.db - PowerSync database instance
90
- * @param options.remoteStorage - Remote storage adapter for upload/download operations
91
- * @param options.localStorage - Local storage adapter for file persistence
92
- * @param options.watchAttachments - Callback for monitoring attachment changes in your data model
93
- * @param options.tableName - Name of the table to store attachment records. Default: 'ps_attachment_queue'
94
- * @param options.logger - Logger instance. Defaults to db.logger
95
- * @param options.syncIntervalMs - Periodic polling interval in milliseconds for retrying failed uploads/downloads. Default: 30000
96
- * @param options.syncThrottleDuration - Throttle duration in milliseconds for the reactive watch query that detects attachment changes. Prevents rapid-fire syncs during bulk changes. Default: 30
97
- * @param options.downloadAttachments - Whether to automatically download remote attachments. Default: true
98
- * @param options.archivedCacheLimit - Maximum archived attachments before cleanup. Default: 100
99
141
  */
100
142
  constructor({
101
143
  db,
@@ -105,23 +147,11 @@ export class AttachmentQueue {
105
147
  logger,
106
148
  tableName = ATTACHMENT_TABLE,
107
149
  syncIntervalMs = 30 * 1000,
108
- syncThrottleDuration = DEFAULT_WATCH_THROTTLE_MS,
150
+ syncThrottleDuration,
109
151
  downloadAttachments = true,
110
152
  archivedCacheLimit = 100,
111
153
  errorHandler
112
- }: {
113
- db: AbstractPowerSyncDatabase;
114
- remoteStorage: RemoteStorageAdapter;
115
- localStorage: LocalStorageAdapter;
116
- watchAttachments: (onUpdate: (attachment: WatchedAttachmentItem[]) => Promise<void>, signal: AbortSignal) => void;
117
- tableName?: string;
118
- logger?: ILogger;
119
- syncIntervalMs?: number;
120
- syncThrottleDuration?: number;
121
- downloadAttachments?: boolean;
122
- archivedCacheLimit?: number;
123
- errorHandler?: AttachmentErrorHandler;
124
- }) {
154
+ }: AttachmentQueueOptions) {
125
155
  this.db = db;
126
156
  this.remoteStorage = remoteStorage;
127
157
  this.localStorage = localStorage;
@@ -190,7 +220,7 @@ export class AttachmentQueue {
190
220
  if (status.connected) {
191
221
  // Device came online, process attachments immediately
192
222
  this.syncStorage().catch((error) => {
193
- this.logger.error('Error syncing storage on connection:', error);
223
+ this.logger.log({ level: LogLevels.error, message: 'Error syncing storage on connection', error });
194
224
  });
195
225
  }
196
226
  }
@@ -228,6 +258,7 @@ export class AttachmentQueue {
228
258
  state: AttachmentState.QUEUED_DOWNLOAD,
229
259
  hasSynced: false,
230
260
  metaData: watchedAttachment.metaData,
261
+ mediaType: watchedAttachment.mediaType,
231
262
  timestamp: new Date().getTime()
232
263
  });
233
264
  continue;
@@ -321,17 +352,24 @@ export class AttachmentQueue {
321
352
  }
322
353
  }
323
354
 
355
+ /**
356
+ * Provides an {@link AttachmentContext} to a callback.
357
+ *
358
+ * The callback runs while the attachment queue mutex is held. Do not call
359
+ * other {@link AttachmentQueue} methods from within the callback, as they may
360
+ * attempt to acquire the same mutex and block indefinitely.
361
+ */
362
+ withAttachmentContext<T>(callback: (context: AttachmentContext) => Promise<T>): Promise<T> {
363
+ /**
364
+ * AttachmentService is internal and private in this class.
365
+ * We only need to expose its locking and context functionality for extending classes.
366
+ */
367
+ return this.attachmentService.withContext(callback);
368
+ }
324
369
  /**
325
370
  * Saves a file to local storage and queues it for upload to remote storage.
326
371
  *
327
372
  * @param options - File save options
328
- * @param options.data - The file data as ArrayBuffer, Blob, or base64 string
329
- * @param options.fileExtension - File extension (e.g., 'jpg', 'pdf')
330
- * @param options.mediaType - MIME type of the file (e.g., 'image/jpeg')
331
- * @param options.metaData - Optional metadata to associate with the attachment
332
- * @param options.id - Optional custom ID. If not provided, a UUID will be generated
333
- * @param options.updateHook - Optional callback to execute additional database operations
334
- * within the same transaction as the attachment creation
335
373
  * @returns Promise resolving to the created attachment record
336
374
  */
337
375
  async saveFile({
@@ -342,11 +380,30 @@ export class AttachmentQueue {
342
380
  id,
343
381
  updateHook
344
382
  }: {
383
+ /**
384
+ * The file data as ArrayBuffer, Blob, or base64 string
385
+ */
345
386
  data: AttachmentData;
387
+ /**
388
+ * File extension (e.g., 'jpg', 'pdf')
389
+ */
346
390
  fileExtension: string;
391
+ /**
392
+ * MIME type of the file (e.g., 'image/jpeg')
393
+ */
347
394
  mediaType?: string;
395
+ /**
396
+ * Optional metadata to associate with the attachment
397
+ */
348
398
  metaData?: string;
399
+ /**
400
+ * Optional custom ID. If not provided, a UUID will be generated
401
+ */
349
402
  id?: string;
403
+ /**
404
+ * Optional callback to execute additional database operations within the same transaction as the attachment
405
+ * creation.
406
+ */
350
407
  updateHook?: (transaction: Transaction, attachment: AttachmentRecord) => Promise<void>;
351
408
  }): Promise<AttachmentRecord> {
352
409
  const resolvedId = id ?? (await this.generateAttachmentId());
@@ -1,6 +1,6 @@
1
- import { AbstractPowerSyncDatabase } from '../client/AbstractPowerSyncDatabase.js';
1
+ import { CommonPowerSyncDatabase } from '../client/CommonPowerSyncDatabase.js';
2
2
  import { DifferentialWatchedQuery } from '../client/watched/processors/DifferentialQueryProcessor.js';
3
- import { ILogger } from '../utils/Logger.js';
3
+ import { PowerSyncLogger, LogLevels } from '../utils/Logger.js';
4
4
  import { Mutex } from '../utils/mutex.js';
5
5
  import { AttachmentContext } from './AttachmentContext.js';
6
6
  import { AttachmentRecord, AttachmentState } from './Schema.js';
@@ -11,15 +11,16 @@ import { AttachmentRecord, AttachmentState } from './Schema.js';
11
11
  * @internal
12
12
  */
13
13
  export class AttachmentService {
14
- private mutex = new Mutex();
14
+ private mutex: Mutex;
15
15
  private context: AttachmentContext;
16
16
 
17
17
  constructor(
18
- private db: AbstractPowerSyncDatabase,
19
- private logger: ILogger,
18
+ private db: CommonPowerSyncDatabase,
19
+ private logger: PowerSyncLogger,
20
20
  private tableName: string = 'attachments',
21
21
  archivedCacheLimit: number = 100
22
22
  ) {
23
+ this.mutex = db.createMutex();
23
24
  this.context = new AttachmentContext(db, tableName, logger, archivedCacheLimit);
24
25
  }
25
26
 
@@ -28,7 +29,7 @@ export class AttachmentService {
28
29
  * @returns Watch query that emits changes for queued uploads, downloads, and deletes
29
30
  */
30
31
  watchActiveAttachments({ throttleMs }: { throttleMs?: number } = {}): DifferentialWatchedQuery<AttachmentRecord> {
31
- this.logger.info('Watching active attachments...');
32
+ this.logger.log({ level: LogLevels.info, message: 'Watching active attachments...' });
32
33
  const watch = this.db
33
34
  .query<AttachmentRecord>({
34
35
  sql: /* sql */ `
@@ -1,5 +1,11 @@
1
+ /**
2
+ * @alpha
3
+ */
1
4
  export type AttachmentData = ArrayBuffer | string;
2
5
 
6
+ /**
7
+ * @alpha
8
+ */
3
9
  export enum EncodingType {
4
10
  UTF8 = 'utf8',
5
11
  Base64 = 'base64'
@@ -15,41 +21,41 @@ export enum EncodingType {
15
21
  export interface LocalStorageAdapter {
16
22
  /**
17
23
  * Saves data to a local file.
18
- * @param filePath Path where the file will be stored
19
- * @param data Data to store (ArrayBuffer, Blob, or string)
24
+ * @param filePath - Path where the file will be stored
25
+ * @param data - Data to store (ArrayBuffer, Blob, or string)
20
26
  * @returns Number of bytes written
21
27
  */
22
28
  saveFile(filePath: string, data: AttachmentData): Promise<number>;
23
29
 
24
30
  /**
25
31
  * Retrieves file data as an ArrayBuffer.
26
- * @param filePath Path where the file is stored
32
+ * @param filePath - Path where the file is stored
27
33
  * @returns ArrayBuffer containing the file data
28
34
  */
29
35
  readFile(filePath: string): Promise<ArrayBuffer>;
30
36
 
31
37
  /**
32
38
  * Deletes the file at the given path.
33
- * @param filePath Path where the file is stored
39
+ * @param filePath - Path where the file is stored
34
40
  */
35
41
  deleteFile(filePath: string): Promise<void>;
36
42
 
37
43
  /**
38
44
  * Checks if a file exists at the given path.
39
- * @param filePath Path where the file is stored
45
+ * @param filePath - Path where the file is stored
40
46
  * @returns True if the file exists, false otherwise
41
47
  */
42
48
  fileExists(filePath: string): Promise<boolean>;
43
49
 
44
50
  /**
45
51
  * Creates a directory at the specified path.
46
- * @param path The full path to the directory
52
+ * @param path - The full path to the directory
47
53
  */
48
54
  makeDir(path: string): Promise<void>;
49
55
 
50
56
  /**
51
57
  * Removes a directory at the specified path.
52
- * @param path The full path to the directory
58
+ * @param path - The full path to the directory
53
59
  */
54
60
  rmDir(path: string): Promise<void>;
55
61
 
@@ -65,7 +71,7 @@ export interface LocalStorageAdapter {
65
71
 
66
72
  /**
67
73
  * Returns the file path for the provided filename in the storage directory.
68
- * @param filename The filename to get the path for
74
+ * @param filename - The filename to get the path for
69
75
  * @returns The full file path
70
76
  */
71
77
  getLocalUri(filename: string): string;
@@ -427,10 +427,12 @@ type WatchedAttachmentItem = {
427
427
  id: string;
428
428
  fileExtension: string; // e.g., 'jpg', 'pdf'
429
429
  metaData?: string;
430
+ mediaType?: string; // e.g., 'image/jpeg'
430
431
  } | {
431
432
  id: string;
432
433
  filename: string; // e.g., 'document.pdf'
433
434
  metaData?: string;
435
+ mediaType?: string; // e.g., 'application/pdf'
434
436
  };
435
437
  ```
436
438
 
@@ -10,21 +10,21 @@ import { AttachmentRecord } from './Schema.js';
10
10
  export interface RemoteStorageAdapter {
11
11
  /**
12
12
  * Uploads a file to remote storage.
13
- * @param fileData The binary content of the file to upload
14
- * @param attachment The associated attachment metadata
13
+ * @param fileData - The binary content of the file to upload
14
+ * @param attachment - The associated attachment metadata
15
15
  */
16
16
  uploadFile(fileData: ArrayBuffer, attachment: AttachmentRecord): Promise<void>;
17
17
 
18
18
  /**
19
19
  * Downloads a file from remote storage.
20
- * @param attachment The attachment describing the file to download
20
+ * @param attachment - The attachment describing the file to download
21
21
  * @returns The binary data of the downloaded file
22
22
  */
23
23
  downloadFile(attachment: AttachmentRecord): Promise<ArrayBuffer>;
24
24
 
25
25
  /**
26
26
  * Deletes a file from remote storage.
27
- * @param attachment The attachment describing the file to delete
27
+ * @param attachment - The attachment describing the file to delete
28
28
  */
29
29
  deleteFile(attachment: AttachmentRecord): Promise<void>;
30
30
  }
@@ -1,13 +1,18 @@
1
1
  import { column } from '../db/schema/Column.js';
2
2
  import { Table } from '../db/schema/Table.js';
3
- import { TableV2Options } from '../db/schema/Table.js';
3
+ import { TableOptions } from '../db/schema/Table.js';
4
4
 
5
+ /**
6
+ * The default name of the local table storing attachment data.
7
+ *
8
+ * @alpha
9
+ */
5
10
  export const ATTACHMENT_TABLE = 'attachments';
6
11
 
7
12
  /**
8
13
  * AttachmentRecord represents an attachment in the local database.
9
14
  *
10
- * @experimental
15
+ * @alpha
11
16
  */
12
17
  export interface AttachmentRecord {
13
18
  id: string;
@@ -27,7 +32,7 @@ export interface AttachmentRecord {
27
32
  * @param row - The database row object
28
33
  * @returns The corresponding AttachmentRecord
29
34
  *
30
- * @experimental
35
+ * @alpha
31
36
  */
32
37
  export function attachmentFromSql(row: any): AttachmentRecord {
33
38
  return {
@@ -46,7 +51,7 @@ export function attachmentFromSql(row: any): AttachmentRecord {
46
51
  /**
47
52
  * AttachmentState represents the current synchronization state of an attachment.
48
53
  *
49
- * @experimental
54
+ * @alpha
50
55
  */
51
56
  export enum AttachmentState {
52
57
  QUEUED_UPLOAD = 0, // Attachment to be uploaded
@@ -56,12 +61,15 @@ export enum AttachmentState {
56
61
  ARCHIVED = 4 // Attachment has been orphaned, i.e. the associated record has been deleted
57
62
  }
58
63
 
59
- export interface AttachmentTableOptions extends Omit<TableV2Options, 'name' | 'columns'> {}
64
+ /**
65
+ * @alpha
66
+ */
67
+ export interface AttachmentTableOptions extends Omit<TableOptions, 'name' | 'columns'> {}
60
68
 
61
69
  /**
62
70
  * AttachmentTable defines the schema for the attachment queue table.
63
71
  *
64
- * @internal
72
+ * @alpha
65
73
  */
66
74
  export class AttachmentTable extends Table {
67
75
  constructor(options?: AttachmentTableOptions) {
@@ -1,4 +1,4 @@
1
- import { ILogger } from '../utils/Logger.js';
1
+ import { LogLevels, PowerSyncLogger } from '../utils/Logger.js';
2
2
  import { AttachmentService } from './AttachmentService.js';
3
3
  import { LocalStorageAdapter } from './LocalStorageAdapter.js';
4
4
  import { RemoteStorageAdapter } from './RemoteStorageAdapter.js';
@@ -16,14 +16,14 @@ export class SyncingService {
16
16
  private attachmentService: AttachmentService;
17
17
  private localStorage: LocalStorageAdapter;
18
18
  private remoteStorage: RemoteStorageAdapter;
19
- private logger: ILogger;
19
+ private logger: PowerSyncLogger;
20
20
  private errorHandler?: AttachmentErrorHandler;
21
21
 
22
22
  constructor(
23
23
  attachmentService: AttachmentService,
24
24
  localStorage: LocalStorageAdapter,
25
25
  remoteStorage: RemoteStorageAdapter,
26
- logger: ILogger,
26
+ logger: PowerSyncLogger,
27
27
  errorHandler?: AttachmentErrorHandler
28
28
  ) {
29
29
  this.attachmentService = attachmentService;
@@ -75,7 +75,7 @@ export class SyncingService {
75
75
  * @throws Error if the attachment has no localUri
76
76
  */
77
77
  async uploadAttachment(attachment: AttachmentRecord): Promise<AttachmentRecord> {
78
- this.logger.info(`Uploading attachment ${attachment.filename}`);
78
+ this.logger.log({ level: LogLevels.info, message: `Uploading attachment ${attachment.filename}` });
79
79
  try {
80
80
  if (attachment.localUri == null) {
81
81
  throw new Error(`No localUri for attachment ${attachment.id}`);
@@ -111,7 +111,7 @@ export class SyncingService {
111
111
  * @returns Updated attachment record with local URI and new state
112
112
  */
113
113
  async downloadAttachment(attachment: AttachmentRecord): Promise<AttachmentRecord> {
114
- this.logger.info(`Downloading attachment ${attachment.filename}`);
114
+ this.logger.log({ level: LogLevels.info, message: `Downloading attachment ${attachment.filename}` });
115
115
  try {
116
116
  const fileData = await this.remoteStorage.downloadFile(attachment);
117
117
 
@@ -183,7 +183,11 @@ export class SyncingService {
183
183
  try {
184
184
  await this.localStorage.deleteFile(attachment.localUri);
185
185
  } catch (error) {
186
- this.logger.error('Error deleting local file for archived attachment', error);
186
+ this.logger.log({
187
+ level: LogLevels.error,
188
+ message: 'Error deleting local file for archived attachment',
189
+ error
190
+ });
187
191
  }
188
192
  }
189
193
  }