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

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 (332) 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/devtools-sessions-channel.d.ts +28 -0
  37. package/dist/devtools/devtools-sessions-channel.d.ts.map +1 -0
  38. package/dist/devtools/devtools-sessions-channel.js +34 -0
  39. package/dist/devtools/devtools-sessions-channel.js.map +1 -0
  40. package/dist/devtools/index.d.ts +35 -38
  41. package/dist/devtools/index.d.ts.map +1 -1
  42. package/dist/devtools/index.js +20 -45
  43. package/dist/devtools/index.js.map +1 -1
  44. package/dist/devtools/mod.d.ts +39 -0
  45. package/dist/devtools/mod.d.ts.map +1 -0
  46. package/dist/devtools/mod.js +27 -0
  47. package/dist/devtools/mod.js.map +1 -0
  48. package/dist/index.d.ts +2 -6
  49. package/dist/index.d.ts.map +1 -1
  50. package/dist/index.js +2 -2
  51. package/dist/index.js.map +1 -1
  52. package/dist/init-singleton-tables.d.ts +2 -2
  53. package/dist/init-singleton-tables.d.ts.map +1 -1
  54. package/dist/init-singleton-tables.js.map +1 -1
  55. package/dist/leader-thread/LeaderSyncProcessor.d.ts +39 -0
  56. package/dist/leader-thread/LeaderSyncProcessor.d.ts.map +1 -0
  57. package/dist/leader-thread/LeaderSyncProcessor.js +527 -0
  58. package/dist/leader-thread/LeaderSyncProcessor.js.map +1 -0
  59. package/dist/leader-thread/apply-mutation.d.ts +5 -2
  60. package/dist/leader-thread/apply-mutation.d.ts.map +1 -1
  61. package/dist/leader-thread/apply-mutation.js +55 -35
  62. package/dist/leader-thread/apply-mutation.js.map +1 -1
  63. package/dist/leader-thread/connection.d.ts +34 -6
  64. package/dist/leader-thread/connection.d.ts.map +1 -1
  65. package/dist/leader-thread/connection.js +22 -7
  66. package/dist/leader-thread/connection.js.map +1 -1
  67. package/dist/leader-thread/leader-worker-devtools.d.ts +1 -1
  68. package/dist/leader-thread/leader-worker-devtools.d.ts.map +1 -1
  69. package/dist/leader-thread/leader-worker-devtools.js +147 -124
  70. package/dist/leader-thread/leader-worker-devtools.js.map +1 -1
  71. package/dist/leader-thread/make-leader-thread-layer.d.ts +12 -11
  72. package/dist/leader-thread/make-leader-thread-layer.d.ts.map +1 -1
  73. package/dist/leader-thread/make-leader-thread-layer.js +55 -18
  74. package/dist/leader-thread/make-leader-thread-layer.js.map +1 -1
  75. package/dist/leader-thread/mutationlog.d.ts +6 -19
  76. package/dist/leader-thread/mutationlog.d.ts.map +1 -1
  77. package/dist/leader-thread/mutationlog.js +12 -9
  78. package/dist/leader-thread/mutationlog.js.map +1 -1
  79. package/dist/leader-thread/pull-queue-set.d.ts +3 -3
  80. package/dist/leader-thread/pull-queue-set.d.ts.map +1 -1
  81. package/dist/leader-thread/pull-queue-set.js +9 -0
  82. package/dist/leader-thread/pull-queue-set.js.map +1 -1
  83. package/dist/leader-thread/recreate-db.d.ts +4 -2
  84. package/dist/leader-thread/recreate-db.d.ts.map +1 -1
  85. package/dist/leader-thread/recreate-db.js +32 -21
  86. package/dist/leader-thread/recreate-db.js.map +1 -1
  87. package/dist/leader-thread/shutdown-channel.d.ts +2 -5
  88. package/dist/leader-thread/shutdown-channel.d.ts.map +1 -1
  89. package/dist/leader-thread/shutdown-channel.js +2 -4
  90. package/dist/leader-thread/shutdown-channel.js.map +1 -1
  91. package/dist/leader-thread/types.d.ts +58 -26
  92. package/dist/leader-thread/types.d.ts.map +1 -1
  93. package/dist/leader-thread/types.js +1 -3
  94. package/dist/leader-thread/types.js.map +1 -1
  95. package/dist/mutation.d.ts +9 -2
  96. package/dist/mutation.d.ts.map +1 -1
  97. package/dist/mutation.js +5 -5
  98. package/dist/mutation.js.map +1 -1
  99. package/dist/otel.d.ts +2 -0
  100. package/dist/otel.d.ts.map +1 -1
  101. package/dist/otel.js +5 -0
  102. package/dist/otel.js.map +1 -1
  103. package/dist/query-builder/api.d.ts +3 -3
  104. package/dist/query-builder/api.d.ts.map +1 -1
  105. package/dist/query-builder/impl.d.ts +4 -4
  106. package/dist/query-builder/impl.d.ts.map +1 -1
  107. package/dist/query-builder/impl.js.map +1 -1
  108. package/dist/query-builder/impl.test.js +16 -1
  109. package/dist/query-builder/impl.test.js.map +1 -1
  110. package/dist/query-info.d.ts +3 -3
  111. package/dist/query-info.d.ts.map +1 -1
  112. package/dist/rehydrate-from-mutationlog.d.ts +5 -5
  113. package/dist/rehydrate-from-mutationlog.d.ts.map +1 -1
  114. package/dist/rehydrate-from-mutationlog.js +23 -27
  115. package/dist/rehydrate-from-mutationlog.js.map +1 -1
  116. package/dist/schema/EventId.d.ts +27 -16
  117. package/dist/schema/EventId.d.ts.map +1 -1
  118. package/dist/schema/EventId.js +36 -11
  119. package/dist/schema/EventId.js.map +1 -1
  120. package/dist/schema/EventId.test.d.ts +2 -0
  121. package/dist/schema/EventId.test.d.ts.map +1 -0
  122. package/dist/schema/EventId.test.js +11 -0
  123. package/dist/schema/EventId.test.js.map +1 -0
  124. package/dist/schema/MutationEvent.d.ts +76 -82
  125. package/dist/schema/MutationEvent.d.ts.map +1 -1
  126. package/dist/schema/MutationEvent.js +53 -20
  127. package/dist/schema/MutationEvent.js.map +1 -1
  128. package/dist/schema/db-schema/ast/sqlite.d.ts +69 -0
  129. package/dist/schema/db-schema/ast/sqlite.d.ts.map +1 -0
  130. package/dist/schema/db-schema/ast/sqlite.js +71 -0
  131. package/dist/schema/db-schema/ast/sqlite.js.map +1 -0
  132. package/dist/schema/db-schema/ast/validate.d.ts +3 -0
  133. package/dist/schema/db-schema/ast/validate.d.ts.map +1 -0
  134. package/dist/schema/db-schema/ast/validate.js +12 -0
  135. package/dist/schema/db-schema/ast/validate.js.map +1 -0
  136. package/dist/schema/db-schema/dsl/field-defs.d.ts +90 -0
  137. package/dist/schema/db-schema/dsl/field-defs.d.ts.map +1 -0
  138. package/dist/schema/db-schema/dsl/field-defs.js +87 -0
  139. package/dist/schema/db-schema/dsl/field-defs.js.map +1 -0
  140. package/dist/schema/db-schema/dsl/field-defs.test.d.ts +2 -0
  141. package/dist/schema/db-schema/dsl/field-defs.test.d.ts.map +1 -0
  142. package/dist/schema/db-schema/dsl/field-defs.test.js +29 -0
  143. package/dist/schema/db-schema/dsl/field-defs.test.js.map +1 -0
  144. package/dist/schema/db-schema/dsl/mod.d.ts +88 -0
  145. package/dist/schema/db-schema/dsl/mod.d.ts.map +1 -0
  146. package/dist/schema/db-schema/dsl/mod.js +35 -0
  147. package/dist/schema/db-schema/dsl/mod.js.map +1 -0
  148. package/dist/schema/db-schema/hash.d.ts +2 -0
  149. package/dist/schema/db-schema/hash.d.ts.map +1 -0
  150. package/dist/schema/db-schema/hash.js +14 -0
  151. package/dist/schema/db-schema/hash.js.map +1 -0
  152. package/dist/schema/db-schema/mod.d.ts +3 -0
  153. package/dist/schema/db-schema/mod.d.ts.map +1 -0
  154. package/dist/schema/db-schema/mod.js +3 -0
  155. package/dist/schema/db-schema/mod.js.map +1 -0
  156. package/dist/schema/mod.d.ts +1 -0
  157. package/dist/schema/mod.d.ts.map +1 -1
  158. package/dist/schema/mod.js +1 -0
  159. package/dist/schema/mod.js.map +1 -1
  160. package/dist/schema/mutations.d.ts +8 -9
  161. package/dist/schema/mutations.d.ts.map +1 -1
  162. package/dist/schema/mutations.js +2 -2
  163. package/dist/schema/mutations.js.map +1 -1
  164. package/dist/schema/schema-helpers.d.ts.map +1 -1
  165. package/dist/schema/schema-helpers.js +1 -1
  166. package/dist/schema/schema-helpers.js.map +1 -1
  167. package/dist/schema/schema.d.ts +5 -2
  168. package/dist/schema/schema.d.ts.map +1 -1
  169. package/dist/schema/schema.js +20 -9
  170. package/dist/schema/schema.js.map +1 -1
  171. package/dist/schema/system-tables.d.ts +65 -47
  172. package/dist/schema/system-tables.d.ts.map +1 -1
  173. package/dist/schema/system-tables.js +24 -13
  174. package/dist/schema/system-tables.js.map +1 -1
  175. package/dist/schema/table-def.d.ts +18 -24
  176. package/dist/schema/table-def.d.ts.map +1 -1
  177. package/dist/schema/table-def.js +3 -4
  178. package/dist/schema/table-def.js.map +1 -1
  179. package/dist/schema-management/common.d.ts +3 -3
  180. package/dist/schema-management/common.d.ts.map +1 -1
  181. package/dist/schema-management/common.js.map +1 -1
  182. package/dist/schema-management/migrations.d.ts +6 -6
  183. package/dist/schema-management/migrations.d.ts.map +1 -1
  184. package/dist/schema-management/migrations.js +13 -8
  185. package/dist/schema-management/migrations.js.map +1 -1
  186. package/dist/schema-management/validate-mutation-defs.d.ts.map +1 -1
  187. package/dist/schema-management/validate-mutation-defs.js +2 -2
  188. package/dist/schema-management/validate-mutation-defs.js.map +1 -1
  189. package/dist/sql-queries/misc.d.ts.map +1 -1
  190. package/dist/sql-queries/sql-queries.d.ts +1 -1
  191. package/dist/sql-queries/sql-queries.d.ts.map +1 -1
  192. package/dist/sql-queries/sql-queries.js.map +1 -1
  193. package/dist/sql-queries/sql-query-builder.d.ts +1 -1
  194. package/dist/sql-queries/sql-query-builder.d.ts.map +1 -1
  195. package/dist/sql-queries/sql-query-builder.js.map +1 -1
  196. package/dist/sql-queries/types.d.ts +2 -1
  197. package/dist/sql-queries/types.d.ts.map +1 -1
  198. package/dist/sql-queries/types.js.map +1 -1
  199. package/dist/sync/{client-session-sync-processor.d.ts → ClientSessionSyncProcessor.d.ts} +25 -14
  200. package/dist/sync/ClientSessionSyncProcessor.d.ts.map +1 -0
  201. package/dist/sync/ClientSessionSyncProcessor.js +199 -0
  202. package/dist/sync/ClientSessionSyncProcessor.js.map +1 -0
  203. package/dist/sync/index.d.ts +1 -1
  204. package/dist/sync/index.d.ts.map +1 -1
  205. package/dist/sync/index.js +1 -1
  206. package/dist/sync/index.js.map +1 -1
  207. package/dist/sync/next/compact-events.d.ts.map +1 -1
  208. package/dist/sync/next/facts.d.ts.map +1 -1
  209. package/dist/sync/next/facts.js +1 -1
  210. package/dist/sync/next/facts.js.map +1 -1
  211. package/dist/sync/next/history-dag-common.d.ts +3 -4
  212. package/dist/sync/next/history-dag-common.d.ts.map +1 -1
  213. package/dist/sync/next/history-dag-common.js +3 -1
  214. package/dist/sync/next/history-dag-common.js.map +1 -1
  215. package/dist/sync/next/history-dag.d.ts.map +1 -1
  216. package/dist/sync/next/history-dag.js +1 -1
  217. package/dist/sync/next/history-dag.js.map +1 -1
  218. package/dist/sync/next/rebase-events.d.ts +6 -4
  219. package/dist/sync/next/rebase-events.d.ts.map +1 -1
  220. package/dist/sync/next/rebase-events.js +6 -3
  221. package/dist/sync/next/rebase-events.js.map +1 -1
  222. package/dist/sync/next/test/compact-events.calculator.test.js +12 -12
  223. package/dist/sync/next/test/compact-events.calculator.test.js.map +1 -1
  224. package/dist/sync/next/test/compact-events.test.js +43 -43
  225. package/dist/sync/next/test/compact-events.test.js.map +1 -1
  226. package/dist/sync/next/test/mutation-fixtures.d.ts +4 -4
  227. package/dist/sync/next/test/mutation-fixtures.d.ts.map +1 -1
  228. package/dist/sync/next/test/mutation-fixtures.js +12 -16
  229. package/dist/sync/next/test/mutation-fixtures.js.map +1 -1
  230. package/dist/sync/sync.d.ts +31 -16
  231. package/dist/sync/sync.d.ts.map +1 -1
  232. package/dist/sync/sync.js +7 -3
  233. package/dist/sync/sync.js.map +1 -1
  234. package/dist/sync/syncstate.d.ts +177 -44
  235. package/dist/sync/syncstate.d.ts.map +1 -1
  236. package/dist/sync/syncstate.js +188 -56
  237. package/dist/sync/syncstate.js.map +1 -1
  238. package/dist/sync/syncstate.test.js +162 -92
  239. package/dist/sync/syncstate.test.js.map +1 -1
  240. package/dist/sync/validate-push-payload.d.ts +2 -2
  241. package/dist/sync/validate-push-payload.d.ts.map +1 -1
  242. package/dist/sync/validate-push-payload.js +2 -2
  243. package/dist/sync/validate-push-payload.js.map +1 -1
  244. package/dist/util.d.ts +2 -2
  245. package/dist/util.d.ts.map +1 -1
  246. package/dist/version.d.ts +1 -1
  247. package/dist/version.d.ts.map +1 -1
  248. package/dist/version.js +1 -1
  249. package/dist/version.js.map +1 -1
  250. package/package.json +6 -6
  251. package/src/adapter-types.ts +80 -56
  252. package/src/derived-mutations.test.ts +1 -1
  253. package/src/derived-mutations.ts +13 -9
  254. package/src/devtools/devtools-messages-client-session.ts +141 -0
  255. package/src/devtools/devtools-messages-common.ts +106 -0
  256. package/src/devtools/devtools-messages-leader.ts +192 -0
  257. package/src/devtools/devtools-messages.ts +3 -243
  258. package/src/devtools/devtools-sessioninfo.ts +99 -0
  259. package/src/devtools/mod.ts +36 -0
  260. package/src/index.ts +2 -8
  261. package/src/init-singleton-tables.ts +2 -2
  262. package/src/leader-thread/LeaderSyncProcessor.ts +833 -0
  263. package/src/leader-thread/apply-mutation.ts +87 -43
  264. package/src/leader-thread/connection.ts +54 -9
  265. package/src/leader-thread/leader-worker-devtools.ts +199 -174
  266. package/src/leader-thread/make-leader-thread-layer.ts +89 -35
  267. package/src/leader-thread/mutationlog.ts +20 -14
  268. package/src/leader-thread/pull-queue-set.ts +10 -1
  269. package/src/leader-thread/recreate-db.ts +38 -25
  270. package/src/leader-thread/shutdown-channel.ts +2 -4
  271. package/src/leader-thread/types.ts +68 -34
  272. package/src/mutation.ts +17 -7
  273. package/src/otel.ts +8 -0
  274. package/src/query-builder/api.ts +4 -4
  275. package/src/query-builder/impl.test.ts +22 -1
  276. package/src/query-builder/impl.ts +2 -2
  277. package/src/query-info.ts +3 -3
  278. package/src/rehydrate-from-mutationlog.ts +28 -34
  279. package/src/schema/EventId.test.ts +12 -0
  280. package/src/schema/EventId.ts +49 -15
  281. package/src/schema/MutationEvent.ts +78 -31
  282. package/src/schema/db-schema/ast/sqlite.ts +142 -0
  283. package/src/schema/db-schema/ast/validate.ts +13 -0
  284. package/src/schema/db-schema/dsl/__snapshots__/field-defs.test.ts.snap +206 -0
  285. package/src/schema/db-schema/dsl/field-defs.test.ts +35 -0
  286. package/src/schema/db-schema/dsl/field-defs.ts +242 -0
  287. package/src/schema/db-schema/dsl/mod.ts +195 -0
  288. package/src/schema/db-schema/hash.ts +14 -0
  289. package/src/schema/db-schema/mod.ts +2 -0
  290. package/src/schema/mod.ts +1 -0
  291. package/src/schema/mutations.ts +10 -20
  292. package/src/schema/schema-helpers.ts +1 -1
  293. package/src/schema/schema.ts +22 -10
  294. package/src/schema/system-tables.ts +24 -13
  295. package/src/schema/table-def.ts +17 -17
  296. package/src/schema-management/common.ts +3 -3
  297. package/src/schema-management/migrations.ts +19 -15
  298. package/src/schema-management/validate-mutation-defs.ts +2 -2
  299. package/src/sql-queries/sql-queries.ts +1 -1
  300. package/src/sql-queries/sql-query-builder.ts +1 -2
  301. package/src/sql-queries/types.ts +3 -1
  302. package/src/sync/ClientSessionSyncProcessor.ts +313 -0
  303. package/src/sync/index.ts +1 -1
  304. package/src/sync/next/facts.ts +1 -1
  305. package/src/sync/next/history-dag-common.ts +5 -1
  306. package/src/sync/next/history-dag.ts +1 -1
  307. package/src/sync/next/rebase-events.ts +13 -7
  308. package/src/sync/next/test/compact-events.calculator.test.ts +12 -12
  309. package/src/sync/next/test/compact-events.test.ts +43 -43
  310. package/src/sync/next/test/mutation-fixtures.ts +16 -19
  311. package/src/sync/sync.ts +26 -10
  312. package/src/sync/syncstate.test.ts +178 -98
  313. package/src/sync/syncstate.ts +170 -83
  314. package/src/sync/validate-push-payload.ts +7 -4
  315. package/src/version.ts +1 -1
  316. package/tmp/pack.tgz +0 -0
  317. package/tsconfig.json +1 -1
  318. package/dist/devtools/devtools-bridge.d.ts +0 -12
  319. package/dist/devtools/devtools-bridge.d.ts.map +0 -1
  320. package/dist/devtools/devtools-bridge.js +0 -2
  321. package/dist/devtools/devtools-bridge.js.map +0 -1
  322. package/dist/leader-thread/leader-sync-processor.d.ts +0 -47
  323. package/dist/leader-thread/leader-sync-processor.d.ts.map +0 -1
  324. package/dist/leader-thread/leader-sync-processor.js +0 -422
  325. package/dist/leader-thread/leader-sync-processor.js.map +0 -1
  326. package/dist/sync/client-session-sync-processor.d.ts.map +0 -1
  327. package/dist/sync/client-session-sync-processor.js +0 -131
  328. package/dist/sync/client-session-sync-processor.js.map +0 -1
  329. package/src/devtools/devtools-bridge.ts +0 -13
  330. package/src/devtools/index.ts +0 -48
  331. package/src/leader-thread/leader-sync-processor.ts +0 -666
  332. package/src/sync/client-session-sync-processor.ts +0 -207
@@ -1,18 +1,12 @@
1
- import { Effect, FiberMap, Option, PubSub, Queue, Stream, SubscriptionRef } from '@livestore/utils/effect'
1
+ import { Effect, FiberMap, Option, Stream, SubscriptionRef } from '@livestore/utils/effect'
2
+ import { nanoid } from '@livestore/utils/nanoid'
2
3
 
3
4
  import { Devtools, IntentionalShutdownCause, liveStoreVersion, UnexpectedError } from '../index.js'
4
5
  import { MUTATION_LOG_META_TABLE, SCHEMA_META_TABLE, SCHEMA_MUTATIONS_META_TABLE } from '../schema/mod.js'
5
- import type { ShutdownChannel } from './shutdown-channel.js'
6
6
  import type { DevtoolsOptions, PersistenceInfoPair } from './types.js'
7
7
  import { LeaderThreadCtx } from './types.js'
8
8
 
9
- type SendMessageToDevtools = (
10
- message: Devtools.MessageFromAppLeader,
11
- options?: {
12
- /** Send message even if not connected (e.g. for initial broadcast messages) */
13
- force: boolean
14
- },
15
- ) => Effect.Effect<void>
9
+ type SendMessageToDevtools = (message: Devtools.Leader.MessageFromApp) => Effect.Effect<void>
16
10
 
17
11
  // TODO bind scope to the webchannel lifetime
18
12
  export const bootDevtools = (options: DevtoolsOptions) =>
@@ -21,240 +15,205 @@ export const bootDevtools = (options: DevtoolsOptions) =>
21
15
  return
22
16
  }
23
17
 
24
- const { persistenceInfo, shutdownChannel, devtoolsWebChannel } = yield* options.makeContext
18
+ const { connectedClientSessionPullQueues, syncProcessor, extraIncomingMessagesQueue } = yield* LeaderThreadCtx
25
19
 
26
- const isConnected = yield* SubscriptionRef.make(true)
20
+ yield* listenToDevtools({
21
+ incomingMessages: Stream.fromQueue(extraIncomingMessagesQueue),
22
+ sendMessage: () => Effect.void,
23
+ }).pipe(Effect.tapCauseLogPretty, Effect.forkScoped)
27
24
 
28
- const incomingMessagesPubSub = yield* PubSub.unbounded<Devtools.MessageToAppLeader>().pipe(
29
- Effect.acquireRelease(PubSub.shutdown),
30
- )
25
+ const { persistenceInfo, devtoolsWebChannel } = yield* options.makeBootContext
31
26
 
32
- const incomingMessages = Stream.fromPubSub(incomingMessagesPubSub)
27
+ const sendMessage: SendMessageToDevtools = (message) =>
28
+ devtoolsWebChannel
29
+ .send(message)
30
+ .pipe(
31
+ Effect.withSpan('@livestore/common:leader-thread:devtools:sendToDevtools'),
32
+ Effect.interruptible,
33
+ Effect.ignoreLogged,
34
+ )
33
35
 
34
- const outgoingMessagesQueue = yield* Queue.unbounded<Devtools.MessageFromAppLeader>().pipe(
35
- Effect.acquireRelease(Queue.shutdown),
36
- )
37
-
38
- const devtoolsCoordinatorChannel = devtoolsWebChannel
39
- // coordinatorMessagePortOrChannel instanceof MessagePort
40
- // ? yield* WebChannel.messagePortChannel({
41
- // port: coordinatorMessagePortOrChannel,
42
- // schema: { send: Devtools.MessageFromAppLeader, listen: Devtools.MessageToAppLeader },
43
- // })
44
- // : coordinatorMessagePortOrChannel
45
-
46
- const sendMessage: SendMessageToDevtools = (message, options) =>
47
- Effect.gen(function* () {
48
- if (options?.force === true || (yield* isConnected)) {
49
- yield* devtoolsCoordinatorChannel.send(message)
50
- } else {
51
- yield* Queue.offer(outgoingMessagesQueue, message)
52
- }
53
- }).pipe(
54
- Effect.withSpan('@livestore/common:leader-thread:devtools:sendToDevtools'),
55
- Effect.interruptible,
56
- Effect.ignoreLogged,
57
- )
58
-
59
- // broadcastCallbacks.add((message) => sendMessage(message))
60
-
61
- const { connectedClientSessionPullQueues, syncProcessor } = yield* LeaderThreadCtx
62
36
  const { localHead } = yield* syncProcessor.syncState
63
37
 
64
38
  // TODO close queue when devtools disconnects
65
39
  const pullQueue = yield* connectedClientSessionPullQueues.makeQueue(localHead)
66
40
 
67
41
  yield* Stream.fromQueue(pullQueue).pipe(
68
- Stream.tap((msg) =>
69
- Effect.gen(function* () {
70
- if (msg.payload._tag === 'upstream-advance') {
71
- for (const mutationEventEncoded of msg.payload.newEvents) {
72
- yield* sendMessage(
73
- Devtools.MutationBroadcast.make({
74
- mutationEventEncoded,
75
-
76
- liveStoreVersion,
77
- }),
78
- )
79
- }
80
- } else {
81
- yield* Effect.logWarning('TODO implement rebases in devtools')
82
- }
83
- }),
84
- ),
85
- Stream.runDrain,
86
- Effect.forkScoped,
87
- )
88
-
89
- yield* devtoolsCoordinatorChannel.listen.pipe(
90
- Stream.flatten(),
91
- // Stream.tapLogWithLabel('@livestore/common:leader-thread:devtools:onPortMessage'),
92
- Stream.tap((msg) =>
93
- Effect.gen(function* () {
94
- // yield* Effect.logDebug(`[@livestore/common:leader-thread:devtools] message from port: ${msg._tag}`, msg)
95
- // if (msg._tag === 'LSD.MessagePortForStoreRes') {
96
- // yield* Deferred.succeed(storeMessagePortDeferred, msg.port)
97
- // } else {
98
- yield* PubSub.publish(incomingMessagesPubSub, msg)
99
- // }
100
- }),
101
- ),
42
+ Stream.tap((msg) => sendMessage(Devtools.Leader.SyncPull.make({ payload: msg.payload, liveStoreVersion }))),
102
43
  Stream.runDrain,
103
- Effect.withSpan(`@livestore/common:leader-thread:devtools:onPortMessage`),
104
- Effect.ignoreLogged,
105
44
  Effect.forkScoped,
106
45
  )
107
46
 
108
- // yield* sendMessage(Devtools.AppHostReady.make({ appHostId, liveStoreVersion, isLeader }), { force: true })
109
-
110
- // yield* sendMessage(Devtools.MessagePortForStoreReq.make({ appHostId, liveStoreVersion, requestId: nanoid() }), {
111
- // force: true,
112
- // })
113
-
114
47
  yield* listenToDevtools({
115
- incomingMessages,
48
+ incomingMessages: devtoolsWebChannel.listen.pipe(Stream.flatten(), Stream.orDie),
116
49
  sendMessage,
117
- // isConnected,
118
- // disconnect,
119
- // storeId,
120
- // appHostId,
121
- // isLeader,
122
50
  persistenceInfo,
123
- shutdownChannel,
124
- })
51
+ }).pipe(Effect.tapCauseLogPretty, Effect.forkScoped)
125
52
  }).pipe(Effect.withSpan('@livestore/common:leader-thread:devtools:boot'))
126
53
 
127
54
  const listenToDevtools = ({
128
55
  incomingMessages,
129
56
  sendMessage,
130
- // isConnected,
131
- // disconnect,
132
- // appHostId,
133
- // storeId,
134
- // isLeader,
135
57
  persistenceInfo,
136
- shutdownChannel,
137
58
  }: {
138
- incomingMessages: Stream.Stream<Devtools.MessageToAppLeader>
59
+ incomingMessages: Stream.Stream<Devtools.Leader.MessageToApp>
139
60
  sendMessage: SendMessageToDevtools
140
- // isConnected: SubscriptionRef.SubscriptionRef<boolean>
141
- // disconnect: Effect.Effect<void>
142
- // appHostId: string
143
- // storeId: string
144
- // isLeader: boolean
145
- persistenceInfo: PersistenceInfoPair
146
- shutdownChannel: ShutdownChannel
61
+ persistenceInfo?: PersistenceInfoPair
147
62
  }) =>
148
63
  Effect.gen(function* () {
149
- const innerWorkerCtx = yield* LeaderThreadCtx
150
- const { syncBackend, makeSyncDb, db, dbLog, shutdownStateSubRef, syncProcessor } = innerWorkerCtx
64
+ const {
65
+ syncBackend,
66
+ makeSqliteDb,
67
+ dbReadModel,
68
+ dbMutationLog,
69
+ shutdownStateSubRef,
70
+ shutdownChannel,
71
+ syncProcessor,
72
+ clientId,
73
+ devtools,
74
+ } = yield* LeaderThreadCtx
75
+
76
+ type SubscriptionId = string
77
+ const subscriptionFiberMap = yield* FiberMap.make<SubscriptionId>()
151
78
 
152
79
  type RequestId = string
153
- const subscriptionFiberMap = yield* FiberMap.make<RequestId>()
80
+ const handledRequestIds = new Set<RequestId>()
154
81
 
155
82
  yield* incomingMessages.pipe(
156
83
  Stream.tap((decodedEvent) =>
157
84
  Effect.gen(function* () {
158
- // yield* Effect.logDebug('[@livestore/common:leader-thread:devtools] incomingMessage', decodedEvent)
159
-
160
- if (decodedEvent._tag === 'LSD.Disconnect') {
161
- // yield* SubscriptionRef.set(isConnected, false)
85
+ const { requestId } = decodedEvent
86
+ const reqPayload = { requestId, liveStoreVersion, clientId }
162
87
 
163
- // yield* disconnect
88
+ // yield* Effect.logDebug(
89
+ // `[@livestore/common:leader-thread:devtools] incomingMessage: ${decodedEvent._tag} (${requestId})`,
90
+ // decodedEvent,
91
+ // )
164
92
 
165
- // TODO is there a better place for this?
166
- // yield* sendMessage(Devtools.AppHostReady.make({ appHostId, liveStoreVersion, isLeader }), {
167
- // force: true,
168
- // })
93
+ if (decodedEvent._tag === 'LSD.Leader.Disconnect') {
94
+ return
95
+ }
169
96
 
97
+ // TODO we should try to move the duplicate message handling on the webmesh layer
98
+ // So far I could only observe this problem with webmesh proxy channels (e.g. for Expo)
99
+ // Proof: https://share.cleanshot.com/V9G87B0B
100
+ // Also see `store/devtools.ts` for same problem
101
+ if (handledRequestIds.has(requestId)) {
102
+ // yield* Effect.logWarning(`Duplicate message`, decodedEvent)
170
103
  return
171
104
  }
172
105
 
173
- const { requestId } = decodedEvent
174
- const reqPayload = { requestId, liveStoreVersion }
106
+ handledRequestIds.add(requestId)
175
107
 
176
108
  switch (decodedEvent._tag) {
177
- case 'LSD.Ping': {
178
- yield* sendMessage(Devtools.Pong.make({ ...reqPayload }))
109
+ case 'LSD.Leader.Ping': {
110
+ yield* sendMessage(Devtools.Leader.Pong.make({ ...reqPayload }))
179
111
  return
180
112
  }
181
113
  case 'LSD.Leader.SnapshotReq': {
182
- const snapshot = db.export()
114
+ const snapshot = dbReadModel.export()
183
115
 
184
- yield* sendMessage(Devtools.SnapshotRes.make({ snapshot, ...reqPayload }))
116
+ yield* sendMessage(Devtools.Leader.SnapshotRes.make({ snapshot, ...reqPayload }))
185
117
 
186
118
  return
187
119
  }
188
- case 'LSD.Leader.LoadDatabaseFileReq': {
120
+ case 'LSD.Leader.LoadDatabaseFile.Request': {
189
121
  const { data } = decodedEvent
190
122
 
191
123
  let tableNames: Set<string>
192
124
 
193
125
  try {
194
- const tmpSyncDb = yield* makeSyncDb({ _tag: 'in-memory' })
195
- tmpSyncDb.import(data)
196
- const tableNameResults = tmpSyncDb.select<{ name: string }>(
126
+ const tmpDb = yield* makeSqliteDb({ _tag: 'in-memory' })
127
+ tmpDb.import(data)
128
+ const tableNameResults = tmpDb.select<{ name: string }>(
197
129
  `select name from sqlite_master where type = 'table'`,
198
130
  )
199
131
 
200
132
  tableNames = new Set(tableNameResults.map((_) => _.name))
201
133
 
202
- tmpSyncDb.close()
203
- } catch (e) {
204
- yield* Effect.logError(`Error importing database file`, e)
205
- yield* sendMessage(Devtools.LoadDatabaseFileRes.make({ ...reqPayload, status: 'unsupported-file' }))
134
+ tmpDb.close()
135
+ } catch (cause) {
136
+ yield* Effect.logError(`Error importing database file`, cause)
137
+ yield* sendMessage(
138
+ Devtools.Leader.LoadDatabaseFile.Error.make({
139
+ ...reqPayload,
140
+ cause: { _tag: 'unexpected-error', cause },
141
+ }),
142
+ )
206
143
 
207
144
  return
208
145
  }
209
146
 
210
- if (tableNames.has(MUTATION_LOG_META_TABLE)) {
211
- yield* SubscriptionRef.set(shutdownStateSubRef, 'shutting-down')
212
-
213
- dbLog.import(data)
147
+ try {
148
+ if (tableNames.has(MUTATION_LOG_META_TABLE)) {
149
+ // Is mutation log
150
+ yield* SubscriptionRef.set(shutdownStateSubRef, 'shutting-down')
214
151
 
215
- db.destroy()
216
- } else if (tableNames.has(SCHEMA_META_TABLE) && tableNames.has(SCHEMA_MUTATIONS_META_TABLE)) {
217
- yield* SubscriptionRef.set(shutdownStateSubRef, 'shutting-down')
152
+ dbMutationLog.import(data)
218
153
 
219
- db.import(data)
154
+ dbReadModel.destroy()
155
+ } else if (tableNames.has(SCHEMA_META_TABLE) && tableNames.has(SCHEMA_MUTATIONS_META_TABLE)) {
156
+ // Is read model
157
+ yield* SubscriptionRef.set(shutdownStateSubRef, 'shutting-down')
220
158
 
221
- dbLog.destroy()
222
- } else {
223
- yield* sendMessage(Devtools.LoadDatabaseFileRes.make({ ...reqPayload, status: 'unsupported-database' }))
224
- return
225
- }
159
+ dbReadModel.import(data)
226
160
 
227
- yield* sendMessage(Devtools.LoadDatabaseFileRes.make({ ...reqPayload, status: 'ok' }))
161
+ dbMutationLog.destroy()
162
+ } else {
163
+ yield* sendMessage(
164
+ Devtools.Leader.LoadDatabaseFile.Error.make({
165
+ ...reqPayload,
166
+ cause: { _tag: 'unsupported-database' },
167
+ }),
168
+ )
169
+ return
170
+ }
228
171
 
229
- yield* shutdownChannel.send(IntentionalShutdownCause.make({ reason: 'devtools-import' }))
172
+ yield* sendMessage(Devtools.Leader.LoadDatabaseFile.Success.make({ ...reqPayload }))
173
+ yield* shutdownChannel.send(IntentionalShutdownCause.make({ reason: 'devtools-import' })) ?? Effect.void
230
174
 
231
- return
175
+ return
176
+ } catch (cause) {
177
+ yield* Effect.logError(`Error importing database file`, cause)
178
+ yield* sendMessage(
179
+ Devtools.Leader.LoadDatabaseFile.Error.make({
180
+ ...reqPayload,
181
+ cause: { _tag: 'unexpected-error', cause },
182
+ }),
183
+ )
184
+ return
185
+ }
232
186
  }
233
- case 'LSD.Leader.ResetAllDataReq': {
187
+ case 'LSD.Leader.ResetAllData.Request': {
234
188
  const { mode } = decodedEvent
235
189
 
236
190
  yield* SubscriptionRef.set(shutdownStateSubRef, 'shutting-down')
237
191
 
238
- db.destroy()
192
+ dbReadModel.destroy()
239
193
 
240
194
  if (mode === 'all-data') {
241
- dbLog.destroy()
195
+ dbMutationLog.destroy()
242
196
  }
243
197
 
244
- yield* sendMessage(Devtools.ResetAllDataRes.make({ ...reqPayload }))
198
+ yield* sendMessage(Devtools.Leader.ResetAllData.Success.make({ ...reqPayload }))
245
199
 
246
- yield* shutdownChannel.send(IntentionalShutdownCause.make({ reason: 'devtools-reset' }))
200
+ yield* shutdownChannel.send(IntentionalShutdownCause.make({ reason: 'devtools-reset' })) ?? Effect.void
247
201
 
248
202
  return
249
203
  }
250
204
  case 'LSD.Leader.DatabaseFileInfoReq': {
205
+ if (persistenceInfo === undefined) {
206
+ console.log('[@livestore/common:leader-thread:devtools] persistenceInfo is required for this request')
207
+ return
208
+ }
209
+
251
210
  const dbSizeQuery = `SELECT page_count * page_size as size FROM pragma_page_count(), pragma_page_size();`
252
- const dbFileSize = db.select<{ size: number }>(dbSizeQuery, undefined)[0]!.size
253
- const mutationLogFileSize = dbLog.select<{ size: number }>(dbSizeQuery, undefined)[0]!.size
211
+ const dbFileSize = dbReadModel.select<{ size: number }>(dbSizeQuery, undefined)[0]!.size
212
+ const mutationLogFileSize = dbMutationLog.select<{ size: number }>(dbSizeQuery, undefined)[0]!.size
254
213
 
255
214
  yield* sendMessage(
256
- Devtools.DatabaseFileInfoRes.make({
257
- db: { fileSize: dbFileSize, persistenceInfo: persistenceInfo.db },
215
+ Devtools.Leader.DatabaseFileInfoRes.make({
216
+ readModel: { fileSize: dbFileSize, persistenceInfo: persistenceInfo.readModel },
258
217
  mutationLog: { fileSize: mutationLogFileSize, persistenceInfo: persistenceInfo.mutationLog },
259
218
  ...reqPayload,
260
219
  }),
@@ -263,21 +222,25 @@ const listenToDevtools = ({
263
222
  return
264
223
  }
265
224
  case 'LSD.Leader.MutationLogReq': {
266
- const mutationLog = dbLog.export()
225
+ const mutationLog = dbMutationLog.export()
267
226
 
268
- yield* sendMessage(Devtools.MutationLogRes.make({ mutationLog, ...reqPayload }))
227
+ yield* sendMessage(Devtools.Leader.MutationLogRes.make({ mutationLog, ...reqPayload }))
269
228
 
270
229
  return
271
230
  }
272
231
  case 'LSD.Leader.RunMutationReq': {
273
- yield* syncProcessor.pushPartial(decodedEvent.mutationEventEncoded)
232
+ yield* syncProcessor.pushPartial({
233
+ mutationEvent: decodedEvent.mutationEventEncoded,
234
+ clientId: `devtools-${clientId}`,
235
+ sessionId: undefined,
236
+ })
274
237
 
275
- yield* sendMessage(Devtools.RunMutationRes.make({ ...reqPayload }))
238
+ yield* sendMessage(Devtools.Leader.RunMutationRes.make({ ...reqPayload }))
276
239
 
277
240
  return
278
241
  }
279
242
  case 'LSD.Leader.SyncHistorySubscribe': {
280
- const { requestId } = decodedEvent
243
+ const { subscriptionId } = decodedEvent
281
244
 
282
245
  if (syncBackend !== undefined) {
283
246
  // TODO consider piggybacking on the existing leader-thread sync-pulling
@@ -285,13 +248,20 @@ const listenToDevtools = ({
285
248
  Stream.map((_) => _.batch),
286
249
  Stream.flattenIterables,
287
250
  Stream.tap(({ mutationEventEncoded, metadata }) =>
288
- sendMessage(Devtools.SyncHistoryRes.make({ mutationEventEncoded, metadata, ...reqPayload })),
251
+ sendMessage(
252
+ Devtools.Leader.SyncHistoryRes.make({
253
+ mutationEventEncoded,
254
+ metadata,
255
+ subscriptionId,
256
+ ...reqPayload,
257
+ requestId: nanoid(10),
258
+ }),
259
+ ),
289
260
  ),
290
261
  Stream.runDrain,
291
- Effect.acquireRelease(() => Effect.log('syncHistorySubscribe done')),
292
262
  Effect.interruptible,
293
263
  Effect.tapCauseLogPretty,
294
- FiberMap.run(subscriptionFiberMap, requestId),
264
+ FiberMap.run(subscriptionFiberMap, subscriptionId),
295
265
  )
296
266
  }
297
267
 
@@ -306,37 +276,42 @@ const listenToDevtools = ({
306
276
  return
307
277
  }
308
278
  case 'LSD.Leader.SyncingInfoReq': {
309
- const syncingInfo = Devtools.SyncingInfo.make({
279
+ const syncingInfo = Devtools.Leader.SyncingInfo.make({
310
280
  enabled: syncBackend !== undefined,
311
281
  metadata: {},
312
282
  })
313
283
 
314
- yield* sendMessage(Devtools.SyncingInfoRes.make({ syncingInfo, ...reqPayload }))
284
+ yield* sendMessage(Devtools.Leader.SyncingInfoRes.make({ syncingInfo, ...reqPayload }))
315
285
 
316
286
  return
317
287
  }
318
288
  case 'LSD.Leader.NetworkStatusSubscribe': {
319
289
  if (syncBackend !== undefined) {
320
- const { requestId } = decodedEvent
290
+ const { subscriptionId } = decodedEvent
321
291
 
322
292
  // TODO investigate and fix bug. seems that when sending messages right after
323
293
  // the devtools have connected get sometimes lost
324
294
  // This is probably the same "flaky databrowser loading" bug as we're seeing in the playwright tests
325
295
  yield* Effect.sleep(1000)
326
296
 
327
- yield* syncBackend.isConnected.changes.pipe(
328
- Stream.tap((isConnected) =>
297
+ yield* Stream.zipLatest(
298
+ syncBackend.isConnected.changes,
299
+ devtools.enabled ? devtools.syncBackendLatchState.changes : Stream.make({ latchClosed: false }),
300
+ ).pipe(
301
+ Stream.tap(([isConnected, { latchClosed }]) =>
329
302
  sendMessage(
330
- Devtools.NetworkStatusRes.make({
331
- networkStatus: { isConnected, timestampMs: Date.now() },
303
+ Devtools.Leader.NetworkStatusRes.make({
304
+ networkStatus: { isConnected, timestampMs: Date.now(), latchClosed },
305
+ subscriptionId,
332
306
  ...reqPayload,
307
+ requestId: nanoid(10),
333
308
  }),
334
309
  ),
335
310
  ),
336
311
  Stream.runDrain,
337
312
  Effect.interruptible,
338
313
  Effect.tapCauseLogPretty,
339
- FiberMap.run(subscriptionFiberMap, requestId),
314
+ FiberMap.run(subscriptionFiberMap, subscriptionId),
340
315
  )
341
316
  }
342
317
 
@@ -349,6 +324,56 @@ const listenToDevtools = ({
349
324
 
350
325
  return
351
326
  }
327
+ case 'LSD.Leader.SyncHeadSubscribe': {
328
+ const { subscriptionId } = decodedEvent
329
+
330
+ yield* syncProcessor.syncState.changes.pipe(
331
+ Stream.tap((syncState) =>
332
+ sendMessage(
333
+ Devtools.Leader.SyncHeadRes.make({
334
+ local: syncState.localHead,
335
+ upstream: syncState.upstreamHead,
336
+ subscriptionId,
337
+ ...reqPayload,
338
+ requestId: nanoid(10),
339
+ }),
340
+ ),
341
+ ),
342
+ Stream.runDrain,
343
+ Effect.interruptible,
344
+ Effect.tapCauseLogPretty,
345
+ FiberMap.run(subscriptionFiberMap, subscriptionId),
346
+ )
347
+
348
+ return
349
+ }
350
+ case 'LSD.Leader.SyncHeadUnsubscribe': {
351
+ const { subscriptionId } = decodedEvent
352
+
353
+ yield* FiberMap.remove(subscriptionFiberMap, subscriptionId)
354
+
355
+ return
356
+ }
357
+ case 'LSD.Leader.SetSyncLatch.Request': {
358
+ const { closeLatch } = decodedEvent
359
+
360
+ if (devtools.enabled === false) return
361
+
362
+ if (closeLatch === true) {
363
+ yield* devtools.syncBackendLatch.close
364
+ } else {
365
+ yield* devtools.syncBackendLatch.open
366
+ }
367
+
368
+ yield* SubscriptionRef.set(devtools.syncBackendLatchState, { latchClosed: closeLatch })
369
+
370
+ yield* sendMessage(Devtools.Leader.SetSyncLatch.Success.make({ ...reqPayload }))
371
+
372
+ return
373
+ }
374
+ default: {
375
+ yield* Effect.logWarning(`TODO implement devtools message`, decodedEvent)
376
+ }
352
377
  }
353
378
  }).pipe(Effect.withSpan(`@livestore/common:leader-thread:onDevtoolsMessage:${decodedEvent._tag}`)),
354
379
  ),