@powersync/service-core 0.8.8 → 0.10.0

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 (376) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/dist/api/RouteAPI.d.ts +67 -0
  3. package/dist/api/RouteAPI.js +2 -0
  4. package/dist/api/RouteAPI.js.map +1 -0
  5. package/dist/api/api-index.d.ts +1 -0
  6. package/dist/api/api-index.js +1 -0
  7. package/dist/api/api-index.js.map +1 -1
  8. package/dist/api/diagnostics.d.ts +4 -4
  9. package/dist/api/diagnostics.js +170 -158
  10. package/dist/api/diagnostics.js.map +1 -1
  11. package/dist/api/schema.d.ts +3 -5
  12. package/dist/api/schema.js +14 -80
  13. package/dist/api/schema.js.map +1 -1
  14. package/dist/auth/CachedKeyCollector.js.map +1 -1
  15. package/dist/auth/KeySpec.js.map +1 -1
  16. package/dist/auth/KeyStore.d.ts +7 -4
  17. package/dist/auth/KeyStore.js +1 -1
  18. package/dist/auth/KeyStore.js.map +1 -1
  19. package/dist/auth/LeakyBucket.js.map +1 -1
  20. package/dist/auth/RemoteJWKSCollector.d.ts +0 -2
  21. package/dist/auth/RemoteJWKSCollector.js.map +1 -1
  22. package/dist/auth/StaticSupabaseKeyCollector.d.ts +19 -0
  23. package/dist/auth/StaticSupabaseKeyCollector.js +28 -0
  24. package/dist/auth/StaticSupabaseKeyCollector.js.map +1 -0
  25. package/dist/auth/auth-index.d.ts +1 -1
  26. package/dist/auth/auth-index.js +1 -1
  27. package/dist/auth/auth-index.js.map +1 -1
  28. package/dist/db/mongo.js +5 -3
  29. package/dist/db/mongo.js.map +1 -1
  30. package/dist/entry/cli-entry.js +3 -2
  31. package/dist/entry/cli-entry.js.map +1 -1
  32. package/dist/entry/commands/compact-action.js +90 -14
  33. package/dist/entry/commands/compact-action.js.map +1 -1
  34. package/dist/entry/commands/migrate-action.js +4 -5
  35. package/dist/entry/commands/migrate-action.js.map +1 -1
  36. package/dist/entry/commands/teardown-action.js +2 -2
  37. package/dist/entry/commands/teardown-action.js.map +1 -1
  38. package/dist/index.d.ts +4 -2
  39. package/dist/index.js +4 -2
  40. package/dist/index.js.map +1 -1
  41. package/dist/locks/MongoLocks.js.map +1 -1
  42. package/dist/metrics/Metrics.d.ts +2 -2
  43. package/dist/metrics/Metrics.js +5 -13
  44. package/dist/metrics/Metrics.js.map +1 -1
  45. package/dist/migrations/db/migrations/1684951997326-init.d.ts +2 -2
  46. package/dist/migrations/db/migrations/1684951997326-init.js +4 -2
  47. package/dist/migrations/db/migrations/1684951997326-init.js.map +1 -1
  48. package/dist/migrations/db/migrations/1702295701188-sync-rule-state.d.ts +2 -2
  49. package/dist/migrations/db/migrations/1702295701188-sync-rule-state.js +4 -2
  50. package/dist/migrations/db/migrations/1702295701188-sync-rule-state.js.map +1 -1
  51. package/dist/migrations/db/migrations/1711543888062-write-checkpoint-index.d.ts +2 -2
  52. package/dist/migrations/db/migrations/1711543888062-write-checkpoint-index.js +4 -2
  53. package/dist/migrations/db/migrations/1711543888062-write-checkpoint-index.js.map +1 -1
  54. package/dist/migrations/db/migrations/1727099539247-custom-write-checkpoint-index.d.ts +3 -0
  55. package/dist/migrations/db/migrations/1727099539247-custom-write-checkpoint-index.js +31 -0
  56. package/dist/migrations/db/migrations/1727099539247-custom-write-checkpoint-index.js.map +1 -0
  57. package/dist/migrations/executor.js.map +1 -1
  58. package/dist/migrations/migrations.d.ts +8 -0
  59. package/dist/migrations/migrations.js +19 -7
  60. package/dist/migrations/migrations.js.map +1 -1
  61. package/dist/migrations/store/migration-store.js.map +1 -1
  62. package/dist/modules/AbstractModule.d.ts +26 -0
  63. package/dist/modules/AbstractModule.js +11 -0
  64. package/dist/modules/AbstractModule.js.map +1 -0
  65. package/dist/modules/ModuleManager.d.ts +11 -0
  66. package/dist/modules/ModuleManager.js +32 -0
  67. package/dist/modules/ModuleManager.js.map +1 -0
  68. package/dist/modules/modules-index.d.ts +2 -0
  69. package/dist/modules/modules-index.js +3 -0
  70. package/dist/modules/modules-index.js.map +1 -0
  71. package/dist/replication/AbstractReplicationJob.d.ts +37 -0
  72. package/dist/replication/AbstractReplicationJob.js +51 -0
  73. package/dist/replication/AbstractReplicationJob.js.map +1 -0
  74. package/dist/replication/AbstractReplicator.d.ts +53 -0
  75. package/dist/replication/AbstractReplicator.js +250 -0
  76. package/dist/replication/AbstractReplicator.js.map +1 -0
  77. package/dist/replication/ErrorRateLimiter.d.ts +0 -10
  78. package/dist/replication/ErrorRateLimiter.js +1 -42
  79. package/dist/replication/ErrorRateLimiter.js.map +1 -1
  80. package/dist/replication/ReplicationEngine.d.ts +18 -0
  81. package/dist/replication/ReplicationEngine.js +41 -0
  82. package/dist/replication/ReplicationEngine.js.map +1 -0
  83. package/dist/replication/ReplicationModule.d.ts +51 -0
  84. package/dist/replication/ReplicationModule.js +68 -0
  85. package/dist/replication/ReplicationModule.js.map +1 -0
  86. package/dist/replication/replication-index.d.ts +4 -6
  87. package/dist/replication/replication-index.js +4 -6
  88. package/dist/replication/replication-index.js.map +1 -1
  89. package/dist/routes/RouterEngine.d.ts +42 -0
  90. package/dist/routes/RouterEngine.js +80 -0
  91. package/dist/routes/RouterEngine.js.map +1 -0
  92. package/dist/routes/auth.d.ts +2 -2
  93. package/dist/routes/auth.js +11 -11
  94. package/dist/routes/auth.js.map +1 -1
  95. package/dist/routes/configure-fastify.d.ts +37 -23
  96. package/dist/routes/configure-fastify.js +18 -18
  97. package/dist/routes/configure-fastify.js.map +1 -1
  98. package/dist/routes/configure-rsocket.d.ts +3 -4
  99. package/dist/routes/configure-rsocket.js +7 -4
  100. package/dist/routes/configure-rsocket.js.map +1 -1
  101. package/dist/routes/endpoints/admin.d.ts +30 -0
  102. package/dist/routes/endpoints/admin.js +46 -67
  103. package/dist/routes/endpoints/admin.js.map +1 -1
  104. package/dist/routes/endpoints/checkpointing.js +103 -15
  105. package/dist/routes/endpoints/checkpointing.js.map +1 -1
  106. package/dist/routes/endpoints/socket-route.js +8 -6
  107. package/dist/routes/endpoints/socket-route.js.map +1 -1
  108. package/dist/routes/endpoints/sync-rules.d.ts +1 -1
  109. package/dist/routes/endpoints/sync-rules.js +32 -23
  110. package/dist/routes/endpoints/sync-rules.js.map +1 -1
  111. package/dist/routes/endpoints/sync-stream.d.ts +0 -1
  112. package/dist/routes/endpoints/sync-stream.js +8 -8
  113. package/dist/routes/endpoints/sync-stream.js.map +1 -1
  114. package/dist/routes/hooks.js.map +1 -1
  115. package/dist/routes/route-register.js.map +1 -1
  116. package/dist/routes/router.d.ts +9 -2
  117. package/dist/routes/router.js.map +1 -1
  118. package/dist/routes/routes-index.d.ts +1 -0
  119. package/dist/routes/routes-index.js +1 -0
  120. package/dist/routes/routes-index.js.map +1 -1
  121. package/dist/runner/teardown.js +109 -76
  122. package/dist/runner/teardown.js.map +1 -1
  123. package/dist/storage/BucketStorage.d.ts +86 -36
  124. package/dist/storage/BucketStorage.js +6 -10
  125. package/dist/storage/BucketStorage.js.map +1 -1
  126. package/dist/storage/ChecksumCache.js.map +1 -1
  127. package/dist/storage/MongoBucketStorage.d.ts +7 -11
  128. package/dist/storage/MongoBucketStorage.js +48 -41
  129. package/dist/storage/MongoBucketStorage.js.map +1 -1
  130. package/dist/storage/ReplicationEventPayload.d.ts +14 -0
  131. package/dist/storage/ReplicationEventPayload.js +2 -0
  132. package/dist/storage/ReplicationEventPayload.js.map +1 -0
  133. package/dist/storage/SourceEntity.d.ts +20 -0
  134. package/dist/storage/SourceEntity.js +2 -0
  135. package/dist/storage/SourceEntity.js.map +1 -0
  136. package/dist/storage/SourceTable.d.ts +12 -5
  137. package/dist/storage/SourceTable.js +12 -5
  138. package/dist/storage/SourceTable.js.map +1 -1
  139. package/dist/storage/StorageEngine.d.ts +28 -0
  140. package/dist/storage/StorageEngine.js +45 -0
  141. package/dist/storage/StorageEngine.js.map +1 -0
  142. package/dist/storage/StorageProvider.d.ts +21 -0
  143. package/dist/storage/StorageProvider.js +2 -0
  144. package/dist/storage/StorageProvider.js.map +1 -0
  145. package/dist/storage/WriteCheckpointAPI.d.ts +74 -0
  146. package/dist/storage/WriteCheckpointAPI.js +16 -0
  147. package/dist/storage/WriteCheckpointAPI.js.map +1 -0
  148. package/dist/storage/mongo/MongoBucketBatch.d.ts +24 -5
  149. package/dist/storage/mongo/MongoBucketBatch.js +119 -62
  150. package/dist/storage/mongo/MongoBucketBatch.js.map +1 -1
  151. package/dist/storage/mongo/MongoCompactor.js +20 -3
  152. package/dist/storage/mongo/MongoCompactor.js.map +1 -1
  153. package/dist/storage/mongo/MongoIdSequence.js.map +1 -1
  154. package/dist/storage/mongo/MongoPersistedSyncRulesContent.d.ts +2 -2
  155. package/dist/storage/mongo/MongoPersistedSyncRulesContent.js +2 -2
  156. package/dist/storage/mongo/MongoPersistedSyncRulesContent.js.map +1 -1
  157. package/dist/storage/mongo/MongoStorageProvider.d.ts +5 -0
  158. package/dist/storage/mongo/MongoStorageProvider.js +26 -0
  159. package/dist/storage/mongo/MongoStorageProvider.js.map +1 -0
  160. package/dist/storage/mongo/MongoSyncBucketStorage.d.ts +18 -10
  161. package/dist/storage/mongo/MongoSyncBucketStorage.js +140 -25
  162. package/dist/storage/mongo/MongoSyncBucketStorage.js.map +1 -1
  163. package/dist/storage/mongo/MongoSyncRulesLock.js +1 -1
  164. package/dist/storage/mongo/MongoSyncRulesLock.js.map +1 -1
  165. package/dist/storage/mongo/MongoWriteCheckpointAPI.d.ts +20 -0
  166. package/dist/storage/mongo/MongoWriteCheckpointAPI.js +103 -0
  167. package/dist/storage/mongo/MongoWriteCheckpointAPI.js.map +1 -0
  168. package/dist/storage/mongo/OperationBatch.d.ts +13 -4
  169. package/dist/storage/mongo/OperationBatch.js +25 -7
  170. package/dist/storage/mongo/OperationBatch.js.map +1 -1
  171. package/dist/storage/mongo/PersistedBatch.d.ts +3 -3
  172. package/dist/storage/mongo/PersistedBatch.js +2 -2
  173. package/dist/storage/mongo/PersistedBatch.js.map +1 -1
  174. package/dist/storage/mongo/config.d.ts +19 -0
  175. package/dist/storage/mongo/config.js +26 -0
  176. package/dist/storage/mongo/config.js.map +1 -0
  177. package/dist/storage/mongo/db.d.ts +3 -2
  178. package/dist/storage/mongo/db.js +1 -0
  179. package/dist/storage/mongo/db.js.map +1 -1
  180. package/dist/storage/mongo/models.d.ts +20 -5
  181. package/dist/storage/mongo/models.js.map +1 -1
  182. package/dist/storage/mongo/util.d.ts +12 -1
  183. package/dist/storage/mongo/util.js +50 -2
  184. package/dist/storage/mongo/util.js.map +1 -1
  185. package/dist/storage/storage-index.d.ts +8 -2
  186. package/dist/storage/storage-index.js +8 -2
  187. package/dist/storage/storage-index.js.map +1 -1
  188. package/dist/sync/BroadcastIterable.d.ts +0 -1
  189. package/dist/sync/BroadcastIterable.js.map +1 -1
  190. package/dist/sync/LastValueSink.d.ts +0 -1
  191. package/dist/sync/LastValueSink.js.map +1 -1
  192. package/dist/sync/merge.d.ts +0 -1
  193. package/dist/sync/merge.js.map +1 -1
  194. package/dist/sync/safeRace.js.map +1 -1
  195. package/dist/sync/sync.d.ts +1 -1
  196. package/dist/sync/sync.js +5 -5
  197. package/dist/sync/sync.js.map +1 -1
  198. package/dist/sync/util.d.ts +0 -2
  199. package/dist/sync/util.js.map +1 -1
  200. package/dist/system/ServiceContext.d.ts +37 -0
  201. package/dist/system/ServiceContext.js +48 -0
  202. package/dist/system/ServiceContext.js.map +1 -0
  203. package/dist/system/system-index.d.ts +1 -1
  204. package/dist/system/system-index.js +1 -1
  205. package/dist/system/system-index.js.map +1 -1
  206. package/dist/util/Mutex.js.map +1 -1
  207. package/dist/util/config/collectors/config-collector.js.map +1 -1
  208. package/dist/util/config/collectors/impl/base64-config-collector.js.map +1 -1
  209. package/dist/util/config/collectors/impl/filesystem-config-collector.js.map +1 -1
  210. package/dist/util/config/compound-config-collector.d.ts +9 -2
  211. package/dist/util/config/compound-config-collector.js +31 -23
  212. package/dist/util/config/compound-config-collector.js.map +1 -1
  213. package/dist/util/config/sync-rules/impl/base64-sync-rules-collector.js.map +1 -1
  214. package/dist/util/config/sync-rules/impl/filesystem-sync-rules-collector.js.map +1 -1
  215. package/dist/util/config/sync-rules/impl/inline-sync-rules-collector.js.map +1 -1
  216. package/dist/util/config/sync-rules/sync-rules-provider.d.ts +9 -0
  217. package/dist/util/config/sync-rules/sync-rules-provider.js +15 -0
  218. package/dist/util/config/sync-rules/sync-rules-provider.js.map +1 -0
  219. package/dist/util/config/types.d.ts +7 -4
  220. package/dist/util/config/types.js.map +1 -1
  221. package/dist/util/config.d.ts +3 -4
  222. package/dist/util/config.js +5 -20
  223. package/dist/util/config.js.map +1 -1
  224. package/dist/util/memory-tracking.js.map +1 -1
  225. package/dist/util/secs.js.map +1 -1
  226. package/dist/util/util-index.d.ts +3 -6
  227. package/dist/util/util-index.js +3 -6
  228. package/dist/util/util-index.js.map +1 -1
  229. package/dist/util/utils.d.ts +10 -7
  230. package/dist/util/utils.js +36 -25
  231. package/dist/util/utils.js.map +1 -1
  232. package/package.json +8 -12
  233. package/src/api/RouteAPI.ts +78 -0
  234. package/src/api/api-index.ts +1 -0
  235. package/src/api/diagnostics.ts +18 -70
  236. package/src/api/schema.ts +18 -90
  237. package/src/auth/KeyStore.ts +9 -6
  238. package/src/auth/RemoteJWKSCollector.ts +4 -1
  239. package/src/auth/StaticSupabaseKeyCollector.ts +31 -0
  240. package/src/auth/auth-index.ts +1 -1
  241. package/src/db/mongo.ts +5 -3
  242. package/src/entry/cli-entry.ts +3 -2
  243. package/src/entry/commands/compact-action.ts +24 -12
  244. package/src/entry/commands/migrate-action.ts +5 -8
  245. package/src/entry/commands/teardown-action.ts +2 -2
  246. package/src/index.ts +5 -2
  247. package/src/metrics/Metrics.ts +6 -16
  248. package/src/migrations/db/migrations/1684951997326-init.ts +9 -4
  249. package/src/migrations/db/migrations/1702295701188-sync-rule-state.ts +7 -4
  250. package/src/migrations/db/migrations/1711543888062-write-checkpoint-index.ts +6 -4
  251. package/src/migrations/db/migrations/1727099539247-custom-write-checkpoint-index.ts +37 -0
  252. package/src/migrations/migrations.ts +24 -8
  253. package/src/modules/AbstractModule.ts +37 -0
  254. package/src/modules/ModuleManager.ts +34 -0
  255. package/src/modules/modules-index.ts +2 -0
  256. package/src/replication/AbstractReplicationJob.ts +79 -0
  257. package/src/replication/AbstractReplicator.ts +228 -0
  258. package/src/replication/ErrorRateLimiter.ts +0 -44
  259. package/src/replication/ReplicationEngine.ts +43 -0
  260. package/src/replication/ReplicationModule.ts +122 -0
  261. package/src/replication/replication-index.ts +4 -6
  262. package/src/routes/RouterEngine.ts +120 -0
  263. package/src/routes/auth.ts +21 -12
  264. package/src/routes/configure-fastify.ts +26 -27
  265. package/src/routes/configure-rsocket.ts +13 -8
  266. package/src/routes/endpoints/admin.ts +72 -76
  267. package/src/routes/endpoints/checkpointing.ts +51 -11
  268. package/src/routes/endpoints/socket-route.ts +10 -6
  269. package/src/routes/endpoints/sync-rules.ts +41 -25
  270. package/src/routes/endpoints/sync-stream.ts +8 -8
  271. package/src/routes/router.ts +8 -3
  272. package/src/routes/routes-index.ts +1 -0
  273. package/src/runner/teardown.ts +50 -88
  274. package/src/storage/BucketStorage.ts +103 -41
  275. package/src/storage/MongoBucketStorage.ts +65 -53
  276. package/src/storage/ReplicationEventPayload.ts +16 -0
  277. package/src/storage/SourceEntity.ts +22 -0
  278. package/src/storage/SourceTable.ts +14 -7
  279. package/src/storage/StorageEngine.ts +62 -0
  280. package/src/storage/StorageProvider.ts +27 -0
  281. package/src/storage/WriteCheckpointAPI.ts +85 -0
  282. package/src/storage/mongo/MongoBucketBatch.ts +164 -84
  283. package/src/storage/mongo/MongoCompactor.ts +25 -4
  284. package/src/storage/mongo/MongoPersistedSyncRulesContent.ts +7 -4
  285. package/src/storage/mongo/MongoStorageProvider.ts +31 -0
  286. package/src/storage/mongo/MongoSyncBucketStorage.ts +118 -41
  287. package/src/storage/mongo/MongoSyncRulesLock.ts +7 -3
  288. package/src/storage/mongo/MongoWriteCheckpointAPI.ts +151 -0
  289. package/src/storage/mongo/OperationBatch.ts +28 -12
  290. package/src/storage/mongo/PersistedBatch.ts +10 -6
  291. package/src/storage/mongo/config.ts +40 -0
  292. package/src/storage/mongo/db.ts +4 -1
  293. package/src/storage/mongo/models.ts +21 -5
  294. package/src/storage/mongo/util.ts +48 -3
  295. package/src/storage/storage-index.ts +8 -2
  296. package/src/sync/sync.ts +7 -4
  297. package/src/sync/util.ts +0 -1
  298. package/src/system/ServiceContext.ts +68 -0
  299. package/src/system/system-index.ts +1 -1
  300. package/src/util/config/compound-config-collector.ts +48 -30
  301. package/src/util/config/sync-rules/sync-rules-provider.ts +18 -0
  302. package/src/util/config/types.ts +7 -5
  303. package/src/util/config.ts +6 -23
  304. package/src/util/util-index.ts +3 -6
  305. package/src/util/utils.ts +48 -41
  306. package/test/src/__snapshots__/sync.test.ts.snap +14 -14
  307. package/test/src/auth.test.ts +7 -7
  308. package/test/src/broadcast_iterable.test.ts +1 -1
  309. package/test/src/compacting.test.ts +50 -40
  310. package/test/src/data_storage.test.ts +382 -202
  311. package/test/src/env.ts +1 -3
  312. package/test/src/merge_iterable.test.ts +1 -6
  313. package/test/src/routes/probes.integration.test.ts +34 -30
  314. package/test/src/setup.ts +1 -1
  315. package/test/src/stream_utils.ts +42 -0
  316. package/test/src/sync.test.ts +115 -39
  317. package/test/src/util.ts +48 -51
  318. package/test/tsconfig.json +1 -1
  319. package/tsconfig.tsbuildinfo +1 -1
  320. package/vitest.config.ts +7 -1
  321. package/dist/auth/SupabaseKeyCollector.d.ts +0 -22
  322. package/dist/auth/SupabaseKeyCollector.js +0 -61
  323. package/dist/auth/SupabaseKeyCollector.js.map +0 -1
  324. package/dist/replication/PgRelation.d.ts +0 -16
  325. package/dist/replication/PgRelation.js +0 -26
  326. package/dist/replication/PgRelation.js.map +0 -1
  327. package/dist/replication/WalConnection.d.ts +0 -34
  328. package/dist/replication/WalConnection.js +0 -190
  329. package/dist/replication/WalConnection.js.map +0 -1
  330. package/dist/replication/WalStream.d.ts +0 -57
  331. package/dist/replication/WalStream.js +0 -519
  332. package/dist/replication/WalStream.js.map +0 -1
  333. package/dist/replication/WalStreamManager.d.ts +0 -30
  334. package/dist/replication/WalStreamManager.js +0 -198
  335. package/dist/replication/WalStreamManager.js.map +0 -1
  336. package/dist/replication/WalStreamRunner.d.ts +0 -38
  337. package/dist/replication/WalStreamRunner.js +0 -155
  338. package/dist/replication/WalStreamRunner.js.map +0 -1
  339. package/dist/replication/util.d.ts +0 -9
  340. package/dist/replication/util.js +0 -62
  341. package/dist/replication/util.js.map +0 -1
  342. package/dist/system/CorePowerSyncSystem.d.ts +0 -23
  343. package/dist/system/CorePowerSyncSystem.js +0 -52
  344. package/dist/system/CorePowerSyncSystem.js.map +0 -1
  345. package/dist/util/PgManager.d.ts +0 -24
  346. package/dist/util/PgManager.js +0 -55
  347. package/dist/util/PgManager.js.map +0 -1
  348. package/dist/util/migration_lib.d.ts +0 -11
  349. package/dist/util/migration_lib.js +0 -64
  350. package/dist/util/migration_lib.js.map +0 -1
  351. package/dist/util/pgwire_utils.d.ts +0 -24
  352. package/dist/util/pgwire_utils.js +0 -117
  353. package/dist/util/pgwire_utils.js.map +0 -1
  354. package/dist/util/populate_test_data.d.ts +0 -8
  355. package/dist/util/populate_test_data.js +0 -65
  356. package/dist/util/populate_test_data.js.map +0 -1
  357. package/src/auth/SupabaseKeyCollector.ts +0 -67
  358. package/src/replication/PgRelation.ts +0 -42
  359. package/src/replication/WalConnection.ts +0 -227
  360. package/src/replication/WalStream.ts +0 -631
  361. package/src/replication/WalStreamManager.ts +0 -213
  362. package/src/replication/WalStreamRunner.ts +0 -180
  363. package/src/replication/util.ts +0 -76
  364. package/src/system/CorePowerSyncSystem.ts +0 -64
  365. package/src/util/PgManager.ts +0 -64
  366. package/src/util/migration_lib.ts +0 -79
  367. package/src/util/pgwire_utils.ts +0 -139
  368. package/src/util/populate_test_data.ts +0 -78
  369. package/test/src/__snapshots__/pg_test.test.ts.snap +0 -256
  370. package/test/src/large_batch.test.ts +0 -194
  371. package/test/src/pg_test.test.ts +0 -450
  372. package/test/src/schema_changes.test.ts +0 -545
  373. package/test/src/slow_tests.test.ts +0 -338
  374. package/test/src/validation.test.ts +0 -63
  375. package/test/src/wal_stream.test.ts +0 -319
  376. package/test/src/wal_stream_utils.ts +0 -156
@@ -0,0 +1,228 @@
1
+ import { container, logger } from '@powersync/lib-services-framework';
2
+ import { hrtime } from 'node:process';
3
+ import winston from 'winston';
4
+ import * as storage from '../storage/storage-index.js';
5
+ import { StorageEngine } from '../storage/storage-index.js';
6
+ import { SyncRulesProvider } from '../util/config/sync-rules/sync-rules-provider.js';
7
+ import { AbstractReplicationJob } from './AbstractReplicationJob.js';
8
+ import { ErrorRateLimiter } from './ErrorRateLimiter.js';
9
+
10
+ // 5 minutes
11
+ const PING_INTERVAL = 1_000_000_000n * 300n;
12
+
13
+ export interface CreateJobOptions {
14
+ lock: storage.ReplicationLock;
15
+ storage: storage.SyncRulesBucketStorage;
16
+ }
17
+
18
+ export interface AbstractReplicatorOptions {
19
+ id: string;
20
+ storageEngine: StorageEngine;
21
+ syncRuleProvider: SyncRulesProvider;
22
+ /**
23
+ * This limits the effect of retries when there is a persistent issue.
24
+ */
25
+ rateLimiter: ErrorRateLimiter;
26
+ }
27
+
28
+ /**
29
+ * A replicator manages the mechanics for replicating data from a data source to a storage bucket.
30
+ * This includes copying across the original data set and then keeping it in sync with the data source using Replication Jobs.
31
+ * It also handles any changes to the sync rules.
32
+ */
33
+ export abstract class AbstractReplicator<T extends AbstractReplicationJob = AbstractReplicationJob> {
34
+ protected logger: winston.Logger;
35
+ /**
36
+ * Map of replication jobs by sync rule id. Usually there is only one running job, but there could be two when
37
+ * transitioning to a new set of sync rules.
38
+ * @private
39
+ */
40
+ private replicationJobs = new Map<number, T>();
41
+ private stopped = false;
42
+
43
+ // First ping is only after 5 minutes, not when starting
44
+ private lastPing = hrtime.bigint();
45
+
46
+ protected constructor(private options: AbstractReplicatorOptions) {
47
+ this.logger = logger.child({ name: `Replicator:${options.id}` });
48
+ }
49
+
50
+ abstract createJob(options: CreateJobOptions): T;
51
+
52
+ /**
53
+ * Clean up any configuration or state for the specified sync rule on the datasource.
54
+ * Should be a no-op if the configuration has already been cleared
55
+ */
56
+ abstract cleanUp(syncRuleStorage: storage.SyncRulesBucketStorage): Promise<void>;
57
+
58
+ public get id() {
59
+ return this.options.id;
60
+ }
61
+
62
+ protected get storage() {
63
+ return this.options.storageEngine.activeBucketStorage;
64
+ }
65
+
66
+ protected get syncRuleProvider() {
67
+ return this.options.syncRuleProvider;
68
+ }
69
+
70
+ protected get rateLimiter() {
71
+ return this.options.rateLimiter;
72
+ }
73
+
74
+ public async start(): Promise<void> {
75
+ this.runLoop().catch((e) => {
76
+ this.logger.error('Data source fatal replication error', e);
77
+ container.reporter.captureException(e);
78
+ setTimeout(() => {
79
+ process.exit(1);
80
+ }, 1000);
81
+ });
82
+ }
83
+
84
+ public async stop(): Promise<void> {
85
+ this.stopped = true;
86
+ let promises: Promise<void>[] = [];
87
+ for (const job of this.replicationJobs.values()) {
88
+ promises.push(job.stop());
89
+ }
90
+ await Promise.all(promises);
91
+ }
92
+
93
+ private async runLoop() {
94
+ const syncRules = await this.syncRuleProvider.get();
95
+ let configuredLock: storage.ReplicationLock | undefined = undefined;
96
+ if (syncRules != null) {
97
+ this.logger.info('Loaded sync rules');
98
+ try {
99
+ // Configure new sync rules, if they have changed.
100
+ // In that case, also immediately take out a lock, so that another process doesn't start replication on it.
101
+ const { lock } = await this.storage.configureSyncRules(syncRules, {
102
+ lock: true
103
+ });
104
+ if (lock) {
105
+ configuredLock = lock;
106
+ }
107
+ } catch (e) {
108
+ // Log, but continue with previous sync rules
109
+ this.logger.error(`Failed to update sync rules from configuration`, e);
110
+ }
111
+ } else {
112
+ this.logger.info('No sync rules configured - configure via API');
113
+ }
114
+ while (!this.stopped) {
115
+ await container.probes.touch();
116
+ try {
117
+ await this.refresh({ configured_lock: configuredLock });
118
+ // The lock is only valid on the first refresh.
119
+ configuredLock = undefined;
120
+
121
+ // Ensure that the replication jobs' connections are kept alive.
122
+ // We don't ping while in error retry back-off, to avoid having too failures.
123
+ if (this.rateLimiter.mayPing()) {
124
+ const now = hrtime.bigint();
125
+ if (now - this.lastPing >= PING_INTERVAL) {
126
+ for (const activeJob of this.replicationJobs.values()) {
127
+ await activeJob.keepAlive();
128
+ }
129
+
130
+ this.lastPing = now;
131
+ }
132
+ }
133
+ } catch (e) {
134
+ this.logger.error('Failed to refresh replication jobs', e);
135
+ }
136
+ await new Promise((resolve) => setTimeout(resolve, 5000));
137
+ }
138
+ }
139
+
140
+ private async refresh(options?: { configured_lock?: storage.ReplicationLock }) {
141
+ if (this.stopped) {
142
+ return;
143
+ }
144
+
145
+ let configuredLock = options?.configured_lock;
146
+
147
+ const existingJobs = new Map<number, T>(this.replicationJobs.entries());
148
+ const replicatingSyncRules = await this.storage.getReplicatingSyncRules();
149
+ const newJobs = new Map<number, T>();
150
+ for (let syncRules of replicatingSyncRules) {
151
+ const existingJob = existingJobs.get(syncRules.id);
152
+ if (existingJob && !existingJob.isStopped) {
153
+ // No change
154
+ existingJobs.delete(syncRules.id);
155
+ newJobs.set(syncRules.id, existingJob);
156
+ } else if (existingJob && existingJob.isStopped) {
157
+ // Stopped (e.g. fatal error).
158
+ // Remove from the list. Next refresh call will restart the job.
159
+ existingJobs.delete(syncRules.id);
160
+ } else {
161
+ // New sync rules were found (or resume after restart)
162
+ try {
163
+ let lock: storage.ReplicationLock;
164
+ if (configuredLock?.sync_rules_id == syncRules.id) {
165
+ lock = configuredLock;
166
+ } else {
167
+ lock = await syncRules.lock();
168
+ }
169
+ const storage = this.storage.getInstance(syncRules);
170
+ const newJob = this.createJob({
171
+ lock: lock,
172
+ storage: storage
173
+ });
174
+
175
+ newJobs.set(syncRules.id, newJob);
176
+ newJob.start();
177
+ } catch (e) {
178
+ // Could be a sync rules parse error,
179
+ // for example from stricter validation that was added.
180
+ // This will be retried every couple of seconds.
181
+ // When new (valid) sync rules are deployed and processed, this one be disabled.
182
+ this.logger.error('Failed to start replication for new sync rules', e);
183
+ }
184
+ }
185
+ }
186
+
187
+ this.replicationJobs = newJobs;
188
+
189
+ // Terminate any orphaned jobs that no longer have sync rules
190
+ for (let job of existingJobs.values()) {
191
+ // Old - stop and clean up
192
+ try {
193
+ await job.stop();
194
+ await this.terminateSyncRules(job.storage);
195
+ job.storage[Symbol.dispose]();
196
+ } catch (e) {
197
+ // This will be retried
198
+ this.logger.warn('Failed to terminate old replication job}', e);
199
+ }
200
+ }
201
+
202
+ // Sync rules stopped previously or by a different process.
203
+ const stopped = await this.storage.getStoppedSyncRules();
204
+ for (let syncRules of stopped) {
205
+ try {
206
+ using syncRuleStorage = this.storage.getInstance(syncRules);
207
+ await this.terminateSyncRules(syncRuleStorage);
208
+ } catch (e) {
209
+ this.logger.warn(`Failed clean up replication config for sync rule: ${syncRules.id}`, e);
210
+ }
211
+ }
212
+ }
213
+
214
+ protected createJobId(syncRuleId: number) {
215
+ return `${this.id}-${syncRuleId}`;
216
+ }
217
+
218
+ protected async terminateSyncRules(syncRuleStorage: storage.SyncRulesBucketStorage) {
219
+ this.logger.info(`Terminating sync rules: ${syncRuleStorage.group_id}...`);
220
+ try {
221
+ await this.cleanUp(syncRuleStorage);
222
+ await syncRuleStorage.terminate();
223
+ this.logger.info(`Successfully terminated sync rules: ${syncRuleStorage.group_id}`);
224
+ } catch (e) {
225
+ this.logger.warn(`Failed clean up replication config for sync rules: ${syncRuleStorage.group_id}`, e);
226
+ }
227
+ }
228
+ }
@@ -1,50 +1,6 @@
1
- import { setTimeout } from 'timers/promises';
2
-
3
1
  export interface ErrorRateLimiter {
4
2
  waitUntilAllowed(options?: { signal?: AbortSignal }): Promise<void>;
5
3
  reportError(e: any): void;
6
4
 
7
5
  mayPing(): boolean;
8
6
  }
9
-
10
- export class DefaultErrorRateLimiter implements ErrorRateLimiter {
11
- nextAllowed: number = Date.now();
12
-
13
- async waitUntilAllowed(options?: { signal?: AbortSignal | undefined } | undefined): Promise<void> {
14
- const delay = Math.max(0, this.nextAllowed - Date.now());
15
- // Minimum delay between connections, even without errors
16
- this.setDelay(500);
17
- await setTimeout(delay, undefined, { signal: options?.signal });
18
- }
19
-
20
- mayPing(): boolean {
21
- return Date.now() >= this.nextAllowed;
22
- }
23
-
24
- reportError(e: any): void {
25
- const message = (e.message as string) ?? '';
26
- if (message.includes('password authentication failed')) {
27
- // Wait 15 minutes, to avoid triggering Supabase's fail2ban
28
- this.setDelay(900_000);
29
- } else if (message.includes('ENOTFOUND')) {
30
- // DNS lookup issue - incorrect URI or deleted instance
31
- this.setDelay(120_000);
32
- } else if (message.includes('ECONNREFUSED')) {
33
- // Could be fail2ban or similar
34
- this.setDelay(120_000);
35
- } else if (
36
- message.includes('Unable to do postgres query on ended pool') ||
37
- message.includes('Postgres unexpectedly closed connection')
38
- ) {
39
- // Connection timed out - ignore / immediately retry
40
- // We don't explicitly set the delay to 0, since there could have been another error that
41
- // we need to respect.
42
- } else {
43
- this.setDelay(30_000);
44
- }
45
- }
46
-
47
- private setDelay(delay: number) {
48
- this.nextAllowed = Math.max(this.nextAllowed, Date.now() + delay);
49
- }
50
- }
@@ -0,0 +1,43 @@
1
+ import { logger } from '@powersync/lib-services-framework';
2
+ import { AbstractReplicator } from './AbstractReplicator.js';
3
+
4
+ export class ReplicationEngine {
5
+ private readonly replicators: Map<string, AbstractReplicator> = new Map();
6
+
7
+ /**
8
+ * Register a Replicator with the engine
9
+ *
10
+ * @param replicator
11
+ */
12
+ public register(replicator: AbstractReplicator) {
13
+ if (this.replicators.has(replicator.id)) {
14
+ throw new Error(`Replicator with id: ${replicator.id} already registered`);
15
+ }
16
+ logger.info(`Successfully registered Replicator ${replicator.id} with ReplicationEngine`);
17
+ this.replicators.set(replicator.id, replicator);
18
+ }
19
+
20
+ /**
21
+ * Start replication on all managed Replicators
22
+ */
23
+ public start(): void {
24
+ logger.info('Starting Replication Engine...');
25
+ for (const replicator of this.replicators.values()) {
26
+ logger.info(`Starting Replicator: ${replicator.id}`);
27
+ replicator.start();
28
+ }
29
+ logger.info('Successfully started Replication Engine.');
30
+ }
31
+
32
+ /**
33
+ * Stop replication on all managed Replicators
34
+ */
35
+ public async shutDown(): Promise<void> {
36
+ logger.info('Shutting down Replication Engine...');
37
+ for (const replicator of this.replicators.values()) {
38
+ logger.info(`Stopping Replicator: ${replicator.id}`);
39
+ await replicator.stop();
40
+ }
41
+ logger.info('Successfully shut down Replication Engine.');
42
+ }
43
+ }
@@ -0,0 +1,122 @@
1
+ import { DataSourceConfig } from '@powersync/service-types/dist/config/PowerSyncConfig.js';
2
+ import * as t from 'ts-codec';
3
+
4
+ import * as types from '@powersync/service-types';
5
+ import * as api from '../api/api-index.js';
6
+ import * as modules from '../modules/modules-index.js';
7
+ import * as system from '../system/system-index.js';
8
+ import { schema } from '@powersync/lib-services-framework';
9
+ import { AbstractReplicator } from './AbstractReplicator.js';
10
+ import { TearDownOptions } from '../modules/modules-index.js';
11
+
12
+ /**
13
+ * Provides a common interface for testing the connection to a DataSource.
14
+ */
15
+ export interface ConnectionTester<TConfig extends DataSourceConfig> {
16
+ /**
17
+ * Confirm if a connection can be established to the datasource for the provided datasource configuration
18
+ * @param config
19
+ */
20
+ testConnection(config: TConfig): Promise<void>;
21
+ }
22
+
23
+ export interface ReplicationModuleOptions extends modules.AbstractModuleOptions {
24
+ type: string;
25
+ configSchema: t.AnyCodec;
26
+ }
27
+
28
+ /**
29
+ * A replication module describes all the functionality that PowerSync requires to
30
+ * replicate data from a DataSource. Whenever a new data source is added to powersync this class should be extended.
31
+ */
32
+ export abstract class ReplicationModule<TConfig extends DataSourceConfig>
33
+ extends modules.AbstractModule
34
+ implements ConnectionTester<TConfig>
35
+ {
36
+ protected type: string;
37
+ protected configSchema: t.AnyCodec;
38
+ protected decodedConfig: TConfig | undefined;
39
+
40
+ /**
41
+ * @protected
42
+ * @param options
43
+ */
44
+ protected constructor(options: ReplicationModuleOptions) {
45
+ super(options);
46
+ this.type = options.type;
47
+ this.configSchema = options.configSchema;
48
+ }
49
+
50
+ /**
51
+ * Create the RouteAPI adapter for the DataSource required to service the sync API
52
+ * endpoints.
53
+ */
54
+ protected abstract createRouteAPIAdapter(): api.RouteAPI;
55
+
56
+ /**
57
+ * Create the Replicator to be used by the ReplicationEngine.
58
+ */
59
+ protected abstract createReplicator(context: system.ServiceContext): AbstractReplicator;
60
+
61
+ public abstract testConnection(config: TConfig): Promise<void>;
62
+
63
+ /**
64
+ * Register this module's Replicators and RouteAPI adapters if the required configuration is present.
65
+ */
66
+ public async initialize(context: system.ServiceContext): Promise<void> {
67
+ if (!context.configuration.connections) {
68
+ // No data source configuration found in the config skip for now
69
+ return;
70
+ }
71
+
72
+ const matchingConfig = context.configuration.connections.filter((dataSource) => dataSource.type === this.type);
73
+ if (!matchingConfig.length) {
74
+ // No configuration for this module was found
75
+ return;
76
+ }
77
+
78
+ if (matchingConfig.length > 1) {
79
+ this.logger.warning(
80
+ `Multiple data sources of type ${this.type} found in the configuration. Only the first will be used.`
81
+ );
82
+ }
83
+
84
+ try {
85
+ const baseMatchingConfig = matchingConfig[0] as TConfig;
86
+ // If decoding fails, log the error and continue, no replication will happen for this data source
87
+ this.decodeConfig(baseMatchingConfig);
88
+
89
+ context.replicationEngine?.register(this.createReplicator(context));
90
+ context.routerEngine?.registerAPI(this.createRouteAPIAdapter());
91
+ } catch (e) {
92
+ this.logger.error('Failed to initialize.', e);
93
+ }
94
+ }
95
+
96
+ protected decodeConfig(config: TConfig): void {
97
+ this.validateConfig(config);
98
+ this.decodedConfig = this.configSchema.decode(config);
99
+ }
100
+
101
+ private validateConfig(config: TConfig): void {
102
+ const validator = schema
103
+ .parseJSONSchema(
104
+ // This generates a schema for the encoded form of the codec
105
+ t.generateJSONSchema(this.configSchema, {
106
+ allowAdditional: true,
107
+ parsers: [types.configFile.portParser]
108
+ })
109
+ )
110
+ .validator();
111
+
112
+ const valid = validator.validate(config);
113
+
114
+ if (!valid.valid) {
115
+ throw new Error(`Failed to validate Module ${this.name} configuration: ${valid.errors.join(', ')}`);
116
+ }
117
+ }
118
+
119
+ protected getDefaultId(dataSourceName: string): string {
120
+ return `${this.type}-${dataSourceName}`;
121
+ }
122
+ }
@@ -1,7 +1,5 @@
1
+ export * from './AbstractReplicationJob.js';
2
+ export * from './AbstractReplicator.js';
1
3
  export * from './ErrorRateLimiter.js';
2
- export * from './PgRelation.js';
3
- export * from './util.js';
4
- export * from './WalConnection.js';
5
- export * from './WalStream.js';
6
- export * from './WalStreamManager.js';
7
- export * from './WalStreamRunner.js';
4
+ export * from './ReplicationEngine.js';
5
+ export * from './ReplicationModule.js';
@@ -0,0 +1,120 @@
1
+ import { logger } from '@powersync/lib-services-framework';
2
+
3
+ import * as api from '../api/api-index.js';
4
+
5
+ import { ADMIN_ROUTES } from './endpoints/admin.js';
6
+ import { CHECKPOINT_ROUTES } from './endpoints/checkpointing.js';
7
+ import { syncStreamReactive } from './endpoints/socket-route.js';
8
+ import { SYNC_RULES_ROUTES } from './endpoints/sync-rules.js';
9
+ import { SYNC_STREAM_ROUTES } from './endpoints/sync-stream.js';
10
+ import { SocketRouteGenerator } from './router-socket.js';
11
+ import { RouteDefinition } from './router.js';
12
+
13
+ export type RouterSetupResponse = {
14
+ onShutdown: () => Promise<void>;
15
+ };
16
+
17
+ export type RouterEngineRoutes = {
18
+ api_routes: RouteDefinition[];
19
+ stream_routes: RouteDefinition[];
20
+ socket_routes: SocketRouteGenerator[];
21
+ };
22
+
23
+ export type RouterSetup = (routes: RouterEngineRoutes) => Promise<RouterSetupResponse>;
24
+
25
+ /**
26
+ * Serves as a registry from which SyncAPIs can be retrieved based on Replication DataSource type
27
+ * Initially only one SyncAPI per DataSource type is supported
28
+ */
29
+ export class RouterEngine {
30
+ closed: boolean;
31
+ routes: RouterEngineRoutes;
32
+
33
+ protected stopHandlers: Set<() => void>;
34
+
35
+ /**
36
+ * A final cleanup handler to be executed after all stopHandlers
37
+ */
38
+ protected cleanupHandler: (() => Promise<void>) | null;
39
+
40
+ private api: api.RouteAPI | null;
41
+
42
+ constructor() {
43
+ this.api = null;
44
+ this.stopHandlers = new Set();
45
+ this.cleanupHandler = null;
46
+ this.closed = false;
47
+
48
+ // Default routes
49
+ this.routes = {
50
+ api_routes: [...ADMIN_ROUTES, ...CHECKPOINT_ROUTES, ...SYNC_RULES_ROUTES],
51
+ stream_routes: [...SYNC_STREAM_ROUTES],
52
+ socket_routes: [syncStreamReactive]
53
+ };
54
+ }
55
+
56
+ public registerAPI(api: api.RouteAPI) {
57
+ if (this.api) {
58
+ logger.warn('A RouteAPI has already been registered. Overriding existing implementation');
59
+ }
60
+
61
+ this.api = api;
62
+ }
63
+
64
+ public getAPI(): api.RouteAPI {
65
+ if (!this.api) {
66
+ throw new Error('No RouteAPI adapter has been registered yet.');
67
+ }
68
+ return this.api;
69
+ }
70
+
71
+ /**
72
+ * Starts the router given the configuration provided
73
+ */
74
+ async start(setup: RouterSetup) {
75
+ logger.info('Starting Router Engine...');
76
+ const { onShutdown } = await setup(this.routes);
77
+ this.cleanupHandler = onShutdown;
78
+ logger.info('Successfully started Router Engine.');
79
+ }
80
+
81
+ /**
82
+ * Runs all stop handlers then final cleanup.
83
+ */
84
+ async shutDown() {
85
+ logger.info('Shutting down Router Engine...');
86
+ // Close open streams, so that they don't block the server from closing.
87
+ // Note: This does not work well when streaming requests are queued. In that case, the server still doesn't
88
+ // close in the 30-second timeout.
89
+ this.closed = true;
90
+
91
+ logger.info(`Closing ${this.stopHandlers.size} streams.`);
92
+ for (let handler of this.stopHandlers) {
93
+ handler();
94
+ }
95
+
96
+ logger.info(`Running cleanup.`);
97
+
98
+ // Typically closes the server
99
+ await this.cleanupHandler?.();
100
+
101
+ // Close the api handlers
102
+ await this.api?.shutdown();
103
+ logger.info('Successfully shut down Router Engine.');
104
+ }
105
+
106
+ /**
107
+ * Add a stop handler callback to be executed when the router engine is being
108
+ * shutdown.
109
+ */
110
+ addStopHandler(handler: () => void): () => void {
111
+ if (this.closed) {
112
+ handler();
113
+ return () => {};
114
+ }
115
+ this.stopHandlers.add(handler);
116
+ return () => {
117
+ this.stopHandlers.delete(handler);
118
+ };
119
+ }
120
+ }
@@ -1,9 +1,9 @@
1
1
  import * as jose from 'jose';
2
2
 
3
3
  import * as auth from '../auth/auth-index.js';
4
+ import { ServiceContext } from '../system/ServiceContext.js';
4
5
  import * as util from '../util/util-index.js';
5
6
  import { BasicRouterRequest, Context, RequestEndpointHandlerPayload } from './router.js';
6
- import { CorePowerSyncSystem } from '../system/CorePowerSyncSystem.js';
7
7
 
8
8
  export function endpoint(req: BasicRouterRequest) {
9
9
  const protocol = req.headers['x-forwarded-proto'] ?? req.protocol;
@@ -108,7 +108,7 @@ export async function authorizeUser(context: Context, authHeader: string = '') {
108
108
  };
109
109
  }
110
110
 
111
- const { context: tokenContext, errors } = await generateContext(context.system, token);
111
+ const { context: tokenContext, errors } = await generateContext(context.service_context, token);
112
112
 
113
113
  if (!tokenContext) {
114
114
  return {
@@ -121,14 +121,14 @@ export async function authorizeUser(context: Context, authHeader: string = '') {
121
121
  return { authorized: true };
122
122
  }
123
123
 
124
- export async function generateContext(system: CorePowerSyncSystem, token: string) {
125
- const config = system.config;
124
+ export async function generateContext(serviceContext: ServiceContext, token: string) {
125
+ const { configuration } = serviceContext;
126
126
 
127
127
  let tokenPayload: auth.JwtPayload;
128
128
  try {
129
- const maxAge = config.token_max_expiration;
130
- tokenPayload = await system.client_keystore.verifyJwt(token, {
131
- defaultAudiences: config.jwt_audiences,
129
+ const maxAge = configuration.token_max_expiration;
130
+ tokenPayload = await configuration.client_keystore.verifyJwt(token, {
131
+ defaultAudiences: configuration.jwt_audiences,
132
132
  maxAge: maxAge
133
133
  });
134
134
  return {
@@ -149,9 +149,14 @@ export async function generateContext(system: CorePowerSyncSystem, token: string
149
149
  * @deprecated
150
150
  */
151
151
  export const authDevUser = async (payload: RequestEndpointHandlerPayload) => {
152
- const context = payload.context;
152
+ const {
153
+ context: {
154
+ service_context: { configuration }
155
+ }
156
+ } = payload;
157
+
153
158
  const token = getTokenFromHeader(payload.request.headers.authorization as string);
154
- if (!context.system.config.dev.demo_auth) {
159
+ if (!configuration.dev.demo_auth) {
155
160
  return {
156
161
  authorized: false,
157
162
  errors: ['Authentication disabled']
@@ -170,7 +175,7 @@ export const authDevUser = async (payload: RequestEndpointHandlerPayload) => {
170
175
 
171
176
  let tokenPayload: auth.JwtPayload;
172
177
  try {
173
- tokenPayload = await context.system.dev_client_keystore.verifyJwt(token, {
178
+ tokenPayload = await configuration.dev_client_keystore.verifyJwt(token, {
174
179
  defaultAudiences: audience,
175
180
  maxAge: '31d'
176
181
  });
@@ -186,8 +191,12 @@ export const authDevUser = async (payload: RequestEndpointHandlerPayload) => {
186
191
  };
187
192
 
188
193
  export const authApi = (payload: RequestEndpointHandlerPayload) => {
189
- const context = payload.context;
190
- const api_keys = context.system.config.api_tokens;
194
+ const {
195
+ context: {
196
+ service_context: { configuration }
197
+ }
198
+ } = payload;
199
+ const api_keys = configuration.api_tokens;
191
200
  if (api_keys.length == 0) {
192
201
  return {
193
202
  authorized: false,