@livestore/common 0.2.0-dev.2 → 0.3.0-dev.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (244) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/__tests__/fixture.d.ts +163 -1
  3. package/dist/__tests__/fixture.d.ts.map +1 -1
  4. package/dist/__tests__/fixture.js +3 -1
  5. package/dist/__tests__/fixture.js.map +1 -1
  6. package/dist/adapter-types.d.ts +53 -38
  7. package/dist/adapter-types.d.ts.map +1 -1
  8. package/dist/adapter-types.js +5 -7
  9. package/dist/adapter-types.js.map +1 -1
  10. package/dist/bounded-collections.d.ts +2 -2
  11. package/dist/bounded-collections.d.ts.map +1 -1
  12. package/dist/debug-info.d.ts +13 -13
  13. package/dist/derived-mutations.d.ts +1 -1
  14. package/dist/derived-mutations.d.ts.map +1 -1
  15. package/dist/devtools/devtools-bridge.d.ts +2 -2
  16. package/dist/devtools/devtools-bridge.d.ts.map +1 -1
  17. package/dist/devtools/devtools-messages.d.ts +84 -196
  18. package/dist/devtools/devtools-messages.d.ts.map +1 -1
  19. package/dist/devtools/devtools-messages.js +55 -61
  20. package/dist/devtools/devtools-messages.js.map +1 -1
  21. package/dist/devtools/index.d.ts.map +1 -1
  22. package/dist/devtools/index.js +1 -2
  23. package/dist/devtools/index.js.map +1 -1
  24. package/dist/index.d.ts +2 -1
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +2 -1
  27. package/dist/index.js.map +1 -1
  28. package/dist/init-singleton-tables.d.ts +1 -1
  29. package/dist/init-singleton-tables.d.ts.map +1 -1
  30. package/dist/leader-thread/apply-mutation.d.ts +8 -0
  31. package/dist/leader-thread/apply-mutation.d.ts.map +1 -0
  32. package/dist/leader-thread/apply-mutation.js +95 -0
  33. package/dist/leader-thread/apply-mutation.js.map +1 -0
  34. package/dist/leader-thread/connection.d.ts +11 -0
  35. package/dist/leader-thread/connection.d.ts.map +1 -0
  36. package/dist/leader-thread/connection.js +44 -0
  37. package/dist/leader-thread/connection.js.map +1 -0
  38. package/dist/leader-thread/leader-sync-processor.d.ts +47 -0
  39. package/dist/leader-thread/leader-sync-processor.d.ts.map +1 -0
  40. package/dist/leader-thread/leader-sync-processor.js +422 -0
  41. package/dist/leader-thread/leader-sync-processor.js.map +1 -0
  42. package/dist/leader-thread/leader-worker-devtools.d.ts +6 -0
  43. package/dist/leader-thread/leader-worker-devtools.d.ts.map +1 -0
  44. package/dist/leader-thread/leader-worker-devtools.js +216 -0
  45. package/dist/leader-thread/leader-worker-devtools.js.map +1 -0
  46. package/dist/leader-thread/make-leader-thread-layer.d.ts +20 -0
  47. package/dist/leader-thread/make-leader-thread-layer.d.ts.map +1 -0
  48. package/dist/leader-thread/make-leader-thread-layer.js +106 -0
  49. package/dist/leader-thread/make-leader-thread-layer.js.map +1 -0
  50. package/dist/leader-thread/mod.d.ts +7 -0
  51. package/dist/leader-thread/mod.d.ts.map +1 -0
  52. package/dist/leader-thread/mod.js +7 -0
  53. package/dist/leader-thread/mod.js.map +1 -0
  54. package/dist/leader-thread/mutationlog.d.ts +23 -0
  55. package/dist/leader-thread/mutationlog.d.ts.map +1 -0
  56. package/dist/leader-thread/mutationlog.js +27 -0
  57. package/dist/leader-thread/mutationlog.js.map +1 -0
  58. package/dist/leader-thread/pull-queue-set.d.ts +7 -0
  59. package/dist/leader-thread/pull-queue-set.d.ts.map +1 -0
  60. package/dist/leader-thread/pull-queue-set.js +39 -0
  61. package/dist/leader-thread/pull-queue-set.js.map +1 -0
  62. package/dist/leader-thread/recreate-db.d.ts +7 -0
  63. package/dist/leader-thread/recreate-db.d.ts.map +1 -0
  64. package/dist/leader-thread/recreate-db.js +69 -0
  65. package/dist/leader-thread/recreate-db.js.map +1 -0
  66. package/dist/leader-thread/shutdown-channel.d.ts +15 -0
  67. package/dist/leader-thread/shutdown-channel.d.ts.map +1 -0
  68. package/dist/leader-thread/shutdown-channel.js +7 -0
  69. package/dist/leader-thread/shutdown-channel.js.map +1 -0
  70. package/dist/leader-thread/types.d.ts +87 -0
  71. package/dist/leader-thread/types.d.ts.map +1 -0
  72. package/dist/leader-thread/types.js +11 -0
  73. package/dist/leader-thread/types.js.map +1 -0
  74. package/dist/mutation.d.ts +3 -4
  75. package/dist/mutation.d.ts.map +1 -1
  76. package/dist/mutation.js +0 -14
  77. package/dist/mutation.js.map +1 -1
  78. package/dist/otel.d.ts +7 -0
  79. package/dist/otel.d.ts.map +1 -0
  80. package/dist/otel.js +11 -0
  81. package/dist/otel.js.map +1 -0
  82. package/dist/query-builder/api.d.ts +2 -2
  83. package/dist/query-builder/api.d.ts.map +1 -1
  84. package/dist/query-builder/api.js.map +1 -1
  85. package/dist/query-builder/impl.d.ts +1 -1
  86. package/dist/query-builder/impl.d.ts.map +1 -1
  87. package/dist/query-builder/impl.js +23 -5
  88. package/dist/query-builder/impl.js.map +1 -1
  89. package/dist/query-builder/impl.test.js +30 -1
  90. package/dist/query-builder/impl.test.js.map +1 -1
  91. package/dist/query-info.d.ts +1 -1
  92. package/dist/query-info.d.ts.map +1 -1
  93. package/dist/rehydrate-from-mutationlog.d.ts +1 -1
  94. package/dist/rehydrate-from-mutationlog.d.ts.map +1 -1
  95. package/dist/rehydrate-from-mutationlog.js +6 -6
  96. package/dist/rehydrate-from-mutationlog.js.map +1 -1
  97. package/dist/schema/EventId.d.ts +37 -0
  98. package/dist/schema/EventId.d.ts.map +1 -0
  99. package/dist/schema/EventId.js +30 -0
  100. package/dist/schema/EventId.js.map +1 -0
  101. package/dist/schema/MutationEvent.d.ts +191 -0
  102. package/dist/schema/MutationEvent.d.ts.map +1 -0
  103. package/dist/schema/MutationEvent.js +56 -0
  104. package/dist/schema/MutationEvent.js.map +1 -0
  105. package/dist/schema/mod.d.ts +8 -0
  106. package/dist/schema/mod.d.ts.map +1 -0
  107. package/dist/schema/mod.js +8 -0
  108. package/dist/schema/mod.js.map +1 -0
  109. package/dist/schema/mutations.d.ts +3 -123
  110. package/dist/schema/mutations.d.ts.map +1 -1
  111. package/dist/schema/mutations.js +0 -26
  112. package/dist/schema/mutations.js.map +1 -1
  113. package/dist/schema/{index.d.ts → schema.d.ts} +1 -5
  114. package/dist/schema/schema.d.ts.map +1 -0
  115. package/dist/schema/{index.js → schema.js} +1 -5
  116. package/dist/schema/schema.js.map +1 -0
  117. package/dist/schema/system-tables.d.ts +55 -29
  118. package/dist/schema/system-tables.d.ts.map +1 -1
  119. package/dist/schema/system-tables.js +10 -5
  120. package/dist/schema/system-tables.js.map +1 -1
  121. package/dist/schema-management/migrations.d.ts +1 -1
  122. package/dist/schema-management/migrations.d.ts.map +1 -1
  123. package/dist/schema-management/migrations.js +6 -1
  124. package/dist/schema-management/migrations.js.map +1 -1
  125. package/dist/schema-management/validate-mutation-defs.d.ts +1 -1
  126. package/dist/schema-management/validate-mutation-defs.d.ts.map +1 -1
  127. package/dist/sync/client-session-sync-processor.d.ts +45 -0
  128. package/dist/sync/client-session-sync-processor.d.ts.map +1 -0
  129. package/dist/sync/client-session-sync-processor.js +131 -0
  130. package/dist/sync/client-session-sync-processor.js.map +1 -0
  131. package/dist/sync/index.d.ts +2 -0
  132. package/dist/sync/index.d.ts.map +1 -1
  133. package/dist/sync/index.js +2 -0
  134. package/dist/sync/index.js.map +1 -1
  135. package/dist/sync/next/compact-events.d.ts +1 -1
  136. package/dist/sync/next/compact-events.d.ts.map +1 -1
  137. package/dist/sync/next/compact-events.js +2 -1
  138. package/dist/sync/next/compact-events.js.map +1 -1
  139. package/dist/sync/next/facts.d.ts +5 -5
  140. package/dist/sync/next/facts.d.ts.map +1 -1
  141. package/dist/sync/next/facts.js +1 -1
  142. package/dist/sync/next/facts.js.map +1 -1
  143. package/dist/sync/next/history-dag-common.d.ts +30 -0
  144. package/dist/sync/next/history-dag-common.d.ts.map +1 -0
  145. package/dist/sync/next/history-dag-common.js +20 -0
  146. package/dist/sync/next/history-dag-common.js.map +1 -0
  147. package/dist/sync/next/history-dag.d.ts +4 -27
  148. package/dist/sync/next/history-dag.d.ts.map +1 -1
  149. package/dist/sync/next/history-dag.js +1 -19
  150. package/dist/sync/next/history-dag.js.map +1 -1
  151. package/dist/sync/next/mod.d.ts +1 -0
  152. package/dist/sync/next/mod.d.ts.map +1 -1
  153. package/dist/sync/next/mod.js +1 -0
  154. package/dist/sync/next/mod.js.map +1 -1
  155. package/dist/sync/next/rebase-events.d.ts +3 -2
  156. package/dist/sync/next/rebase-events.d.ts.map +1 -1
  157. package/dist/sync/next/rebase-events.js.map +1 -1
  158. package/dist/sync/next/test/compact-events.test.d.ts.map +1 -1
  159. package/dist/sync/next/test/compact-events.test.js +2 -1
  160. package/dist/sync/next/test/compact-events.test.js.map +1 -1
  161. package/dist/sync/next/test/mutation-fixtures.d.ts +1 -1
  162. package/dist/sync/next/test/mutation-fixtures.d.ts.map +1 -1
  163. package/dist/sync/next/test/mutation-fixtures.js +4 -3
  164. package/dist/sync/next/test/mutation-fixtures.js.map +1 -1
  165. package/dist/sync/sync.d.ts +33 -12
  166. package/dist/sync/sync.d.ts.map +1 -1
  167. package/dist/sync/sync.js +10 -1
  168. package/dist/sync/sync.js.map +1 -1
  169. package/dist/sync/syncstate.d.ts +123 -0
  170. package/dist/sync/syncstate.d.ts.map +1 -0
  171. package/dist/sync/syncstate.js +248 -0
  172. package/dist/sync/syncstate.js.map +1 -0
  173. package/dist/sync/syncstate.test.d.ts +2 -0
  174. package/dist/sync/syncstate.test.d.ts.map +1 -0
  175. package/dist/sync/syncstate.test.js +399 -0
  176. package/dist/sync/syncstate.test.js.map +1 -0
  177. package/dist/sync/validate-push-payload.d.ts +5 -0
  178. package/dist/sync/validate-push-payload.d.ts.map +1 -0
  179. package/dist/sync/validate-push-payload.js +15 -0
  180. package/dist/sync/validate-push-payload.js.map +1 -0
  181. package/dist/util.d.ts +2 -2
  182. package/dist/util.d.ts.map +1 -1
  183. package/dist/version.d.ts +2 -2
  184. package/dist/version.d.ts.map +1 -1
  185. package/dist/version.js +2 -2
  186. package/dist/version.js.map +1 -1
  187. package/package.json +13 -6
  188. package/src/__tests__/fixture.ts +5 -1
  189. package/src/adapter-types.ts +60 -34
  190. package/src/derived-mutations.test.ts +1 -1
  191. package/src/derived-mutations.ts +1 -1
  192. package/src/devtools/devtools-bridge.ts +2 -2
  193. package/src/devtools/devtools-messages.ts +70 -74
  194. package/src/devtools/index.ts +1 -2
  195. package/src/index.ts +2 -1
  196. package/src/init-singleton-tables.ts +1 -1
  197. package/src/leader-thread/apply-mutation.ts +143 -0
  198. package/src/leader-thread/connection.ts +67 -0
  199. package/src/leader-thread/leader-sync-processor.ts +666 -0
  200. package/src/leader-thread/leader-worker-devtools.ts +358 -0
  201. package/src/leader-thread/make-leader-thread-layer.ts +192 -0
  202. package/src/leader-thread/mod.ts +6 -0
  203. package/src/leader-thread/mutationlog.ts +42 -0
  204. package/src/leader-thread/pull-queue-set.ts +58 -0
  205. package/src/leader-thread/recreate-db.ts +109 -0
  206. package/src/leader-thread/shutdown-channel.ts +13 -0
  207. package/src/leader-thread/types.ts +129 -0
  208. package/src/mutation.ts +3 -21
  209. package/src/otel.ts +20 -0
  210. package/src/query-builder/api.ts +3 -2
  211. package/src/query-builder/impl.test.ts +35 -1
  212. package/src/query-builder/impl.ts +23 -6
  213. package/src/query-info.ts +1 -1
  214. package/src/rehydrate-from-mutationlog.ts +7 -11
  215. package/src/schema/EventId.ts +46 -0
  216. package/src/schema/MutationEvent.ts +161 -0
  217. package/src/schema/mod.ts +7 -0
  218. package/src/schema/mutations.ts +5 -126
  219. package/src/schema/{index.ts → schema.ts} +0 -5
  220. package/src/schema/system-tables.ts +18 -5
  221. package/src/schema-management/migrations.ts +9 -2
  222. package/src/schema-management/validate-mutation-defs.ts +1 -1
  223. package/src/sync/client-session-sync-processor.ts +207 -0
  224. package/src/sync/index.ts +2 -0
  225. package/src/sync/next/compact-events.ts +3 -2
  226. package/src/sync/next/facts.ts +11 -5
  227. package/src/sync/next/history-dag-common.ts +44 -0
  228. package/src/sync/next/history-dag.ts +3 -45
  229. package/src/sync/next/mod.ts +1 -0
  230. package/src/sync/next/rebase-events.ts +6 -5
  231. package/src/sync/next/test/compact-events.test.ts +3 -2
  232. package/src/sync/next/test/mutation-fixtures.ts +7 -6
  233. package/src/sync/sync.ts +32 -12
  234. package/src/sync/syncstate.test.ts +464 -0
  235. package/src/sync/syncstate.ts +385 -0
  236. package/src/sync/validate-push-payload.ts +18 -0
  237. package/src/version.ts +2 -2
  238. package/dist/schema/index.d.ts.map +0 -1
  239. package/dist/schema/index.js.map +0 -1
  240. package/dist/sync/next-mutation-event-id-pair.d.ts +0 -14
  241. package/dist/sync/next-mutation-event-id-pair.d.ts.map +0 -1
  242. package/dist/sync/next-mutation-event-id-pair.js +0 -13
  243. package/dist/sync/next-mutation-event-id-pair.js.map +0 -1
  244. package/src/sync/next-mutation-event-id-pair.ts +0 -20
@@ -0,0 +1,385 @@
1
+ import { shouldNeverHappen } from '@livestore/utils'
2
+ import { ReadonlyArray, Schema } from '@livestore/utils/effect'
3
+
4
+ import * as EventId from '../schema/EventId.js'
5
+ import * as MutationEvent from '../schema/MutationEvent.js'
6
+
7
+ /**
8
+ * SyncState represents the current sync state of a sync node relative to an upstream node.
9
+ * Events flow from local to upstream, with each state maintaining its own event head.
10
+ *
11
+ * Event Chain Structure:
12
+ * ```
13
+ * +-------------------------+------------------------+
14
+ * | ROLLBACK TAIL | PENDING EVENTS |
15
+ * +-------------------------+------------------------+
16
+ * ▼ ▼
17
+ * Upstream Head Local Head
18
+ * Example: (0,0), (0,1), (1,0) (1,1), (1,2), (2,0)
19
+ * ```
20
+ *
21
+ * State:
22
+ * - **Pending Events**: Events awaiting acknowledgment from the upstream.
23
+ * - Can be confirmed or rejected by the upstream.
24
+ * - Subject to rebase if rejected.
25
+ * - **Rollback Tail**: Events that are kept around temporarily for potential rollback until confirmed by upstream.
26
+ *
27
+ * Payloads:
28
+ * - `PayloadUpstreamRebase`: Upstream has performed a rebase, so downstream must roll back to the specified event
29
+ * and rebase the pending events on top of the new events.
30
+ * - `PayloadUpstreamAdvance`: Upstream has advanced, so downstream must rebase the pending events on top of the new events.
31
+ * - `PayloadUpstreamTrimRollbackTail`: Upstream has advanced, so downstream can trim the rollback tail.
32
+ * - `PayloadLocalPush`: Local push payload
33
+ *
34
+ * Invariants:
35
+ * 1. **Chain Continuity**: Each event must reference its immediate parent.
36
+ * 2. **Head Ordering**: Upstream Head ≤ Local Head.
37
+ * 3. **ID Sequence**: Must follow the pattern (1,0)→(1,1)→(1,2)→(2,0).
38
+ *
39
+ * The `updateSyncState` function processes updates to the sync state based on incoming payloads,
40
+ * handling cases such as upstream rebase, advance, local push, and rollback tail trimming.
41
+ */
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({
50
+ pending: Schema.Array(MutationEvent.EncodedWithMeta),
51
+ rollbackTail: Schema.Array(MutationEvent.EncodedWithMeta),
52
+ upstreamHead: EventId.EventId,
53
+ localHead: EventId.EventId,
54
+ }).annotations({ title: 'SyncState' })
55
+
56
+ export class PayloadUpstreamRebase extends Schema.TaggedStruct('upstream-rebase', {
57
+ /** Rollback until this event in the rollback tail (inclusive). Starting from the end of the rollback tail. */
58
+ rollbackUntil: EventId.EventId,
59
+ newEvents: Schema.Array(MutationEvent.EncodedWithMeta),
60
+ /** Trim rollback tail up to this event (inclusive). */
61
+ trimRollbackUntil: Schema.optional(EventId.EventId),
62
+ }) {}
63
+
64
+ export class PayloadUpstreamAdvance extends Schema.TaggedStruct('upstream-advance', {
65
+ newEvents: Schema.Array(MutationEvent.EncodedWithMeta),
66
+ /** Trim rollback tail up to this event (inclusive). */
67
+ trimRollbackUntil: Schema.optional(EventId.EventId),
68
+ }) {}
69
+
70
+ export class PayloadLocalPush extends Schema.TaggedStruct('local-push', {
71
+ newEvents: Schema.Array(MutationEvent.EncodedWithMeta),
72
+ }) {}
73
+
74
+ export class Payload extends Schema.Union(PayloadUpstreamRebase, PayloadUpstreamAdvance, PayloadLocalPush) {}
75
+
76
+ export const PayloadUpstream = Schema.Union(PayloadUpstreamRebase, PayloadUpstreamAdvance)
77
+
78
+ export type PayloadUpstream = typeof PayloadUpstream.Type
79
+
80
+ export type UpdateResultAdvance = {
81
+ _tag: 'advance'
82
+ newSyncState: SyncState
83
+ previousSyncState: SyncState
84
+ /** Events which weren't pending before the update */
85
+ newEvents: ReadonlyArray<MutationEvent.EncodedWithMeta>
86
+ }
87
+
88
+ export type UpdateResultRebase = {
89
+ _tag: 'rebase'
90
+ newSyncState: SyncState
91
+ previousSyncState: SyncState
92
+ /** Events which weren't pending before the update */
93
+ newEvents: ReadonlyArray<MutationEvent.EncodedWithMeta>
94
+ eventsToRollback: ReadonlyArray<MutationEvent.EncodedWithMeta>
95
+ }
96
+
97
+ export type UpdateResultReject = {
98
+ _tag: 'reject'
99
+ previousSyncState: SyncState
100
+ /** The minimum id that the new events must have */
101
+ expectedMinimumId: EventId.EventId
102
+ }
103
+
104
+ export type UpdateResult = UpdateResultAdvance | UpdateResultRebase | UpdateResultReject
105
+
106
+ export const updateSyncState = ({
107
+ syncState,
108
+ payload,
109
+ isLocalEvent,
110
+ isEqualEvent,
111
+ ignoreLocalEvents = false,
112
+ }: {
113
+ syncState: SyncState
114
+ payload: typeof Payload.Type
115
+ isLocalEvent: (event: MutationEvent.EncodedWithMeta) => boolean
116
+ isEqualEvent: (a: MutationEvent.EncodedWithMeta, b: MutationEvent.EncodedWithMeta) => boolean
117
+ /** This is used in the leader which should ignore local events when receiving an upstream-advance payload */
118
+ ignoreLocalEvents?: boolean
119
+ }): UpdateResult => {
120
+ const trimRollbackTail = (
121
+ rollbackTail: ReadonlyArray<MutationEvent.EncodedWithMeta>,
122
+ ): ReadonlyArray<MutationEvent.EncodedWithMeta> => {
123
+ const trimRollbackUntil = payload._tag === 'local-push' ? undefined : payload.trimRollbackUntil
124
+ if (trimRollbackUntil === undefined) return rollbackTail
125
+ const index = rollbackTail.findIndex((event) => EventId.isEqual(event.id, trimRollbackUntil))
126
+ if (index === -1) return []
127
+ return rollbackTail.slice(index + 1)
128
+ }
129
+
130
+ switch (payload._tag) {
131
+ case 'upstream-rebase': {
132
+ // Find the index of the rollback event in the rollback tail
133
+ const rollbackIndex = syncState.rollbackTail.findIndex((event) =>
134
+ EventId.isEqual(event.id, payload.rollbackUntil),
135
+ )
136
+ 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(', ')}]`,
139
+ )
140
+ }
141
+
142
+ const eventsToRollback = [...syncState.rollbackTail.slice(rollbackIndex), ...syncState.pending]
143
+
144
+ // Get the last new event's ID as the new upstream head
145
+ const newUpstreamHead = payload.newEvents.at(-1)?.id ?? syncState.upstreamHead
146
+
147
+ // Rebase pending events on top of the new events
148
+ const rebasedPending = rebaseEvents({
149
+ events: syncState.pending,
150
+ baseEventId: newUpstreamHead,
151
+ isLocalEvent,
152
+ })
153
+
154
+ return {
155
+ _tag: 'rebase',
156
+ newSyncState: {
157
+ pending: rebasedPending,
158
+ rollbackTail: trimRollbackTail([...syncState.rollbackTail.slice(0, rollbackIndex), ...payload.newEvents]),
159
+ upstreamHead: newUpstreamHead,
160
+ localHead: rebasedPending.at(-1)?.id ?? newUpstreamHead,
161
+ },
162
+ previousSyncState: syncState,
163
+ newEvents: payload.newEvents,
164
+ eventsToRollback,
165
+ }
166
+ }
167
+
168
+ case 'upstream-advance': {
169
+ if (payload.newEvents.length === 0) {
170
+ return {
171
+ _tag: 'advance',
172
+ newSyncState: {
173
+ pending: syncState.pending,
174
+ rollbackTail: trimRollbackTail(syncState.rollbackTail),
175
+ upstreamHead: syncState.upstreamHead,
176
+ localHead: syncState.localHead,
177
+ },
178
+ previousSyncState: syncState,
179
+ newEvents: [],
180
+ }
181
+ }
182
+
183
+ // Validate that newEvents are sorted in ascending order by eventId
184
+ for (let i = 1; i < payload.newEvents.length; i++) {
185
+ if (EventId.isGreaterThan(payload.newEvents[i - 1]!.id, payload.newEvents[i]!.id)) {
186
+ return shouldNeverHappen('Events must be sorted in ascending order by eventId')
187
+ }
188
+ }
189
+
190
+ const newUpstreamHead = payload.newEvents.at(-1)!.id
191
+
192
+ const divergentPendingIndex = findDivergencePoint({
193
+ existingEvents: syncState.pending,
194
+ incomingEvents: payload.newEvents,
195
+ isEqualEvent,
196
+ isLocalEvent,
197
+ ignoreLocalEvents,
198
+ })
199
+
200
+ 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}`))
203
+
204
+ // In the case where the incoming events are a subset of the pending events,
205
+ // we need to split the pending events into two groups:
206
+ // - pendingMatching: The pending events up to point where they match the incoming events
207
+ // - pendingRemaining: The pending events after the point where they match the incoming events
208
+ // The `localIndexOffset` is used to account for the local events that are being ignored
209
+ let localIndexOffset = 0
210
+ const [pendingMatching, pendingRemaining] = ReadonlyArray.splitWhere(
211
+ syncState.pending,
212
+ (pendingEvent, index) => {
213
+ if (ignoreLocalEvents && isLocalEvent(pendingEvent)) {
214
+ localIndexOffset++
215
+ return false
216
+ }
217
+
218
+ const newEvent = payload.newEvents.at(index - localIndexOffset)
219
+ if (!newEvent) {
220
+ return true
221
+ }
222
+ return isEqualEvent(pendingEvent, newEvent) === false
223
+ },
224
+ )
225
+
226
+ const seenEventIds = new Set<string>()
227
+ const pendingAndNewEvents = [...pendingMatching, ...payload.newEvents].filter((event) => {
228
+ const eventIdStr = `${event.id.global},${event.id.local}`
229
+ if (seenEventIds.has(eventIdStr)) {
230
+ return false
231
+ }
232
+ seenEventIds.add(eventIdStr)
233
+ return true
234
+ })
235
+
236
+ return {
237
+ _tag: 'advance',
238
+ newSyncState: {
239
+ pending: pendingRemaining,
240
+ rollbackTail: trimRollbackTail([...syncState.rollbackTail, ...pendingAndNewEvents]),
241
+ upstreamHead: newUpstreamHead,
242
+ localHead: pendingRemaining.at(-1)?.id ?? newUpstreamHead,
243
+ },
244
+ previousSyncState: syncState,
245
+ newEvents,
246
+ }
247
+ } else {
248
+ const divergentPending = syncState.pending.slice(divergentPendingIndex)
249
+ const rebasedPending = rebaseEvents({
250
+ events: divergentPending,
251
+ baseEventId: newUpstreamHead,
252
+ isLocalEvent,
253
+ })
254
+
255
+ const divergentNewEventsIndex = findDivergencePoint({
256
+ existingEvents: payload.newEvents,
257
+ incomingEvents: syncState.pending,
258
+ isEqualEvent,
259
+ isLocalEvent,
260
+ ignoreLocalEvents,
261
+ })
262
+
263
+ return {
264
+ _tag: 'rebase',
265
+ newSyncState: {
266
+ pending: rebasedPending,
267
+ rollbackTail: trimRollbackTail([...syncState.rollbackTail, ...payload.newEvents]),
268
+ upstreamHead: newUpstreamHead,
269
+ localHead: rebasedPending.at(-1)!.id,
270
+ },
271
+ previousSyncState: syncState,
272
+ newEvents: [...payload.newEvents.slice(divergentNewEventsIndex), ...rebasedPending],
273
+ eventsToRollback: [...syncState.rollbackTail, ...divergentPending],
274
+ }
275
+ }
276
+ }
277
+
278
+ case 'local-push': {
279
+ if (payload.newEvents.length === 0) {
280
+ return { _tag: 'advance', newSyncState: syncState, previousSyncState: syncState, newEvents: [] }
281
+ }
282
+
283
+ const newEventsFirst = payload.newEvents.at(0)!
284
+ const invalidEventId = EventId.isGreaterThan(newEventsFirst.id, syncState.localHead) === false
285
+
286
+ if (invalidEventId) {
287
+ const expectedMinimumId = EventId.nextPair(syncState.localHead, true).id
288
+ return { _tag: 'reject', previousSyncState: syncState, expectedMinimumId }
289
+ } else {
290
+ return {
291
+ _tag: 'advance',
292
+ newSyncState: {
293
+ pending: [...syncState.pending, ...payload.newEvents],
294
+ rollbackTail: syncState.rollbackTail,
295
+ upstreamHead: syncState.upstreamHead,
296
+ localHead: payload.newEvents.at(-1)!.id,
297
+ },
298
+ previousSyncState: syncState,
299
+ newEvents: payload.newEvents,
300
+ }
301
+ }
302
+ }
303
+
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
+ // }
325
+ }
326
+ }
327
+
328
+ /**
329
+ * Gets the index relative to `existingEvents` where the divergence point is
330
+ * by comparing each event in `existingEvents` to the corresponding event in `incomingEvents`
331
+ */
332
+ const findDivergencePoint = ({
333
+ existingEvents,
334
+ incomingEvents,
335
+ isEqualEvent,
336
+ isLocalEvent,
337
+ ignoreLocalEvents,
338
+ }: {
339
+ existingEvents: ReadonlyArray<MutationEvent.EncodedWithMeta>
340
+ incomingEvents: ReadonlyArray<MutationEvent.EncodedWithMeta>
341
+ isEqualEvent: (a: MutationEvent.EncodedWithMeta, b: MutationEvent.EncodedWithMeta) => boolean
342
+ isLocalEvent: (event: MutationEvent.EncodedWithMeta) => boolean
343
+ ignoreLocalEvents: boolean
344
+ }): number => {
345
+ if (ignoreLocalEvents) {
346
+ const filteredExistingEvents = existingEvents.filter((event) => !isLocalEvent(event))
347
+ const divergencePointWithoutLocalEvents = findDivergencePoint({
348
+ existingEvents: filteredExistingEvents,
349
+ incomingEvents,
350
+ isEqualEvent,
351
+ isLocalEvent,
352
+ ignoreLocalEvents: false,
353
+ })
354
+
355
+ if (divergencePointWithoutLocalEvents === -1) return -1
356
+
357
+ const divergencePointEventId = existingEvents[divergencePointWithoutLocalEvents]!.id
358
+ // Now find the divergence point in the original array
359
+ return existingEvents.findIndex((event) => EventId.isEqual(event.id, divergencePointEventId))
360
+ }
361
+
362
+ return existingEvents.findIndex((existingEvent, index) => {
363
+ const incomingEvent = incomingEvents[index]
364
+ // return !incomingEvent || !isEqualEvent(existingEvent, incomingEvent)
365
+ return incomingEvent && !isEqualEvent(existingEvent, incomingEvent)
366
+ })
367
+ }
368
+
369
+ const rebaseEvents = ({
370
+ events,
371
+ baseEventId,
372
+ isLocalEvent,
373
+ }: {
374
+ events: ReadonlyArray<MutationEvent.EncodedWithMeta>
375
+ baseEventId: EventId.EventId
376
+ isLocalEvent: (event: MutationEvent.EncodedWithMeta) => boolean
377
+ }): ReadonlyArray<MutationEvent.EncodedWithMeta> => {
378
+ let prevEventId = baseEventId
379
+ return events.map((event) => {
380
+ const isLocal = isLocalEvent(event)
381
+ const newEvent = event.rebase(prevEventId, isLocal)
382
+ prevEventId = newEvent.id
383
+ return newEvent
384
+ })
385
+ }
@@ -0,0 +1,18 @@
1
+ import { Effect } from '@livestore/utils/effect'
2
+
3
+ import type { MutationEvent } from '../schema/mod.js'
4
+ import { InvalidPushError } from './sync.js'
5
+
6
+ // TODO proper batch validation
7
+ export const validatePushPayload = (batch: ReadonlyArray<MutationEvent.AnyEncoded>, currentEventId: number) =>
8
+ Effect.gen(function* () {
9
+ if (batch[0]!.id.global <= currentEventId) {
10
+ return yield* InvalidPushError.make({
11
+ reason: {
12
+ _tag: 'ServerAhead',
13
+ minimumExpectedId: currentEventId + 1,
14
+ providedId: batch[0]!.id.global,
15
+ },
16
+ })
17
+ }
18
+ })
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.2.0-dev.1' as const
5
+ export const liveStoreVersion = '0.2.0' as const
6
6
 
7
7
  /**
8
8
  * This version number is incremented whenever the internal storage format changes in a breaking way.
@@ -11,4 +11,4 @@ export const liveStoreVersion = '0.2.0-dev.1' as const
11
11
  * While LiveStore is in alpha, this might happen more frequently.
12
12
  * In the future, LiveStore will provide a migration path for older database files to avoid the impression of data loss.
13
13
  */
14
- export const liveStoreStorageFormatVersion = 2
14
+ export const liveStoreStorageFormatVersion = 3
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/schema/index.ts"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/schema/index.ts"],"names":[],"mappings":"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"}
@@ -1,14 +0,0 @@
1
- import { Effect } from '@livestore/utils/effect';
2
- import type { EventId } from '../adapter-types.js';
3
- export declare const makeNextMutationEventIdPair: (currentMutationEventIdRef: {
4
- current: EventId;
5
- }) => (opts: {
6
- localOnly: boolean;
7
- }) => Effect.Effect<{
8
- id: {
9
- global: number;
10
- local: number;
11
- };
12
- parentId: EventId;
13
- }, never, never>;
14
- //# sourceMappingURL=next-mutation-event-id-pair.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"next-mutation-event-id-pair.d.ts","sourceRoot":"","sources":["../../src/sync/next-mutation-event-id-pair.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAEhD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAElD,eAAO,MAAM,2BAA2B,8BACV;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,YAAY;IAAE,SAAS,EAAE,OAAO,CAAA;CAAE;;;;;;gBAc9E,CAAA"}
@@ -1,13 +0,0 @@
1
- import { Effect } from '@livestore/utils/effect';
2
- export const makeNextMutationEventIdPair = (currentMutationEventIdRef) => (opts) => Effect.gen(function* () {
3
- // NOTE we always point to `local: 0` for non-localOnly mutations
4
- const parentId = opts.localOnly
5
- ? currentMutationEventIdRef.current
6
- : { global: currentMutationEventIdRef.current.global, local: 0 };
7
- const id = opts.localOnly
8
- ? { global: parentId.global, local: parentId.local + 1 }
9
- : { global: parentId.global + 1, local: 0 };
10
- currentMutationEventIdRef.current = id;
11
- return { id, parentId };
12
- });
13
- //# sourceMappingURL=next-mutation-event-id-pair.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"next-mutation-event-id-pair.js","sourceRoot":"","sources":["../../src/sync/next-mutation-event-id-pair.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAIhD,MAAM,CAAC,MAAM,2BAA2B,GACtC,CAAC,yBAA+C,EAAE,EAAE,CAAC,CAAC,IAA4B,EAAE,EAAE,CACpF,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,iEAAiE;IACjE,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS;QAC7B,CAAC,CAAC,yBAAyB,CAAC,OAAO;QACnC,CAAC,CAAC,EAAE,MAAM,EAAE,yBAAyB,CAAC,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,CAAA;IAElE,MAAM,EAAE,GAAG,IAAI,CAAC,SAAS;QACvB,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,GAAG,CAAC,EAAE;QACxD,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAA;IAE7C,yBAAyB,CAAC,OAAO,GAAG,EAAE,CAAA;IAEtC,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAA;AACzB,CAAC,CAAC,CAAA"}
@@ -1,20 +0,0 @@
1
- import { Effect } from '@livestore/utils/effect'
2
-
3
- import type { EventId } from '../adapter-types.js'
4
-
5
- export const makeNextMutationEventIdPair =
6
- (currentMutationEventIdRef: { current: EventId }) => (opts: { localOnly: boolean }) =>
7
- Effect.gen(function* () {
8
- // NOTE we always point to `local: 0` for non-localOnly mutations
9
- const parentId = opts.localOnly
10
- ? currentMutationEventIdRef.current
11
- : { global: currentMutationEventIdRef.current.global, local: 0 }
12
-
13
- const id = opts.localOnly
14
- ? { global: parentId.global, local: parentId.local + 1 }
15
- : { global: parentId.global + 1, local: 0 }
16
-
17
- currentMutationEventIdRef.current = id
18
-
19
- return { id, parentId }
20
- })