@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,6 +1,7 @@
1
- import { shouldNeverHappen } from '@livestore/utils'
2
- import { ReadonlyArray, Schema } from '@livestore/utils/effect'
1
+ import { casesHandled } from '@livestore/utils'
2
+ import { Match, ReadonlyArray, Schema } from '@livestore/utils/effect'
3
3
 
4
+ import { UnexpectedError } from '../adapter-types.js'
4
5
  import * as EventId from '../schema/EventId.js'
5
6
  import * as MutationEvent from '../schema/MutationEvent.js'
6
7
 
@@ -39,19 +40,21 @@ import * as MutationEvent from '../schema/MutationEvent.js'
39
40
  * The `updateSyncState` function processes updates to the sync state based on incoming payloads,
40
41
  * handling cases such as upstream rebase, advance, local push, and rollback tail trimming.
41
42
  */
42
- export interface SyncState {
43
- pending: ReadonlyArray<MutationEvent.EncodedWithMeta>
44
- rollbackTail: ReadonlyArray<MutationEvent.EncodedWithMeta>
45
- upstreamHead: EventId.EventId
46
- localHead: EventId.EventId
47
- }
48
-
49
- export const SyncState = Schema.Struct({
43
+ export class SyncState extends Schema.Class<SyncState>('SyncState')({
50
44
  pending: Schema.Array(MutationEvent.EncodedWithMeta),
51
45
  rollbackTail: Schema.Array(MutationEvent.EncodedWithMeta),
52
46
  upstreamHead: EventId.EventId,
53
47
  localHead: EventId.EventId,
54
- }).annotations({ title: 'SyncState' })
48
+ }) {
49
+ toJSON = (): any => {
50
+ return {
51
+ pending: this.pending.map((e) => e.toJSON()),
52
+ rollbackTail: this.rollbackTail.map((e) => e.toJSON()),
53
+ upstreamHead: `(${this.upstreamHead.global},${this.upstreamHead.client})`,
54
+ localHead: `(${this.localHead.global},${this.localHead.client})`,
55
+ }
56
+ }
57
+ }
55
58
 
56
59
  export class PayloadUpstreamRebase extends Schema.TaggedStruct('upstream-rebase', {
57
60
  /** Rollback until this event in the rollback tail (inclusive). Starting from the end of the rollback tail. */
@@ -77,31 +80,104 @@ export const PayloadUpstream = Schema.Union(PayloadUpstreamRebase, PayloadUpstre
77
80
 
78
81
  export type PayloadUpstream = typeof PayloadUpstream.Type
79
82
 
80
- export type UpdateResultAdvance = {
81
- _tag: 'advance'
82
- newSyncState: SyncState
83
- previousSyncState: SyncState
83
+ /** Only used for debugging purposes */
84
+ export class UpdateContext extends Schema.Class<UpdateContext>('UpdateContext')({
85
+ payload: Payload,
86
+ syncState: SyncState,
87
+ }) {
88
+ toJSON = (): any => {
89
+ const payload = Match.value(this.payload).pipe(
90
+ Match.tag('local-push', () => ({
91
+ _tag: 'local-push',
92
+ newEvents: this.payload.newEvents.map((e) => e.toJSON()),
93
+ })),
94
+ Match.tag('upstream-advance', () => ({
95
+ _tag: 'upstream-advance',
96
+ newEvents: this.payload.newEvents.map((e) => e.toJSON()),
97
+ })),
98
+ Match.tag('upstream-rebase', () => ({
99
+ _tag: 'upstream-rebase',
100
+ newEvents: this.payload.newEvents.map((e) => e.toJSON()),
101
+ })),
102
+ Match.exhaustive,
103
+ )
104
+ return {
105
+ payload,
106
+ syncState: this.syncState.toJSON(),
107
+ }
108
+ }
109
+ }
110
+
111
+ export class UpdateResultAdvance extends Schema.Class<UpdateResultAdvance>('UpdateResultAdvance')({
112
+ _tag: Schema.Literal('advance'),
113
+ newSyncState: SyncState,
84
114
  /** Events which weren't pending before the update */
85
- newEvents: ReadonlyArray<MutationEvent.EncodedWithMeta>
115
+ newEvents: Schema.Array(MutationEvent.EncodedWithMeta),
116
+ updateContext: UpdateContext,
117
+ }) {
118
+ toJSON = (): any => {
119
+ return {
120
+ _tag: this._tag,
121
+ newSyncState: this.newSyncState.toJSON(),
122
+ newEvents: this.newEvents.map((e) => e.toJSON()),
123
+ updateContext: this.updateContext.toJSON(),
124
+ }
125
+ }
86
126
  }
87
127
 
88
- export type UpdateResultRebase = {
89
- _tag: 'rebase'
90
- newSyncState: SyncState
91
- previousSyncState: SyncState
128
+ export class UpdateResultRebase extends Schema.Class<UpdateResultRebase>('UpdateResultRebase')({
129
+ _tag: Schema.Literal('rebase'),
130
+ newSyncState: SyncState,
92
131
  /** Events which weren't pending before the update */
93
- newEvents: ReadonlyArray<MutationEvent.EncodedWithMeta>
94
- eventsToRollback: ReadonlyArray<MutationEvent.EncodedWithMeta>
132
+ newEvents: Schema.Array(MutationEvent.EncodedWithMeta),
133
+ eventsToRollback: Schema.Array(MutationEvent.EncodedWithMeta),
134
+ updateContext: UpdateContext,
135
+ }) {
136
+ toJSON = (): any => {
137
+ return {
138
+ _tag: this._tag,
139
+ newSyncState: this.newSyncState.toJSON(),
140
+ newEvents: this.newEvents.map((e) => e.toJSON()),
141
+ eventsToRollback: this.eventsToRollback.map((e) => e.toJSON()),
142
+ updateContext: this.updateContext.toJSON(),
143
+ }
144
+ }
95
145
  }
96
146
 
97
- export type UpdateResultReject = {
98
- _tag: 'reject'
99
- previousSyncState: SyncState
147
+ export class UpdateResultReject extends Schema.Class<UpdateResultReject>('UpdateResultReject')({
148
+ _tag: Schema.Literal('reject'),
100
149
  /** The minimum id that the new events must have */
101
- expectedMinimumId: EventId.EventId
150
+ expectedMinimumId: EventId.EventId,
151
+ updateContext: UpdateContext,
152
+ }) {
153
+ toJSON = (): any => {
154
+ return {
155
+ _tag: this._tag,
156
+ expectedMinimumId: `(${this.expectedMinimumId.global},${this.expectedMinimumId.client})`,
157
+ updateContext: this.updateContext.toJSON(),
158
+ }
159
+ }
102
160
  }
103
161
 
104
- export type UpdateResult = UpdateResultAdvance | UpdateResultRebase | UpdateResultReject
162
+ export class UpdateResultUnexpectedError extends Schema.Class<UpdateResultUnexpectedError>(
163
+ 'UpdateResultUnexpectedError',
164
+ )({
165
+ _tag: Schema.Literal('unexpected-error'),
166
+ cause: UnexpectedError,
167
+ }) {}
168
+
169
+ export class UpdateResult extends Schema.Union(
170
+ UpdateResultAdvance,
171
+ UpdateResultRebase,
172
+ UpdateResultReject,
173
+ UpdateResultUnexpectedError,
174
+ ) {}
175
+
176
+ const unexpectedError = (cause: unknown): UpdateResultUnexpectedError =>
177
+ UpdateResultUnexpectedError.make({
178
+ _tag: 'unexpected-error',
179
+ cause: new UnexpectedError({ cause }),
180
+ })
105
181
 
106
182
  export const updateSyncState = ({
107
183
  syncState,
@@ -116,7 +192,7 @@ export const updateSyncState = ({
116
192
  isEqualEvent: (a: MutationEvent.EncodedWithMeta, b: MutationEvent.EncodedWithMeta) => boolean
117
193
  /** This is used in the leader which should ignore local events when receiving an upstream-advance payload */
118
194
  ignoreLocalEvents?: boolean
119
- }): UpdateResult => {
195
+ }): typeof UpdateResult.Type => {
120
196
  const trimRollbackTail = (
121
197
  rollbackTail: ReadonlyArray<MutationEvent.EncodedWithMeta>,
122
198
  ): ReadonlyArray<MutationEvent.EncodedWithMeta> => {
@@ -127,6 +203,8 @@ export const updateSyncState = ({
127
203
  return rollbackTail.slice(index + 1)
128
204
  }
129
205
 
206
+ const updateContext = UpdateContext.make({ payload, syncState })
207
+
130
208
  switch (payload._tag) {
131
209
  case 'upstream-rebase': {
132
210
  // Find the index of the rollback event in the rollback tail
@@ -134,8 +212,8 @@ export const updateSyncState = ({
134
212
  EventId.isEqual(event.id, payload.rollbackUntil),
135
213
  )
136
214
  if (rollbackIndex === -1) {
137
- return shouldNeverHappen(
138
- `Rollback event not found in rollback tail. Rollback until: [${payload.rollbackUntil.global},${payload.rollbackUntil.local}]. Rollback tail: [${syncState.rollbackTail.map((e) => e.toString()).join(', ')}]`,
215
+ return unexpectedError(
216
+ `Rollback event not found in rollback tail. Rollback until: [${payload.rollbackUntil.global},${payload.rollbackUntil.client}]. Rollback tail: [${syncState.rollbackTail.map((e) => e.toString()).join(', ')}]`,
139
217
  )
140
218
  }
141
219
 
@@ -151,42 +229,51 @@ export const updateSyncState = ({
151
229
  isLocalEvent,
152
230
  })
153
231
 
154
- return {
232
+ return UpdateResultRebase.make({
155
233
  _tag: 'rebase',
156
- newSyncState: {
234
+ newSyncState: new SyncState({
157
235
  pending: rebasedPending,
158
236
  rollbackTail: trimRollbackTail([...syncState.rollbackTail.slice(0, rollbackIndex), ...payload.newEvents]),
159
237
  upstreamHead: newUpstreamHead,
160
238
  localHead: rebasedPending.at(-1)?.id ?? newUpstreamHead,
161
- },
162
- previousSyncState: syncState,
163
- newEvents: payload.newEvents,
239
+ }),
240
+ newEvents: [...payload.newEvents, ...rebasedPending],
164
241
  eventsToRollback,
165
- }
242
+ updateContext,
243
+ })
166
244
  }
167
245
 
168
246
  case 'upstream-advance': {
169
247
  if (payload.newEvents.length === 0) {
170
- return {
248
+ return UpdateResultAdvance.make({
171
249
  _tag: 'advance',
172
- newSyncState: {
250
+ newSyncState: new SyncState({
173
251
  pending: syncState.pending,
174
252
  rollbackTail: trimRollbackTail(syncState.rollbackTail),
175
253
  upstreamHead: syncState.upstreamHead,
176
254
  localHead: syncState.localHead,
177
- },
178
- previousSyncState: syncState,
255
+ }),
179
256
  newEvents: [],
180
- }
257
+ updateContext,
258
+ })
181
259
  }
182
260
 
183
261
  // Validate that newEvents are sorted in ascending order by eventId
184
262
  for (let i = 1; i < payload.newEvents.length; i++) {
185
263
  if (EventId.isGreaterThan(payload.newEvents[i - 1]!.id, payload.newEvents[i]!.id)) {
186
- return shouldNeverHappen('Events must be sorted in ascending order by eventId')
264
+ return unexpectedError(
265
+ `Events must be sorted in ascending order by eventId. Received: [${payload.newEvents.map((e) => `(${e.id.global},${e.id.client})`).join(', ')}]`,
266
+ )
187
267
  }
188
268
  }
189
269
 
270
+ // Validate that incoming events are larger than upstream head
271
+ if (EventId.isGreaterThan(syncState.upstreamHead, payload.newEvents[0]!.id)) {
272
+ return unexpectedError(
273
+ `Incoming events must be greater than upstream head. Expected greater than: [${syncState.upstreamHead.global},${syncState.upstreamHead.client}]. Received: [${payload.newEvents.map((e) => `(${e.id.global},${e.id.client})`).join(', ')}]`,
274
+ )
275
+ }
276
+
190
277
  const newUpstreamHead = payload.newEvents.at(-1)!.id
191
278
 
192
279
  const divergentPendingIndex = findDivergencePoint({
@@ -198,8 +285,8 @@ export const updateSyncState = ({
198
285
  })
199
286
 
200
287
  if (divergentPendingIndex === -1) {
201
- const pendingEventIds = new Set(syncState.pending.map((e) => `${e.id.global},${e.id.local}`))
202
- const newEvents = payload.newEvents.filter((e) => !pendingEventIds.has(`${e.id.global},${e.id.local}`))
288
+ const pendingEventIds = new Set(syncState.pending.map((e) => `${e.id.global},${e.id.client}`))
289
+ const newEvents = payload.newEvents.filter((e) => !pendingEventIds.has(`${e.id.global},${e.id.client}`))
203
290
 
204
291
  // In the case where the incoming events are a subset of the pending events,
205
292
  // we need to split the pending events into two groups:
@@ -225,7 +312,7 @@ export const updateSyncState = ({
225
312
 
226
313
  const seenEventIds = new Set<string>()
227
314
  const pendingAndNewEvents = [...pendingMatching, ...payload.newEvents].filter((event) => {
228
- const eventIdStr = `${event.id.global},${event.id.local}`
315
+ const eventIdStr = `${event.id.global},${event.id.client}`
229
316
  if (seenEventIds.has(eventIdStr)) {
230
317
  return false
231
318
  }
@@ -233,17 +320,17 @@ export const updateSyncState = ({
233
320
  return true
234
321
  })
235
322
 
236
- return {
323
+ return UpdateResultAdvance.make({
237
324
  _tag: 'advance',
238
- newSyncState: {
325
+ newSyncState: new SyncState({
239
326
  pending: pendingRemaining,
240
327
  rollbackTail: trimRollbackTail([...syncState.rollbackTail, ...pendingAndNewEvents]),
241
328
  upstreamHead: newUpstreamHead,
242
329
  localHead: pendingRemaining.at(-1)?.id ?? newUpstreamHead,
243
- },
244
- previousSyncState: syncState,
330
+ }),
245
331
  newEvents,
246
- }
332
+ updateContext,
333
+ })
247
334
  } else {
248
335
  const divergentPending = syncState.pending.slice(divergentPendingIndex)
249
336
  const rebasedPending = rebaseEvents({
@@ -260,24 +347,29 @@ export const updateSyncState = ({
260
347
  ignoreLocalEvents,
261
348
  })
262
349
 
263
- return {
350
+ return UpdateResultRebase.make({
264
351
  _tag: 'rebase',
265
- newSyncState: {
352
+ newSyncState: new SyncState({
266
353
  pending: rebasedPending,
267
354
  rollbackTail: trimRollbackTail([...syncState.rollbackTail, ...payload.newEvents]),
268
355
  upstreamHead: newUpstreamHead,
269
356
  localHead: rebasedPending.at(-1)!.id,
270
- },
271
- previousSyncState: syncState,
357
+ }),
272
358
  newEvents: [...payload.newEvents.slice(divergentNewEventsIndex), ...rebasedPending],
273
359
  eventsToRollback: [...syncState.rollbackTail, ...divergentPending],
274
- }
360
+ updateContext,
361
+ })
275
362
  }
276
363
  }
277
364
 
278
365
  case 'local-push': {
279
366
  if (payload.newEvents.length === 0) {
280
- return { _tag: 'advance', newSyncState: syncState, previousSyncState: syncState, newEvents: [] }
367
+ return UpdateResultAdvance.make({
368
+ _tag: 'advance',
369
+ newSyncState: syncState,
370
+ newEvents: [],
371
+ updateContext,
372
+ })
281
373
  }
282
374
 
283
375
  const newEventsFirst = payload.newEvents.at(0)!
@@ -285,43 +377,29 @@ export const updateSyncState = ({
285
377
 
286
378
  if (invalidEventId) {
287
379
  const expectedMinimumId = EventId.nextPair(syncState.localHead, true).id
288
- return { _tag: 'reject', previousSyncState: syncState, expectedMinimumId }
380
+ return UpdateResultReject.make({
381
+ _tag: 'reject',
382
+ expectedMinimumId,
383
+ updateContext,
384
+ })
289
385
  } else {
290
- return {
386
+ return UpdateResultAdvance.make({
291
387
  _tag: 'advance',
292
- newSyncState: {
388
+ newSyncState: new SyncState({
293
389
  pending: [...syncState.pending, ...payload.newEvents],
294
390
  rollbackTail: syncState.rollbackTail,
295
391
  upstreamHead: syncState.upstreamHead,
296
392
  localHead: payload.newEvents.at(-1)!.id,
297
- },
298
- previousSyncState: syncState,
393
+ }),
299
394
  newEvents: payload.newEvents,
300
- }
395
+ updateContext,
396
+ })
301
397
  }
302
398
  }
303
399
 
304
- // case 'upstream-trim-rollback-tail': {
305
- // // Find the index of the new rollback start in the rollback tail
306
- // const startIndex = syncState.rollbackTail.findIndex((event) => eventIdsEqual(event.id, payload.trimRollbackUntil))
307
- // if (startIndex === -1) {
308
- // return shouldNeverHappen('New rollback start event not found in rollback tail')
309
- // }
310
-
311
- // // Keep only the events from the start index onwards
312
- // const newRollbackTail = syncState.rollbackTail.slice(startIndex)
313
-
314
- // return {
315
- // _tag: 'advance',
316
- // syncState: {
317
- // pending: syncState.pending,
318
- // rollbackTail: newRollbackTail,
319
- // upstreamHead: syncState.upstreamHead,
320
- // localHead: syncState.localHead,
321
- // },
322
- // newEvents: [],
323
- // }
324
- // }
400
+ default: {
401
+ casesHandled(payload)
402
+ }
325
403
  }
326
404
  }
327
405
 
@@ -383,3 +461,12 @@ const rebaseEvents = ({
383
461
  return newEvent
384
462
  })
385
463
  }
464
+
465
+ /**
466
+ * TODO: Implement this
467
+ *
468
+ * In certain scenarios e.g. when the client session has a queue of upstream update results,
469
+ * it could make sense to "flatten" update results into a single update result which the client session
470
+ * can process more efficiently which avoids push-threshing
471
+ */
472
+ const _flattenUpdateResults = (_updateResults: ReadonlyArray<UpdateResult>) => {}
@@ -1,17 +1,20 @@
1
1
  import { Effect } from '@livestore/utils/effect'
2
2
 
3
- import type { MutationEvent } from '../schema/mod.js'
3
+ import type { EventId, MutationEvent } from '../schema/mod.js'
4
4
  import { InvalidPushError } from './sync.js'
5
5
 
6
6
  // TODO proper batch validation
7
- export const validatePushPayload = (batch: ReadonlyArray<MutationEvent.AnyEncoded>, currentEventId: number) =>
7
+ export const validatePushPayload = (
8
+ batch: ReadonlyArray<MutationEvent.AnyEncodedGlobal>,
9
+ currentEventId: EventId.GlobalEventId,
10
+ ) =>
8
11
  Effect.gen(function* () {
9
- if (batch[0]!.id.global <= currentEventId) {
12
+ if (batch[0]!.id <= currentEventId) {
10
13
  return yield* InvalidPushError.make({
11
14
  reason: {
12
15
  _tag: 'ServerAhead',
13
16
  minimumExpectedId: currentEventId + 1,
14
- providedId: batch[0]!.id.global,
17
+ providedId: batch[0]!.id,
15
18
  },
16
19
  })
17
20
  }
package/src/version.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  // import packageJson from '../package.json' with { type: 'json' }
3
3
  // export const liveStoreVersion = packageJson.version
4
4
 
5
- export const liveStoreVersion = '0.3.0-dev.0' as const
5
+ export const liveStoreVersion = '0.3.0-dev.21' as const
6
6
 
7
7
  /**
8
8
  * This version number is incremented whenever the internal storage format changes in a breaking way.
package/tmp/pack.tgz ADDED
Binary file
package/tsconfig.json CHANGED
@@ -7,5 +7,5 @@
7
7
  "tsBuildInfoFile": "./dist/.tsbuildinfo"
8
8
  },
9
9
  "include": ["./src"],
10
- "references": [{ "path": "../db-schema" }, { "path": "../utils" }]
10
+ "references": [{ "path": "../utils" }]
11
11
  }
@@ -1,12 +0,0 @@
1
- import type { Effect, PubSub } from '@livestore/utils/effect';
2
- import type * as Devtools from './devtools-messages.js';
3
- export type PrepareDevtoolsBridge = {
4
- /** Messages coming from the app host (usually responses to requests) */
5
- responsePubSub: PubSub.PubSub<Devtools.MessageFromAppLeader | Devtools.MessageFromAppClientSession>;
6
- sendToAppHost: (msg: Devtools.MessageToAppLeader | Devtools.MessageToAppClientSession) => Effect.Effect<void>;
7
- appHostId: string;
8
- copyToClipboard: (text: string) => Effect.Effect<void>;
9
- sendEscapeKey?: Effect.Effect<void>;
10
- isLeader: boolean;
11
- };
12
- //# sourceMappingURL=devtools-bridge.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"devtools-bridge.d.ts","sourceRoot":"","sources":["../../src/devtools/devtools-bridge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAE7D,OAAO,KAAK,KAAK,QAAQ,MAAM,wBAAwB,CAAA;AAEvD,MAAM,MAAM,qBAAqB,GAAG;IAClC,wEAAwE;IACxE,cAAc,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,oBAAoB,GAAG,QAAQ,CAAC,2BAA2B,CAAC,CAAA;IACnG,aAAa,EAAE,CAAC,GAAG,EAAE,QAAQ,CAAC,kBAAkB,GAAG,QAAQ,CAAC,yBAAyB,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IAC7G,SAAS,EAAE,MAAM,CAAA;IACjB,eAAe,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IACtD,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IACnC,QAAQ,EAAE,OAAO,CAAA;CAClB,CAAA"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=devtools-bridge.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"devtools-bridge.js","sourceRoot":"","sources":["../../src/devtools/devtools-bridge.ts"],"names":[],"mappings":""}
@@ -1,47 +0,0 @@
1
- import type { Scope } from '@livestore/utils/effect';
2
- import { Effect } from '@livestore/utils/effect';
3
- import type { SynchronousDatabase } from '../adapter-types.js';
4
- import { UnexpectedError } from '../adapter-types.js';
5
- import type { LiveStoreSchema } from '../schema/mod.js';
6
- import type { InitialBlockingSyncContext, SyncProcessor } from './types.js';
7
- /**
8
- * The general idea of the sync processor is to "follow the sync state"
9
- * and apply/rollback mutations as needed to the read model and mutation log.
10
- * The leader sync processor is also responsible for
11
- * - broadcasting mutations to client sessions via the pull queues.
12
- * - pushing mutations to the sync backend
13
- *
14
- * In the leader sync processor, pulling always has precedence over pushing.
15
- *
16
- * External events:
17
- * - Mutation pushed from client session
18
- * - Mutation pushed from devtools (via pushPartial)
19
- * - Mutation pulled from sync backend
20
- *
21
- * The machine can be in the following states:
22
- * - in-sync: fully synced with remote, now idling
23
- * - applying-syncstate-advance (with pointer to current progress in case of rebase interrupt)
24
- *
25
- * Transitions:
26
- * - in-sync -> applying-syncstate-advance
27
- * - applying-syncstate-advance -> in-sync
28
- * - applying-syncstate-advance -> applying-syncstate-advance (need to interrupt previous operation)
29
- *
30
- * Queuing vs interrupting behaviour:
31
- * - Operations caused by pull can never be interrupted
32
- * - Incoming pull can interrupt current push
33
- * - Incoming pull needs to wait to previous pull to finish
34
- * - Incoming push needs to wait to previous push to finish
35
- *
36
- * Backend pushing:
37
- * - continously push to backend
38
- * - only interrupted and restarted on rebase
39
- */
40
- export declare const makeLeaderSyncProcessor: ({ schema, dbMissing, dbLog, initialBlockingSyncContext, }: {
41
- schema: LiveStoreSchema;
42
- /** Only used to know whether we can safely query dbLog during setup execution */
43
- dbMissing: boolean;
44
- dbLog: SynchronousDatabase;
45
- initialBlockingSyncContext: InitialBlockingSyncContext;
46
- }) => Effect.Effect<SyncProcessor, UnexpectedError, Scope.Scope>;
47
- //# sourceMappingURL=leader-sync-processor.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"leader-sync-processor.d.ts","sourceRoot":"","sources":["../../src/leader-thread/leader-sync-processor.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAc,KAAK,EAAE,MAAM,yBAAyB,CAAA;AAChE,OAAO,EAGL,MAAM,EAUP,MAAM,yBAAyB,CAAA;AAGhC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAA;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AACrD,OAAO,KAAK,EAAE,eAAe,EAA2B,MAAM,kBAAkB,CAAA;AAehF,OAAO,KAAK,EAAE,0BAA0B,EAAmB,aAAa,EAAE,MAAM,YAAY,CAAA;AAuB5F;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,eAAO,MAAM,uBAAuB,8DAKjC;IACD,MAAM,EAAE,eAAe,CAAA;IACvB,iFAAiF;IACjF,SAAS,EAAE,OAAO,CAAA;IAClB,KAAK,EAAE,mBAAmB,CAAA;IAC1B,0BAA0B,EAAE,0BAA0B,CAAA;CACvD,KAAG,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,eAAe,EAAE,KAAK,CAAC,KAAK,CAoOzD,CAAA"}