@livestore/common 0.3.0-dev.2 → 0.3.0-dev.22

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 (328) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/__tests__/fixture.d.ts +21 -21
  3. package/dist/adapter-types.d.ts +97 -53
  4. package/dist/adapter-types.d.ts.map +1 -1
  5. package/dist/adapter-types.js +17 -0
  6. package/dist/adapter-types.js.map +1 -1
  7. package/dist/bounded-collections.d.ts +1 -1
  8. package/dist/bounded-collections.d.ts.map +1 -1
  9. package/dist/debug-info.d.ts +1 -1
  10. package/dist/debug-info.d.ts.map +1 -1
  11. package/dist/derived-mutations.d.ts +5 -5
  12. package/dist/derived-mutations.d.ts.map +1 -1
  13. package/dist/derived-mutations.js +3 -3
  14. package/dist/derived-mutations.js.map +1 -1
  15. package/dist/derived-mutations.test.js.map +1 -1
  16. package/dist/devtools/devtools-messages-client-session.d.ts +389 -0
  17. package/dist/devtools/devtools-messages-client-session.d.ts.map +1 -0
  18. package/dist/devtools/devtools-messages-client-session.js +96 -0
  19. package/dist/devtools/devtools-messages-client-session.js.map +1 -0
  20. package/dist/devtools/devtools-messages-common.d.ts +61 -0
  21. package/dist/devtools/devtools-messages-common.d.ts.map +1 -0
  22. package/dist/devtools/devtools-messages-common.js +54 -0
  23. package/dist/devtools/devtools-messages-common.js.map +1 -0
  24. package/dist/devtools/devtools-messages-leader.d.ts +393 -0
  25. package/dist/devtools/devtools-messages-leader.d.ts.map +1 -0
  26. package/dist/devtools/devtools-messages-leader.js +148 -0
  27. package/dist/devtools/devtools-messages-leader.js.map +1 -0
  28. package/dist/devtools/devtools-messages.d.ts +3 -592
  29. package/dist/devtools/devtools-messages.d.ts.map +1 -1
  30. package/dist/devtools/devtools-messages.js +3 -171
  31. package/dist/devtools/devtools-messages.js.map +1 -1
  32. package/dist/devtools/devtools-sessioninfo.d.ts +28 -0
  33. package/dist/devtools/devtools-sessioninfo.d.ts.map +1 -0
  34. package/dist/devtools/devtools-sessioninfo.js +34 -0
  35. package/dist/devtools/devtools-sessioninfo.js.map +1 -0
  36. package/dist/devtools/mod.d.ts +39 -0
  37. package/dist/devtools/mod.d.ts.map +1 -0
  38. package/dist/devtools/mod.js +27 -0
  39. package/dist/devtools/mod.js.map +1 -0
  40. package/dist/index.d.ts +2 -6
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.js +2 -2
  43. package/dist/index.js.map +1 -1
  44. package/dist/init-singleton-tables.d.ts +2 -2
  45. package/dist/init-singleton-tables.d.ts.map +1 -1
  46. package/dist/init-singleton-tables.js.map +1 -1
  47. package/dist/leader-thread/LeaderSyncProcessor.d.ts +39 -0
  48. package/dist/leader-thread/LeaderSyncProcessor.d.ts.map +1 -0
  49. package/dist/leader-thread/LeaderSyncProcessor.js +527 -0
  50. package/dist/leader-thread/LeaderSyncProcessor.js.map +1 -0
  51. package/dist/leader-thread/apply-mutation.d.ts +5 -2
  52. package/dist/leader-thread/apply-mutation.d.ts.map +1 -1
  53. package/dist/leader-thread/apply-mutation.js +55 -35
  54. package/dist/leader-thread/apply-mutation.js.map +1 -1
  55. package/dist/leader-thread/connection.d.ts +34 -6
  56. package/dist/leader-thread/connection.d.ts.map +1 -1
  57. package/dist/leader-thread/connection.js +22 -7
  58. package/dist/leader-thread/connection.js.map +1 -1
  59. package/dist/leader-thread/leader-worker-devtools.d.ts +1 -1
  60. package/dist/leader-thread/leader-worker-devtools.d.ts.map +1 -1
  61. package/dist/leader-thread/leader-worker-devtools.js +147 -124
  62. package/dist/leader-thread/leader-worker-devtools.js.map +1 -1
  63. package/dist/leader-thread/make-leader-thread-layer.d.ts +12 -11
  64. package/dist/leader-thread/make-leader-thread-layer.d.ts.map +1 -1
  65. package/dist/leader-thread/make-leader-thread-layer.js +55 -18
  66. package/dist/leader-thread/make-leader-thread-layer.js.map +1 -1
  67. package/dist/leader-thread/mutationlog.d.ts +6 -19
  68. package/dist/leader-thread/mutationlog.d.ts.map +1 -1
  69. package/dist/leader-thread/mutationlog.js +12 -9
  70. package/dist/leader-thread/mutationlog.js.map +1 -1
  71. package/dist/leader-thread/pull-queue-set.d.ts +3 -3
  72. package/dist/leader-thread/pull-queue-set.d.ts.map +1 -1
  73. package/dist/leader-thread/pull-queue-set.js +9 -0
  74. package/dist/leader-thread/pull-queue-set.js.map +1 -1
  75. package/dist/leader-thread/recreate-db.d.ts +4 -2
  76. package/dist/leader-thread/recreate-db.d.ts.map +1 -1
  77. package/dist/leader-thread/recreate-db.js +32 -21
  78. package/dist/leader-thread/recreate-db.js.map +1 -1
  79. package/dist/leader-thread/shutdown-channel.d.ts +2 -5
  80. package/dist/leader-thread/shutdown-channel.d.ts.map +1 -1
  81. package/dist/leader-thread/shutdown-channel.js +2 -4
  82. package/dist/leader-thread/shutdown-channel.js.map +1 -1
  83. package/dist/leader-thread/types.d.ts +58 -26
  84. package/dist/leader-thread/types.d.ts.map +1 -1
  85. package/dist/leader-thread/types.js +1 -3
  86. package/dist/leader-thread/types.js.map +1 -1
  87. package/dist/mutation.d.ts +9 -2
  88. package/dist/mutation.d.ts.map +1 -1
  89. package/dist/mutation.js +5 -5
  90. package/dist/mutation.js.map +1 -1
  91. package/dist/otel.d.ts +2 -0
  92. package/dist/otel.d.ts.map +1 -1
  93. package/dist/otel.js +5 -0
  94. package/dist/otel.js.map +1 -1
  95. package/dist/query-builder/api.d.ts +3 -3
  96. package/dist/query-builder/api.d.ts.map +1 -1
  97. package/dist/query-builder/impl.d.ts +4 -4
  98. package/dist/query-builder/impl.d.ts.map +1 -1
  99. package/dist/query-builder/impl.js.map +1 -1
  100. package/dist/query-builder/impl.test.js +16 -1
  101. package/dist/query-builder/impl.test.js.map +1 -1
  102. package/dist/query-info.d.ts +3 -3
  103. package/dist/query-info.d.ts.map +1 -1
  104. package/dist/rehydrate-from-mutationlog.d.ts +5 -5
  105. package/dist/rehydrate-from-mutationlog.d.ts.map +1 -1
  106. package/dist/rehydrate-from-mutationlog.js +23 -27
  107. package/dist/rehydrate-from-mutationlog.js.map +1 -1
  108. package/dist/schema/EventId.d.ts +27 -16
  109. package/dist/schema/EventId.d.ts.map +1 -1
  110. package/dist/schema/EventId.js +36 -11
  111. package/dist/schema/EventId.js.map +1 -1
  112. package/dist/schema/EventId.test.d.ts +2 -0
  113. package/dist/schema/EventId.test.d.ts.map +1 -0
  114. package/dist/schema/EventId.test.js +11 -0
  115. package/dist/schema/EventId.test.js.map +1 -0
  116. package/dist/schema/MutationEvent.d.ts +76 -82
  117. package/dist/schema/MutationEvent.d.ts.map +1 -1
  118. package/dist/schema/MutationEvent.js +53 -20
  119. package/dist/schema/MutationEvent.js.map +1 -1
  120. package/dist/schema/db-schema/ast/sqlite.d.ts +69 -0
  121. package/dist/schema/db-schema/ast/sqlite.d.ts.map +1 -0
  122. package/dist/schema/db-schema/ast/sqlite.js +71 -0
  123. package/dist/schema/db-schema/ast/sqlite.js.map +1 -0
  124. package/dist/schema/db-schema/ast/validate.d.ts +3 -0
  125. package/dist/schema/db-schema/ast/validate.d.ts.map +1 -0
  126. package/dist/schema/db-schema/ast/validate.js +12 -0
  127. package/dist/schema/db-schema/ast/validate.js.map +1 -0
  128. package/dist/schema/db-schema/dsl/field-defs.d.ts +90 -0
  129. package/dist/schema/db-schema/dsl/field-defs.d.ts.map +1 -0
  130. package/dist/schema/db-schema/dsl/field-defs.js +87 -0
  131. package/dist/schema/db-schema/dsl/field-defs.js.map +1 -0
  132. package/dist/schema/db-schema/dsl/field-defs.test.d.ts +2 -0
  133. package/dist/schema/db-schema/dsl/field-defs.test.d.ts.map +1 -0
  134. package/dist/schema/db-schema/dsl/field-defs.test.js +29 -0
  135. package/dist/schema/db-schema/dsl/field-defs.test.js.map +1 -0
  136. package/dist/schema/db-schema/dsl/mod.d.ts +88 -0
  137. package/dist/schema/db-schema/dsl/mod.d.ts.map +1 -0
  138. package/dist/schema/db-schema/dsl/mod.js +35 -0
  139. package/dist/schema/db-schema/dsl/mod.js.map +1 -0
  140. package/dist/schema/db-schema/hash.d.ts +2 -0
  141. package/dist/schema/db-schema/hash.d.ts.map +1 -0
  142. package/dist/schema/db-schema/hash.js +14 -0
  143. package/dist/schema/db-schema/hash.js.map +1 -0
  144. package/dist/schema/db-schema/mod.d.ts +3 -0
  145. package/dist/schema/db-schema/mod.d.ts.map +1 -0
  146. package/dist/schema/db-schema/mod.js +3 -0
  147. package/dist/schema/db-schema/mod.js.map +1 -0
  148. package/dist/schema/mod.d.ts +1 -0
  149. package/dist/schema/mod.d.ts.map +1 -1
  150. package/dist/schema/mod.js +1 -0
  151. package/dist/schema/mod.js.map +1 -1
  152. package/dist/schema/mutations.d.ts +8 -9
  153. package/dist/schema/mutations.d.ts.map +1 -1
  154. package/dist/schema/mutations.js +2 -2
  155. package/dist/schema/mutations.js.map +1 -1
  156. package/dist/schema/schema-helpers.d.ts.map +1 -1
  157. package/dist/schema/schema-helpers.js +1 -1
  158. package/dist/schema/schema-helpers.js.map +1 -1
  159. package/dist/schema/schema.d.ts +5 -2
  160. package/dist/schema/schema.d.ts.map +1 -1
  161. package/dist/schema/schema.js +20 -9
  162. package/dist/schema/schema.js.map +1 -1
  163. package/dist/schema/system-tables.d.ts +65 -47
  164. package/dist/schema/system-tables.d.ts.map +1 -1
  165. package/dist/schema/system-tables.js +24 -13
  166. package/dist/schema/system-tables.js.map +1 -1
  167. package/dist/schema/table-def.d.ts +18 -24
  168. package/dist/schema/table-def.d.ts.map +1 -1
  169. package/dist/schema/table-def.js +3 -4
  170. package/dist/schema/table-def.js.map +1 -1
  171. package/dist/schema-management/common.d.ts +3 -3
  172. package/dist/schema-management/common.d.ts.map +1 -1
  173. package/dist/schema-management/common.js.map +1 -1
  174. package/dist/schema-management/migrations.d.ts +6 -6
  175. package/dist/schema-management/migrations.d.ts.map +1 -1
  176. package/dist/schema-management/migrations.js +13 -8
  177. package/dist/schema-management/migrations.js.map +1 -1
  178. package/dist/schema-management/validate-mutation-defs.d.ts.map +1 -1
  179. package/dist/schema-management/validate-mutation-defs.js +2 -2
  180. package/dist/schema-management/validate-mutation-defs.js.map +1 -1
  181. package/dist/sql-queries/misc.d.ts.map +1 -1
  182. package/dist/sql-queries/sql-queries.d.ts +1 -1
  183. package/dist/sql-queries/sql-queries.d.ts.map +1 -1
  184. package/dist/sql-queries/sql-queries.js.map +1 -1
  185. package/dist/sql-queries/sql-query-builder.d.ts +1 -1
  186. package/dist/sql-queries/sql-query-builder.d.ts.map +1 -1
  187. package/dist/sql-queries/sql-query-builder.js.map +1 -1
  188. package/dist/sql-queries/types.d.ts +2 -1
  189. package/dist/sql-queries/types.d.ts.map +1 -1
  190. package/dist/sql-queries/types.js.map +1 -1
  191. package/dist/sync/{client-session-sync-processor.d.ts → ClientSessionSyncProcessor.d.ts} +25 -14
  192. package/dist/sync/ClientSessionSyncProcessor.d.ts.map +1 -0
  193. package/dist/sync/ClientSessionSyncProcessor.js +199 -0
  194. package/dist/sync/ClientSessionSyncProcessor.js.map +1 -0
  195. package/dist/sync/index.d.ts +1 -1
  196. package/dist/sync/index.d.ts.map +1 -1
  197. package/dist/sync/index.js +1 -1
  198. package/dist/sync/index.js.map +1 -1
  199. package/dist/sync/next/compact-events.d.ts.map +1 -1
  200. package/dist/sync/next/facts.d.ts.map +1 -1
  201. package/dist/sync/next/facts.js +1 -1
  202. package/dist/sync/next/facts.js.map +1 -1
  203. package/dist/sync/next/history-dag-common.d.ts +3 -4
  204. package/dist/sync/next/history-dag-common.d.ts.map +1 -1
  205. package/dist/sync/next/history-dag-common.js +3 -1
  206. package/dist/sync/next/history-dag-common.js.map +1 -1
  207. package/dist/sync/next/history-dag.d.ts.map +1 -1
  208. package/dist/sync/next/history-dag.js +1 -1
  209. package/dist/sync/next/history-dag.js.map +1 -1
  210. package/dist/sync/next/rebase-events.d.ts +6 -4
  211. package/dist/sync/next/rebase-events.d.ts.map +1 -1
  212. package/dist/sync/next/rebase-events.js +6 -3
  213. package/dist/sync/next/rebase-events.js.map +1 -1
  214. package/dist/sync/next/test/compact-events.calculator.test.js +12 -12
  215. package/dist/sync/next/test/compact-events.calculator.test.js.map +1 -1
  216. package/dist/sync/next/test/compact-events.test.js +43 -43
  217. package/dist/sync/next/test/compact-events.test.js.map +1 -1
  218. package/dist/sync/next/test/mutation-fixtures.d.ts +4 -4
  219. package/dist/sync/next/test/mutation-fixtures.d.ts.map +1 -1
  220. package/dist/sync/next/test/mutation-fixtures.js +12 -16
  221. package/dist/sync/next/test/mutation-fixtures.js.map +1 -1
  222. package/dist/sync/sync.d.ts +31 -16
  223. package/dist/sync/sync.d.ts.map +1 -1
  224. package/dist/sync/sync.js +7 -3
  225. package/dist/sync/sync.js.map +1 -1
  226. package/dist/sync/syncstate.d.ts +177 -44
  227. package/dist/sync/syncstate.d.ts.map +1 -1
  228. package/dist/sync/syncstate.js +188 -56
  229. package/dist/sync/syncstate.js.map +1 -1
  230. package/dist/sync/syncstate.test.js +162 -92
  231. package/dist/sync/syncstate.test.js.map +1 -1
  232. package/dist/sync/validate-push-payload.d.ts +2 -2
  233. package/dist/sync/validate-push-payload.d.ts.map +1 -1
  234. package/dist/sync/validate-push-payload.js +2 -2
  235. package/dist/sync/validate-push-payload.js.map +1 -1
  236. package/dist/util.d.ts +2 -2
  237. package/dist/util.d.ts.map +1 -1
  238. package/dist/version.d.ts +1 -1
  239. package/dist/version.d.ts.map +1 -1
  240. package/dist/version.js +1 -1
  241. package/dist/version.js.map +1 -1
  242. package/package.json +6 -6
  243. package/src/adapter-types.ts +80 -56
  244. package/src/derived-mutations.test.ts +1 -1
  245. package/src/derived-mutations.ts +13 -9
  246. package/src/devtools/devtools-messages-client-session.ts +141 -0
  247. package/src/devtools/devtools-messages-common.ts +106 -0
  248. package/src/devtools/devtools-messages-leader.ts +192 -0
  249. package/src/devtools/devtools-messages.ts +3 -243
  250. package/src/devtools/devtools-sessioninfo.ts +99 -0
  251. package/src/devtools/mod.ts +36 -0
  252. package/src/index.ts +2 -8
  253. package/src/init-singleton-tables.ts +2 -2
  254. package/src/leader-thread/LeaderSyncProcessor.ts +833 -0
  255. package/src/leader-thread/apply-mutation.ts +87 -43
  256. package/src/leader-thread/connection.ts +54 -9
  257. package/src/leader-thread/leader-worker-devtools.ts +199 -174
  258. package/src/leader-thread/make-leader-thread-layer.ts +89 -35
  259. package/src/leader-thread/mutationlog.ts +20 -14
  260. package/src/leader-thread/pull-queue-set.ts +10 -1
  261. package/src/leader-thread/recreate-db.ts +38 -25
  262. package/src/leader-thread/shutdown-channel.ts +2 -4
  263. package/src/leader-thread/types.ts +68 -34
  264. package/src/mutation.ts +17 -7
  265. package/src/otel.ts +8 -0
  266. package/src/query-builder/api.ts +4 -4
  267. package/src/query-builder/impl.test.ts +22 -1
  268. package/src/query-builder/impl.ts +2 -2
  269. package/src/query-info.ts +3 -3
  270. package/src/rehydrate-from-mutationlog.ts +28 -34
  271. package/src/schema/EventId.test.ts +12 -0
  272. package/src/schema/EventId.ts +49 -15
  273. package/src/schema/MutationEvent.ts +78 -31
  274. package/src/schema/db-schema/ast/sqlite.ts +142 -0
  275. package/src/schema/db-schema/ast/validate.ts +13 -0
  276. package/src/schema/db-schema/dsl/__snapshots__/field-defs.test.ts.snap +206 -0
  277. package/src/schema/db-schema/dsl/field-defs.test.ts +35 -0
  278. package/src/schema/db-schema/dsl/field-defs.ts +242 -0
  279. package/src/schema/db-schema/dsl/mod.ts +195 -0
  280. package/src/schema/db-schema/hash.ts +14 -0
  281. package/src/schema/db-schema/mod.ts +2 -0
  282. package/src/schema/mod.ts +1 -0
  283. package/src/schema/mutations.ts +10 -20
  284. package/src/schema/schema-helpers.ts +1 -1
  285. package/src/schema/schema.ts +22 -10
  286. package/src/schema/system-tables.ts +24 -13
  287. package/src/schema/table-def.ts +17 -17
  288. package/src/schema-management/common.ts +3 -3
  289. package/src/schema-management/migrations.ts +19 -15
  290. package/src/schema-management/validate-mutation-defs.ts +2 -2
  291. package/src/sql-queries/sql-queries.ts +1 -1
  292. package/src/sql-queries/sql-query-builder.ts +1 -2
  293. package/src/sql-queries/types.ts +3 -1
  294. package/src/sync/ClientSessionSyncProcessor.ts +313 -0
  295. package/src/sync/index.ts +1 -1
  296. package/src/sync/next/facts.ts +1 -1
  297. package/src/sync/next/history-dag-common.ts +5 -1
  298. package/src/sync/next/history-dag.ts +1 -1
  299. package/src/sync/next/rebase-events.ts +13 -7
  300. package/src/sync/next/test/compact-events.calculator.test.ts +12 -12
  301. package/src/sync/next/test/compact-events.test.ts +43 -43
  302. package/src/sync/next/test/mutation-fixtures.ts +16 -19
  303. package/src/sync/sync.ts +26 -10
  304. package/src/sync/syncstate.test.ts +178 -98
  305. package/src/sync/syncstate.ts +170 -83
  306. package/src/sync/validate-push-payload.ts +7 -4
  307. package/src/version.ts +1 -1
  308. package/tmp/pack.tgz +0 -0
  309. package/tsconfig.json +1 -1
  310. package/dist/devtools/devtools-bridge.d.ts +0 -12
  311. package/dist/devtools/devtools-bridge.d.ts.map +0 -1
  312. package/dist/devtools/devtools-bridge.js +0 -2
  313. package/dist/devtools/devtools-bridge.js.map +0 -1
  314. package/dist/devtools/index.d.ts +0 -42
  315. package/dist/devtools/index.d.ts.map +0 -1
  316. package/dist/devtools/index.js +0 -48
  317. package/dist/devtools/index.js.map +0 -1
  318. package/dist/leader-thread/leader-sync-processor.d.ts +0 -47
  319. package/dist/leader-thread/leader-sync-processor.d.ts.map +0 -1
  320. package/dist/leader-thread/leader-sync-processor.js +0 -422
  321. package/dist/leader-thread/leader-sync-processor.js.map +0 -1
  322. package/dist/sync/client-session-sync-processor.d.ts.map +0 -1
  323. package/dist/sync/client-session-sync-processor.js +0 -131
  324. package/dist/sync/client-session-sync-processor.js.map +0 -1
  325. package/src/devtools/devtools-bridge.ts +0 -13
  326. package/src/devtools/index.ts +0 -48
  327. package/src/leader-thread/leader-sync-processor.ts +0 -666
  328. package/src/sync/client-session-sync-processor.ts +0 -207
@@ -1,68 +1,104 @@
1
- import type { HttpClient, Scope, WebChannel } from '@livestore/utils/effect'
2
- import { Deferred, Effect, FiberSet, Layer, Queue, SubscriptionRef } from '@livestore/utils/effect'
1
+ import type { HttpClient, Scope } from '@livestore/utils/effect'
2
+ import { Deferred, Effect, Layer, Queue, SubscriptionRef } from '@livestore/utils/effect'
3
3
 
4
- import type { BootStatus, MakeSynchronousDatabase, SqliteError, SynchronousDatabase } from '../adapter-types.js'
4
+ import type { BootStatus, MakeSqliteDb, MigrationsReport, SqliteError } from '../adapter-types.js'
5
5
  import { UnexpectedError } from '../adapter-types.js'
6
+ import type * as Devtools from '../devtools/mod.js'
6
7
  import type { LiveStoreSchema } from '../schema/mod.js'
7
8
  import { EventId, MutationEvent, mutationLogMetaTable, SYNC_STATUS_TABLE, syncStatusTable } from '../schema/mod.js'
8
9
  import { migrateTable } from '../schema-management/migrations.js'
9
- import type { InvalidPullError, IsOfflineError, SyncBackend } from '../sync/sync.js'
10
+ import type { InvalidPullError, IsOfflineError, SyncOptions } from '../sync/sync.js'
10
11
  import { sql } from '../util.js'
11
12
  import { execSql } from './connection.js'
12
- import { makeLeaderSyncProcessor } from './leader-sync-processor.js'
13
13
  import { bootDevtools } from './leader-worker-devtools.js'
14
+ import { makeLeaderSyncProcessor } from './LeaderSyncProcessor.js'
14
15
  import { makePullQueueSet } from './pull-queue-set.js'
15
16
  import { recreateDb } from './recreate-db.js'
16
- import type { DevtoolsOptions, InitialBlockingSyncContext, InitialSyncOptions, ShutdownState } from './types.js'
17
+ import type { ShutdownChannel } from './shutdown-channel.js'
18
+ import type {
19
+ DevtoolsOptions,
20
+ InitialBlockingSyncContext,
21
+ InitialSyncOptions,
22
+ LeaderSqliteDb,
23
+ ShutdownState,
24
+ } from './types.js'
17
25
  import { LeaderThreadCtx } from './types.js'
18
26
 
19
27
  export const makeLeaderThreadLayer = ({
20
28
  schema,
21
29
  storeId,
22
- originId,
23
- makeSyncDb,
24
- makeSyncBackend,
25
- db,
26
- dbLog,
30
+ clientId,
31
+ makeSqliteDb,
32
+ syncOptions,
33
+ dbReadModel,
34
+ dbMutationLog,
27
35
  devtoolsOptions,
28
- initialSyncOptions = { _tag: 'Skip' },
36
+ shutdownChannel,
29
37
  }: {
30
38
  storeId: string
31
- originId: string
39
+ clientId: string
32
40
  schema: LiveStoreSchema
33
- makeSyncDb: MakeSynchronousDatabase
34
- makeSyncBackend: Effect.Effect<SyncBackend, UnexpectedError, Scope.Scope> | undefined
35
- db: SynchronousDatabase
36
- dbLog: SynchronousDatabase
41
+ makeSqliteDb: MakeSqliteDb
42
+ syncOptions: SyncOptions | undefined
43
+ dbReadModel: LeaderSqliteDb
44
+ dbMutationLog: LeaderSqliteDb
37
45
  devtoolsOptions: DevtoolsOptions
38
- initialSyncOptions: InitialSyncOptions | undefined
46
+ shutdownChannel: ShutdownChannel
39
47
  }): Layer.Layer<LeaderThreadCtx, UnexpectedError, Scope.Scope | HttpClient.HttpClient> =>
40
48
  Effect.gen(function* () {
41
49
  const bootStatusQueue = yield* Queue.unbounded<BootStatus>().pipe(Effect.acquireRelease(Queue.shutdown))
42
50
 
43
51
  // TODO do more validation here than just checking the count of tables
44
52
  // Either happens on initial boot or if schema changes
45
- const dbMissing = db.select<{ count: number }>(sql`select count(*) as count from sqlite_master`)[0]!.count === 0
53
+ const dbMissing =
54
+ dbReadModel.select<{ count: number }>(sql`select count(*) as count from sqlite_master`)[0]!.count === 0
46
55
 
47
- const syncBackend = makeSyncBackend === undefined ? undefined : yield* makeSyncBackend
56
+ const syncBackend =
57
+ syncOptions?.makeBackend === undefined ? undefined : yield* syncOptions.makeBackend({ storeId, clientId })
48
58
 
49
- const initialBlockingSyncContext = yield* makeInitialBlockingSyncContext({ initialSyncOptions, bootStatusQueue })
59
+ const initialBlockingSyncContext = yield* makeInitialBlockingSyncContext({
60
+ initialSyncOptions: syncOptions?.initialSyncOptions ?? { _tag: 'Skip' },
61
+ bootStatusQueue,
62
+ })
50
63
 
51
- const syncProcessor = yield* makeLeaderSyncProcessor({ schema, dbMissing, dbLog, initialBlockingSyncContext })
64
+ const syncProcessor = yield* makeLeaderSyncProcessor({
65
+ schema,
66
+ dbMissing,
67
+ dbMutationLog,
68
+ initialBlockingSyncContext,
69
+ clientId,
70
+ })
71
+
72
+ const extraIncomingMessagesQueue = yield* Queue.unbounded<Devtools.Leader.MessageToApp>().pipe(
73
+ Effect.acquireRelease(Queue.shutdown),
74
+ )
75
+
76
+ const devtoolsContext = devtoolsOptions.enabled
77
+ ? {
78
+ enabled: true as const,
79
+ syncBackendLatch: yield* Effect.makeLatch(true),
80
+ syncBackendLatchState: yield* SubscriptionRef.make<{ latchClosed: boolean }>({ latchClosed: false }),
81
+ }
82
+ : { enabled: false as const }
52
83
 
53
84
  const ctx = {
54
85
  schema,
55
86
  bootStatusQueue,
56
87
  storeId,
57
- originId,
58
- db,
59
- dbLog,
60
- makeSyncDb,
88
+ clientId,
89
+ dbReadModel,
90
+ dbMutationLog,
91
+ makeSqliteDb,
61
92
  mutationEventSchema: MutationEvent.makeMutationEventSchema(schema),
62
93
  shutdownStateSubRef: yield* SubscriptionRef.make<ShutdownState>('running'),
94
+ shutdownChannel,
63
95
  syncBackend,
64
96
  syncProcessor,
65
97
  connectedClientSessionPullQueues: yield* makePullQueueSet,
98
+ extraIncomingMessagesQueue,
99
+ devtools: devtoolsContext,
100
+ // State will be set during `bootLeaderThread`
101
+ initialState: {} as any as LeaderThreadCtx['Type']['initialState'],
66
102
  } satisfies typeof LeaderThreadCtx.Service
67
103
 
68
104
  // @ts-expect-error For debugging purposes
@@ -70,7 +106,11 @@ export const makeLeaderThreadLayer = ({
70
106
 
71
107
  const layer = Layer.succeed(LeaderThreadCtx, ctx)
72
108
 
73
- yield* bootLeaderThread({ dbMissing, initialBlockingSyncContext, devtoolsOptions }).pipe(Effect.provide(layer))
109
+ ctx.initialState = yield* bootLeaderThread({
110
+ dbMissing,
111
+ initialBlockingSyncContext,
112
+ devtoolsOptions,
113
+ }).pipe(Effect.provide(layer))
74
114
 
75
115
  return layer
76
116
  }).pipe(
@@ -140,22 +180,22 @@ const bootLeaderThread = ({
140
180
  initialBlockingSyncContext: InitialBlockingSyncContext
141
181
  devtoolsOptions: DevtoolsOptions
142
182
  }): Effect.Effect<
143
- void,
183
+ LeaderThreadCtx['Type']['initialState'],
144
184
  UnexpectedError | SqliteError | IsOfflineError | InvalidPullError,
145
185
  LeaderThreadCtx | Scope.Scope | HttpClient.HttpClient
146
186
  > =>
147
187
  Effect.gen(function* () {
148
- const { dbLog, bootStatusQueue, syncProcessor } = yield* LeaderThreadCtx
188
+ const { dbMutationLog, bootStatusQueue, syncProcessor } = yield* LeaderThreadCtx
149
189
 
150
190
  yield* migrateTable({
151
- db: dbLog,
191
+ db: dbMutationLog,
152
192
  behaviour: 'create-if-not-exists',
153
193
  tableAst: mutationLogMetaTable.sqliteDef.ast,
154
194
  skipMetaTable: true,
155
195
  })
156
196
 
157
197
  yield* migrateTable({
158
- db: dbLog,
198
+ db: dbMutationLog,
159
199
  behaviour: 'create-if-not-exists',
160
200
  tableAst: syncStatusTable.sqliteDef.ast,
161
201
  skipMetaTable: true,
@@ -163,7 +203,7 @@ const bootLeaderThread = ({
163
203
 
164
204
  // Create sync status row if it doesn't exist
165
205
  yield* execSql(
166
- dbLog,
206
+ dbMutationLog,
167
207
  sql`INSERT INTO ${SYNC_STATUS_TABLE} (head)
168
208
  SELECT ${EventId.ROOT.global}
169
209
  WHERE NOT EXISTS (SELECT 1 FROM ${SYNC_STATUS_TABLE})`,
@@ -174,19 +214,33 @@ const bootLeaderThread = ({
174
214
 
175
215
  // We're already starting pulling from the sync backend concurrently but wait until the db is ready before
176
216
  // processing any incoming mutations
177
- yield* syncProcessor.boot({ dbReady })
217
+ const { initialLeaderHead } = yield* syncProcessor.boot({ dbReady })
178
218
 
219
+ let migrationsReport: MigrationsReport
179
220
  if (dbMissing) {
180
- yield* recreateDb
221
+ const recreateResult = yield* recreateDb
222
+ migrationsReport = recreateResult.migrationsReport
223
+ } else {
224
+ migrationsReport = { migrations: [] }
181
225
  }
182
226
 
183
227
  yield* Deferred.succeed(dbReady, void 0)
184
228
 
185
229
  if (initialBlockingSyncContext.blockingDeferred !== undefined) {
186
- yield* initialBlockingSyncContext.blockingDeferred
230
+ // Provides a syncing status right away before the first pull response comes in
231
+ yield* Queue.offer(bootStatusQueue, {
232
+ stage: 'syncing',
233
+ progress: { done: 0, total: -1 },
234
+ })
235
+
236
+ yield* initialBlockingSyncContext.blockingDeferred.pipe(
237
+ Effect.withSpan('@livestore/common:leader-thread:initial-sync-blocking'),
238
+ )
187
239
  }
188
240
 
189
241
  yield* Queue.offer(bootStatusQueue, { stage: 'done' })
190
242
 
191
243
  yield* bootDevtools(devtoolsOptions).pipe(Effect.tapCauseLogPretty, Effect.forkScoped)
244
+
245
+ return { migrationsReport, leaderHead: initialLeaderHead }
192
246
  })
@@ -1,17 +1,20 @@
1
1
  import { Effect, Schema } from '@livestore/utils/effect'
2
2
 
3
- import type { SynchronousDatabase } from '../adapter-types.js'
3
+ import type { SqliteDb } from '../adapter-types.js'
4
4
  import * as EventId from '../schema/EventId.js'
5
+ import type * as MutationEvent from '../schema/MutationEvent.js'
5
6
  import { MUTATION_LOG_META_TABLE, mutationLogMetaTable, SYNC_STATUS_TABLE } from '../schema/system-tables.js'
6
7
  import { prepareBindValues, sql } from '../util.js'
7
8
  import { LeaderThreadCtx } from './types.js'
8
9
 
9
- export const getMutationEventsSince = (since: EventId.EventId) =>
10
+ export const getMutationEventsSince = (
11
+ since: EventId.EventId,
12
+ ): Effect.Effect<ReadonlyArray<MutationEvent.AnyEncoded>, never, LeaderThreadCtx> =>
10
13
  Effect.gen(function* () {
11
- const { dbLog } = yield* LeaderThreadCtx
14
+ const { dbMutationLog } = yield* LeaderThreadCtx
12
15
 
13
16
  const query = mutationLogMetaTable.query.where('idGlobal', '>=', since.global).asSql()
14
- const pendingMutationEventsRaw = dbLog.select(query.query, prepareBindValues(query.bindValues, query.query))
17
+ const pendingMutationEventsRaw = dbMutationLog.select(query.query, prepareBindValues(query.bindValues, query.query))
15
18
  const pendingMutationEvents = Schema.decodeUnknownSync(mutationLogMetaTable.schema.pipe(Schema.Array))(
16
19
  pendingMutationEventsRaw,
17
20
  )
@@ -20,23 +23,26 @@ export const getMutationEventsSince = (since: EventId.EventId) =>
20
23
  .map((_) => ({
21
24
  mutation: _.mutation,
22
25
  args: _.argsJson,
23
- id: { global: _.idGlobal, local: _.idLocal },
24
- parentId: { global: _.parentIdGlobal, local: _.parentIdLocal },
26
+ id: { global: _.idGlobal, client: _.idClient },
27
+ parentId: { global: _.parentIdGlobal, client: _.parentIdClient },
28
+ clientId: _.clientId,
29
+ sessionId: _.sessionId ?? undefined,
25
30
  }))
26
31
  .filter((_) => EventId.compare(_.id, since) > 0)
27
32
  })
28
33
 
29
- export const getLocalHeadFromDb = (dbLog: SynchronousDatabase) => {
30
- const res = dbLog.select<{ idGlobal: number; idLocal: number }>(
31
- sql`select idGlobal, idLocal from ${MUTATION_LOG_META_TABLE} order by idGlobal DESC, idLocal DESC limit 1`,
34
+ export const getClientHeadFromDb = (dbMutationLog: SqliteDb): EventId.EventId => {
35
+ const res = dbMutationLog.select<{ idGlobal: EventId.GlobalEventId; idClient: EventId.ClientEventId }>(
36
+ sql`select idGlobal, idClient from ${MUTATION_LOG_META_TABLE} order by idGlobal DESC, idClient DESC limit 1`,
32
37
  )[0]
33
38
 
34
- return res ? { global: res.idGlobal, local: res.idLocal } : EventId.ROOT
39
+ return res ? { global: res.idGlobal, client: res.idClient } : EventId.ROOT
35
40
  }
36
41
 
37
- export const getBackendHeadFromDb = (dbLog: SynchronousDatabase) =>
38
- dbLog.select<{ head: number }>(sql`select head from ${SYNC_STATUS_TABLE}`)[0]?.head ?? EventId.ROOT.global
42
+ export const getBackendHeadFromDb = (dbMutationLog: SqliteDb): EventId.GlobalEventId =>
43
+ dbMutationLog.select<{ head: EventId.GlobalEventId }>(sql`select head from ${SYNC_STATUS_TABLE}`)[0]?.head ??
44
+ EventId.ROOT.global
39
45
 
40
46
  // TODO use prepared statements
41
- export const updateBackendHead = (dbLog: SynchronousDatabase, head: EventId.EventId) =>
42
- dbLog.execute(sql`UPDATE ${SYNC_STATUS_TABLE} SET head = ${head.global}`)
47
+ export const updateBackendHead = (dbMutationLog: SqliteDb, head: EventId.EventId) =>
48
+ dbMutationLog.execute(sql`UPDATE ${SYNC_STATUS_TABLE} SET head = ${head.global}`)
@@ -2,7 +2,7 @@ import { Effect, Queue } from '@livestore/utils/effect'
2
2
 
3
3
  import * as MutationEvent from '../schema/MutationEvent.js'
4
4
  import { getMutationEventsSince } from './mutationlog.js'
5
- import { type PullQueueItem, type PullQueueSet } from './types.js'
5
+ import { LeaderThreadCtx, type PullQueueItem, type PullQueueSet } from './types.js'
6
6
 
7
7
  export const makePullQueueSet = Effect.gen(function* () {
8
8
  const set = new Set<Queue.Queue<PullQueueItem>>()
@@ -46,6 +46,15 @@ export const makePullQueueSet = Effect.gen(function* () {
46
46
  return
47
47
  }
48
48
 
49
+ const { clientId } = yield* LeaderThreadCtx
50
+ if (clientId === 'client-b') {
51
+ // console.log(
52
+ // 'offer',
53
+ // item.payload._tag,
54
+ // item.payload.newEvents.map((_) => _.toJSON()),
55
+ // )
56
+ }
57
+
49
58
  for (const queue of set) {
50
59
  yield* Queue.offer(queue, item)
51
60
  }
@@ -2,85 +2,94 @@ import { casesHandled } from '@livestore/utils'
2
2
  import type { HttpClient } from '@livestore/utils/effect'
3
3
  import { Effect, Queue } from '@livestore/utils/effect'
4
4
 
5
- import type { InvalidPullError, IsOfflineError, MigrationHooks, SqliteError } from '../index.js'
5
+ import type { InvalidPullError, IsOfflineError, MigrationHooks, MigrationsReport, SqliteError } from '../index.js'
6
6
  import { initializeSingletonTables, migrateDb, rehydrateFromMutationLog, UnexpectedError } from '../index.js'
7
7
  import { configureConnection } from './connection.js'
8
8
  import { LeaderThreadCtx } from './types.js'
9
9
 
10
10
  export const recreateDb: Effect.Effect<
11
- void,
11
+ { migrationsReport: MigrationsReport },
12
12
  UnexpectedError | SqliteError | IsOfflineError | InvalidPullError,
13
13
  LeaderThreadCtx | HttpClient.HttpClient
14
14
  > = Effect.gen(function* () {
15
- const { db, dbLog, makeSyncDb, schema, bootStatusQueue } = yield* LeaderThreadCtx
15
+ const { dbReadModel, dbMutationLog, schema, bootStatusQueue } = yield* LeaderThreadCtx
16
16
 
17
17
  const migrationOptions = schema.migrationOptions
18
+ let migrationsReport: MigrationsReport
18
19
 
19
20
  yield* Effect.addFinalizer(
20
21
  Effect.fn('recreateDb:finalizer')(function* (ex) {
21
- if (ex._tag === 'Failure') db.destroy()
22
+ if (ex._tag === 'Failure') dbReadModel.destroy()
22
23
  }),
23
24
  )
24
25
 
25
26
  // NOTE to speed up the operations below, we're creating a temporary in-memory database
26
27
  // and later we'll overwrite the persisted database with the new data
27
- const tmpSyncDb = yield* makeSyncDb({ _tag: 'in-memory' })
28
- yield* configureConnection(tmpSyncDb, { fkEnabled: true })
28
+ // TODO bring back this optimization
29
+ // const tmpDb = yield* makeSqliteDb({ _tag: 'in-memory' })
30
+ const tmpDb = dbReadModel
31
+ yield* configureConnection(tmpDb, { foreignKeys: true })
29
32
 
30
33
  const initDb = (hooks: Partial<MigrationHooks> | undefined) =>
31
34
  Effect.gen(function* () {
32
- yield* Effect.tryAll(() => hooks?.init?.(tmpSyncDb)).pipe(UnexpectedError.mapToUnexpectedError)
35
+ yield* Effect.tryAll(() => hooks?.init?.(tmpDb)).pipe(UnexpectedError.mapToUnexpectedError)
33
36
 
34
- yield* migrateDb({
35
- db: tmpSyncDb,
37
+ const migrationsReport = yield* migrateDb({
38
+ db: tmpDb,
36
39
  schema,
37
40
  onProgress: ({ done, total }) =>
38
41
  Queue.offer(bootStatusQueue, { stage: 'migrating', progress: { done, total } }),
39
42
  })
40
43
 
41
- initializeSingletonTables(schema, tmpSyncDb)
44
+ initializeSingletonTables(schema, tmpDb)
42
45
 
43
- yield* Effect.tryAll(() => hooks?.pre?.(tmpSyncDb)).pipe(UnexpectedError.mapToUnexpectedError)
46
+ yield* Effect.tryAll(() => hooks?.pre?.(tmpDb)).pipe(UnexpectedError.mapToUnexpectedError)
44
47
 
45
- return tmpSyncDb
48
+ return { migrationsReport, tmpDb }
46
49
  })
47
50
 
48
51
  switch (migrationOptions.strategy) {
49
52
  case 'from-mutation-log': {
50
53
  const hooks = migrationOptions.hooks
51
- const tmpSyncDb = yield* initDb(hooks)
54
+ const initResult = yield* initDb(hooks)
55
+
56
+ migrationsReport = initResult.migrationsReport
52
57
 
53
58
  yield* rehydrateFromMutationLog({
54
- db: tmpSyncDb,
55
- logDb: dbLog,
59
+ db: initResult.tmpDb,
60
+ logDb: dbMutationLog,
56
61
  schema,
57
62
  migrationOptions,
58
63
  onProgress: ({ done, total }) =>
59
64
  Queue.offer(bootStatusQueue, { stage: 'rehydrating', progress: { done, total } }),
60
65
  })
61
66
 
62
- yield* Effect.tryAll(() => hooks?.post?.(tmpSyncDb)).pipe(UnexpectedError.mapToUnexpectedError)
67
+ yield* Effect.tryAll(() => hooks?.post?.(initResult.tmpDb)).pipe(UnexpectedError.mapToUnexpectedError)
63
68
 
64
69
  break
65
70
  }
66
71
  case 'hard-reset': {
67
72
  const hooks = migrationOptions.hooks
68
- const tmpInMemoryDb = yield* initDb(hooks)
73
+ const initResult = yield* initDb(hooks)
74
+
75
+ migrationsReport = initResult.migrationsReport
69
76
 
70
77
  // The database is migrated but empty now, so nothing else to do
71
78
 
72
- yield* Effect.tryAll(() => hooks?.post?.(tmpInMemoryDb)).pipe(UnexpectedError.mapToUnexpectedError)
79
+ yield* Effect.tryAll(() => hooks?.post?.(initResult.tmpDb)).pipe(UnexpectedError.mapToUnexpectedError)
73
80
 
74
81
  break
75
82
  }
76
83
  case 'manual': {
77
- const oldDbData = db.export()
84
+ const oldDbData = dbReadModel.export()
85
+
86
+ migrationsReport = { migrations: [] }
78
87
 
79
88
  const newDbData = yield* Effect.tryAll(() => migrationOptions.migrate(oldDbData)).pipe(
80
89
  UnexpectedError.mapToUnexpectedError,
81
90
  )
82
91
 
83
- tmpSyncDb.import(newDbData)
92
+ tmpDb.import(newDbData)
84
93
 
85
94
  // TODO validate schema
86
95
 
@@ -91,17 +100,21 @@ export const recreateDb: Effect.Effect<
91
100
  }
92
101
  }
93
102
 
103
+ // TODO bring back
94
104
  // Import the temporary in-memory database into the persistent database
95
- yield* Effect.sync(() => db.import(tmpSyncDb)).pipe(
96
- Effect.withSpan('@livestore/common:leader-thread:recreateDb:import'),
97
- )
105
+ // yield* Effect.sync(() => db.import(tmpDb)).pipe(
106
+ // Effect.withSpan('@livestore/common:leader-thread:recreateDb:import'),
107
+ // )
98
108
 
99
109
  // TODO maybe bring back re-using this initial snapshot to avoid calling `.export()` again
100
110
  // We've disabled this for now as it made the code too complex, as we often run syncing right after
101
111
  // so the snapshot is no longer up to date
102
- // const snapshotFromTmpDb = tmpSyncDb.export()
112
+ // const snapshotFromTmpDb = tmpDb.export()
113
+
114
+ // TODO bring back
115
+ // tmpDb.close()
103
116
 
104
- tmpSyncDb.close()
117
+ return { migrationsReport }
105
118
  }).pipe(
106
119
  Effect.scoped, // NOTE we're closing the scope here so finalizers are called when the effect is done
107
120
  Effect.withSpan('@livestore/common:leader-thread:recreateDb'),
@@ -1,11 +1,9 @@
1
1
  import type { WebChannel } from '@livestore/utils/effect'
2
2
  import { Schema } from '@livestore/utils/effect'
3
3
 
4
- import { IntentionalShutdownCause } from '../index.js'
4
+ import { IntentionalShutdownCause, UnexpectedError } from '../index.js'
5
5
 
6
- export class DedicatedWorkerDisconnectBroadcast extends Schema.TaggedStruct('DedicatedWorkerDisconnectBroadcast', {}) {}
7
-
8
- export class All extends Schema.Union(IntentionalShutdownCause, DedicatedWorkerDisconnectBroadcast) {}
6
+ export class All extends Schema.Union(IntentionalShutdownCause, UnexpectedError) {}
9
7
 
10
8
  /**
11
9
  * Used internally by an adapter to shutdown gracefully.
@@ -1,11 +1,11 @@
1
1
  import type {
2
2
  Deferred,
3
3
  Effect,
4
- Fiber,
5
4
  HttpClient,
6
5
  Option,
7
6
  Queue,
8
7
  Scope,
8
+ Subscribable,
9
9
  SubscriptionRef,
10
10
  WebChannel,
11
11
  } from '@livestore/utils/effect'
@@ -14,31 +14,25 @@ import { Context, Schema } from '@livestore/utils/effect'
14
14
  import type {
15
15
  BootStatus,
16
16
  Devtools,
17
- InvalidPushError,
18
- MakeSynchronousDatabase,
17
+ LeaderAheadError,
18
+ MakeSqliteDb,
19
+ MigrationsReport,
19
20
  PersistenceInfo,
21
+ SqliteDb,
20
22
  SyncBackend,
21
- SynchronousDatabase,
22
23
  UnexpectedError,
23
24
  } from '../index.js'
24
25
  import type { EventId, LiveStoreSchema, MutationEvent } from '../schema/mod.js'
25
- import type { PayloadUpstream, SyncState } from '../sync/syncstate.js'
26
+ import type * as SyncState from '../sync/syncstate.js'
26
27
  import type { ShutdownChannel } from './shutdown-channel.js'
27
28
 
28
29
  export type ShutdownState = 'running' | 'shutting-down'
29
30
 
30
- export class OuterWorkerCtx extends Context.Tag('OuterWorkerCtx')<
31
- OuterWorkerCtx,
32
- {
33
- innerFiber: Fiber.RuntimeFiber<any, any>
34
- }
35
- >() {}
36
-
37
31
  export const InitialSyncOptionsSkip = Schema.TaggedStruct('Skip', {})
38
32
  export type InitialSyncOptionsSkip = typeof InitialSyncOptionsSkip.Type
39
33
 
40
34
  export const InitialSyncOptionsBlocking = Schema.TaggedStruct('Blocking', {
41
- timeout: Schema.DurationFromMillis,
35
+ timeout: Schema.Union(Schema.DurationFromMillis, Schema.Number),
42
36
  })
43
37
 
44
38
  export type InitialSyncOptionsBlocking = typeof InitialSyncOptionsBlocking.Type
@@ -55,8 +49,8 @@ export type InitialSyncInfo = Option.Option<{
55
49
  // | { _tag: 'Recreate'; snapshotRef: Ref.Ref<Uint8Array | undefined>; syncInfo: InitialSyncInfo }
56
50
  // | { _tag: 'Reuse'; syncInfo: InitialSyncInfo }
57
51
 
58
- export type LeaderDatabase = SynchronousDatabase<{ dbPointer: number; persistenceInfo: PersistenceInfo }>
59
- export type PersistenceInfoPair = { db: PersistenceInfo; mutationLog: PersistenceInfo }
52
+ export type LeaderSqliteDb = SqliteDb<{ dbPointer: number; persistenceInfo: PersistenceInfo }>
53
+ export type PersistenceInfoPair = { readModel: PersistenceInfo; mutationLog: PersistenceInfo }
60
54
 
61
55
  export type DevtoolsOptions =
62
56
  | {
@@ -64,10 +58,9 @@ export type DevtoolsOptions =
64
58
  }
65
59
  | {
66
60
  enabled: true
67
- makeContext: Effect.Effect<
61
+ makeBootContext: Effect.Effect<
68
62
  {
69
- devtoolsWebChannel: WebChannel.WebChannel<Devtools.MessageToAppLeader, Devtools.MessageFromAppLeader>
70
- shutdownChannel: ShutdownChannel
63
+ devtoolsWebChannel: WebChannel.WebChannel<Devtools.Leader.MessageToApp, Devtools.Leader.MessageFromApp>
71
64
  persistenceInfo: PersistenceInfoPair
72
65
  },
73
66
  UnexpectedError,
@@ -75,23 +68,46 @@ export type DevtoolsOptions =
75
68
  >
76
69
  }
77
70
 
71
+ export type DevtoolsContext =
72
+ | {
73
+ enabled: true
74
+ // syncBackendPullLatch: Effect.Latch
75
+ // syncBackendPushLatch: Effect.Latch
76
+ syncBackendLatch: Effect.Latch
77
+ syncBackendLatchState: SubscriptionRef.SubscriptionRef<{ latchClosed: boolean }>
78
+ }
79
+ | {
80
+ enabled: false
81
+ }
82
+
78
83
  export class LeaderThreadCtx extends Context.Tag('LeaderThreadCtx')<
79
84
  LeaderThreadCtx,
80
85
  {
81
86
  schema: LiveStoreSchema
82
87
  storeId: string
83
- originId: string
84
- makeSyncDb: MakeSynchronousDatabase
85
- db: LeaderDatabase
86
- dbLog: LeaderDatabase
88
+ clientId: string
89
+ makeSqliteDb: MakeSqliteDb
90
+ dbReadModel: LeaderSqliteDb
91
+ dbMutationLog: LeaderSqliteDb
87
92
  bootStatusQueue: Queue.Queue<BootStatus>
88
93
  // TODO we should find a more elegant way to handle cases which need this ref for their implementation
89
94
  shutdownStateSubRef: SubscriptionRef.SubscriptionRef<ShutdownState>
95
+ shutdownChannel: ShutdownChannel
90
96
  mutationEventSchema: MutationEvent.ForMutationDefRecord<any>
91
- // devtools: DevtoolsContext
97
+ devtools: DevtoolsContext
92
98
  syncBackend: SyncBackend | undefined
93
- syncProcessor: SyncProcessor
99
+ syncProcessor: LeaderSyncProcessor
94
100
  connectedClientSessionPullQueues: PullQueueSet
101
+ initialState: {
102
+ leaderHead: EventId.EventId
103
+ migrationsReport: MigrationsReport
104
+ }
105
+ /**
106
+ * e.g. used for `store._dev` APIs
107
+ *
108
+ * This is currently separated from `.devtools` as it also needs to work when devtools are disabled
109
+ */
110
+ extraIncomingMessagesQueue: Queue.Queue<Devtools.Leader.MessageToApp>
95
111
  }
96
112
  >() {}
97
113
 
@@ -101,24 +117,42 @@ export type InitialBlockingSyncContext = {
101
117
  }
102
118
 
103
119
  export type PullQueueItem = {
104
- // mutationEvents: ReadonlyArray<MutationEvent.AnyEncoded>
105
- // backendHead: number
106
- payload: PayloadUpstream
107
- // TODO move `remaining` into `PayloadUpstream`
120
+ payload: SyncState.PayloadUpstream
108
121
  remaining: number
109
122
  }
110
123
 
111
- export interface SyncProcessor {
124
+ export interface LeaderSyncProcessor {
112
125
  push: (
113
126
  /** `batch` needs to follow the same rules as `batch` in `SyncBackend.push` */
114
127
  batch: ReadonlyArray<MutationEvent.EncodedWithMeta>,
115
- ) => Effect.Effect<void, UnexpectedError | InvalidPushError, HttpClient.HttpClient | LeaderThreadCtx>
116
-
117
- pushPartial: (mutationEvent: MutationEvent.PartialAnyEncoded) => Effect.Effect<void, UnexpectedError, LeaderThreadCtx>
128
+ options?: {
129
+ /**
130
+ * This generation number is used to automatically reject subsequent pushes
131
+ * of a previously rejected push from a client session. This might occur in
132
+ * certain concurrent scenarios.
133
+ */
134
+ // generation: number
135
+ /**
136
+ * If true, the effect will only finish when the local push has been processed (i.e. succeeded or was rejected).
137
+ * @default false
138
+ */
139
+ waitForProcessing?: boolean
140
+ },
141
+ ) => Effect.Effect<void, LeaderAheadError>
142
+
143
+ pushPartial: (args: {
144
+ mutationEvent: MutationEvent.PartialAnyEncoded
145
+ clientId: string
146
+ sessionId: string | undefined
147
+ }) => Effect.Effect<void, UnexpectedError, LeaderThreadCtx>
118
148
  boot: (args: {
119
149
  dbReady: Deferred.Deferred<void>
120
- }) => Effect.Effect<void, UnexpectedError, LeaderThreadCtx | Scope.Scope | HttpClient.HttpClient>
121
- syncState: Effect.Effect<SyncState, UnexpectedError>
150
+ }) => Effect.Effect<
151
+ { initialLeaderHead: EventId.EventId },
152
+ UnexpectedError,
153
+ LeaderThreadCtx | Scope.Scope | HttpClient.HttpClient
154
+ >
155
+ syncState: Subscribable.Subscribable<SyncState.SyncState>
122
156
  }
123
157
 
124
158
  export interface PullQueueSet {