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

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 (146) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/adapter-types.d.ts +23 -26
  3. package/dist/adapter-types.d.ts.map +1 -1
  4. package/dist/adapter-types.js.map +1 -1
  5. package/dist/derived-mutations.d.ts +4 -4
  6. package/dist/derived-mutations.d.ts.map +1 -1
  7. package/dist/derived-mutations.test.js.map +1 -1
  8. package/dist/devtools/devtools-bridge.d.ts +1 -2
  9. package/dist/devtools/devtools-bridge.d.ts.map +1 -1
  10. package/dist/devtools/devtools-messages.d.ts +110 -98
  11. package/dist/devtools/devtools-messages.d.ts.map +1 -1
  12. package/dist/devtools/devtools-messages.js +6 -9
  13. package/dist/devtools/devtools-messages.js.map +1 -1
  14. package/dist/index.d.ts +4 -0
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/leader-thread/apply-mutation.d.ts +2 -5
  17. package/dist/leader-thread/apply-mutation.d.ts.map +1 -1
  18. package/dist/leader-thread/apply-mutation.js +26 -38
  19. package/dist/leader-thread/apply-mutation.js.map +1 -1
  20. package/dist/leader-thread/leader-sync-processor.d.ts +2 -2
  21. package/dist/leader-thread/leader-sync-processor.d.ts.map +1 -1
  22. package/dist/leader-thread/leader-sync-processor.js +12 -20
  23. package/dist/leader-thread/leader-sync-processor.js.map +1 -1
  24. package/dist/leader-thread/leader-worker-devtools.d.ts +1 -1
  25. package/dist/leader-thread/leader-worker-devtools.d.ts.map +1 -1
  26. package/dist/leader-thread/leader-worker-devtools.js +66 -22
  27. package/dist/leader-thread/leader-worker-devtools.js.map +1 -1
  28. package/dist/leader-thread/make-leader-thread-layer.d.ts +7 -8
  29. package/dist/leader-thread/make-leader-thread-layer.d.ts.map +1 -1
  30. package/dist/leader-thread/make-leader-thread-layer.js +5 -11
  31. package/dist/leader-thread/make-leader-thread-layer.js.map +1 -1
  32. package/dist/leader-thread/mutationlog.d.ts +17 -4
  33. package/dist/leader-thread/mutationlog.d.ts.map +1 -1
  34. package/dist/leader-thread/mutationlog.js +1 -2
  35. package/dist/leader-thread/mutationlog.js.map +1 -1
  36. package/dist/leader-thread/pull-queue-set.d.ts.map +1 -1
  37. package/dist/leader-thread/recreate-db.d.ts.map +1 -1
  38. package/dist/leader-thread/recreate-db.js +3 -9
  39. package/dist/leader-thread/recreate-db.js.map +1 -1
  40. package/dist/leader-thread/types.d.ts +9 -17
  41. package/dist/leader-thread/types.d.ts.map +1 -1
  42. package/dist/leader-thread/types.js.map +1 -1
  43. package/dist/mutation.d.ts +2 -9
  44. package/dist/mutation.d.ts.map +1 -1
  45. package/dist/mutation.js +5 -5
  46. package/dist/mutation.js.map +1 -1
  47. package/dist/query-builder/impl.d.ts +1 -1
  48. package/dist/rehydrate-from-mutationlog.d.ts +2 -2
  49. package/dist/rehydrate-from-mutationlog.d.ts.map +1 -1
  50. package/dist/rehydrate-from-mutationlog.js +19 -13
  51. package/dist/rehydrate-from-mutationlog.js.map +1 -1
  52. package/dist/schema/EventId.d.ts +14 -16
  53. package/dist/schema/EventId.d.ts.map +1 -1
  54. package/dist/schema/EventId.js +7 -15
  55. package/dist/schema/EventId.js.map +1 -1
  56. package/dist/schema/MutationEvent.d.ts +80 -49
  57. package/dist/schema/MutationEvent.d.ts.map +1 -1
  58. package/dist/schema/MutationEvent.js +15 -32
  59. package/dist/schema/MutationEvent.js.map +1 -1
  60. package/dist/schema/system-tables.d.ts +26 -26
  61. package/dist/schema/system-tables.d.ts.map +1 -1
  62. package/dist/schema/system-tables.js +11 -19
  63. package/dist/schema/system-tables.js.map +1 -1
  64. package/dist/schema-management/migrations.js +6 -6
  65. package/dist/schema-management/migrations.js.map +1 -1
  66. package/dist/sync/client-session-sync-processor.d.ts +4 -4
  67. package/dist/sync/client-session-sync-processor.d.ts.map +1 -1
  68. package/dist/sync/index.d.ts +1 -1
  69. package/dist/sync/index.d.ts.map +1 -1
  70. package/dist/sync/index.js +1 -1
  71. package/dist/sync/index.js.map +1 -1
  72. package/dist/sync/next/history-dag-common.d.ts +4 -1
  73. package/dist/sync/next/history-dag-common.d.ts.map +1 -1
  74. package/dist/sync/next/history-dag-common.js +1 -1
  75. package/dist/sync/next/history-dag-common.js.map +1 -1
  76. package/dist/sync/next/rebase-events.d.ts +3 -3
  77. package/dist/sync/next/rebase-events.d.ts.map +1 -1
  78. package/dist/sync/next/rebase-events.js +2 -3
  79. package/dist/sync/next/rebase-events.js.map +1 -1
  80. package/dist/sync/next/test/mutation-fixtures.d.ts.map +1 -1
  81. package/dist/sync/next/test/mutation-fixtures.js +9 -3
  82. package/dist/sync/next/test/mutation-fixtures.js.map +1 -1
  83. package/dist/sync/sync.d.ts +11 -21
  84. package/dist/sync/sync.d.ts.map +1 -1
  85. package/dist/sync/sync.js.map +1 -1
  86. package/dist/sync/syncstate.d.ts +23 -45
  87. package/dist/sync/syncstate.d.ts.map +1 -1
  88. package/dist/sync/syncstate.js +12 -56
  89. package/dist/sync/syncstate.js.map +1 -1
  90. package/dist/sync/syncstate.test.js +69 -125
  91. package/dist/sync/syncstate.test.js.map +1 -1
  92. package/dist/sync/validate-push-payload.d.ts +2 -2
  93. package/dist/sync/validate-push-payload.d.ts.map +1 -1
  94. package/dist/sync/validate-push-payload.js +2 -2
  95. package/dist/sync/validate-push-payload.js.map +1 -1
  96. package/dist/version.d.ts +1 -1
  97. package/dist/version.d.ts.map +1 -1
  98. package/dist/version.js +1 -1
  99. package/dist/version.js.map +1 -1
  100. package/package.json +5 -6
  101. package/src/adapter-types.ts +24 -22
  102. package/src/derived-mutations.test.ts +1 -1
  103. package/src/derived-mutations.ts +5 -9
  104. package/src/devtools/devtools-bridge.ts +1 -2
  105. package/src/devtools/devtools-messages.ts +6 -9
  106. package/src/index.ts +6 -0
  107. package/src/leader-thread/apply-mutation.ts +31 -49
  108. package/src/leader-thread/{LeaderSyncProcessor.ts → leader-sync-processor.ts} +230 -235
  109. package/src/leader-thread/leader-worker-devtools.ts +109 -30
  110. package/src/leader-thread/make-leader-thread-layer.ts +13 -24
  111. package/src/leader-thread/mutationlog.ts +5 -9
  112. package/src/leader-thread/recreate-db.ts +5 -9
  113. package/src/leader-thread/types.ts +11 -18
  114. package/src/mutation.ts +7 -17
  115. package/src/rehydrate-from-mutationlog.ts +23 -15
  116. package/src/schema/EventId.ts +9 -23
  117. package/src/schema/MutationEvent.ts +24 -46
  118. package/src/schema/system-tables.ts +11 -19
  119. package/src/schema-management/migrations.ts +6 -6
  120. package/src/sync/{ClientSessionSyncProcessor.ts → client-session-sync-processor.ts} +9 -11
  121. package/src/sync/index.ts +1 -1
  122. package/src/sync/next/history-dag-common.ts +1 -1
  123. package/src/sync/next/rebase-events.ts +7 -7
  124. package/src/sync/next/test/mutation-fixtures.ts +10 -3
  125. package/src/sync/sync.ts +6 -19
  126. package/src/sync/syncstate.test.ts +67 -127
  127. package/src/sync/syncstate.ts +19 -21
  128. package/src/sync/validate-push-payload.ts +4 -7
  129. package/src/version.ts +1 -1
  130. package/dist/leader-thread/LeaderSyncProcessor.d.ts +0 -37
  131. package/dist/leader-thread/LeaderSyncProcessor.d.ts.map +0 -1
  132. package/dist/leader-thread/LeaderSyncProcessor.js +0 -417
  133. package/dist/leader-thread/LeaderSyncProcessor.js.map +0 -1
  134. package/dist/schema/EventId.test.d.ts +0 -2
  135. package/dist/schema/EventId.test.d.ts.map +0 -1
  136. package/dist/schema/EventId.test.js +0 -11
  137. package/dist/schema/EventId.test.js.map +0 -1
  138. package/dist/schema/MutationEvent.test.d.ts +0 -2
  139. package/dist/schema/MutationEvent.test.d.ts.map +0 -1
  140. package/dist/schema/MutationEvent.test.js +0 -2
  141. package/dist/schema/MutationEvent.test.js.map +0 -1
  142. package/dist/sync/ClientSessionSyncProcessor.d.ts +0 -45
  143. package/dist/sync/ClientSessionSyncProcessor.d.ts.map +0 -1
  144. package/dist/sync/ClientSessionSyncProcessor.js +0 -134
  145. package/dist/sync/ClientSessionSyncProcessor.js.map +0 -1
  146. package/src/schema/EventId.test.ts +0 -12
@@ -7,14 +7,14 @@ import * as SyncState from './syncstate.js'
7
7
 
8
8
  class TestEvent extends MutationEvent.EncodedWithMeta {
9
9
  constructor(
10
- id: EventId.EventId | typeof EventId.EventId.Encoded,
11
- parentId: EventId.EventId,
10
+ public readonly id: EventId.EventId,
11
+ public readonly parentId: EventId.EventId,
12
12
  public readonly payload: string,
13
13
  public readonly isLocal: boolean,
14
14
  ) {
15
15
  super({
16
- id: EventId.make(id),
17
- parentId: EventId.make(parentId),
16
+ id,
17
+ parentId,
18
18
  mutation: 'a',
19
19
  args: payload,
20
20
  meta: {},
@@ -58,12 +58,12 @@ describe('syncstate', () => {
58
58
  'upstream-rebase (trimRollbackUntil: $trimRollbackUntil)',
59
59
  ({ trimRollbackUntil }) => {
60
60
  it('should rollback until start', () => {
61
- const syncState = new SyncState.SyncState({
61
+ const syncState = {
62
62
  pending: [e_1_0],
63
63
  rollbackTail: [e_0_0, e_0_1],
64
64
  upstreamHead: EventId.ROOT,
65
65
  localHead: e_1_0.id,
66
- })
66
+ }
67
67
  const e_0_0_e_1_0 = e_0_0.rebase_(e_1_0.id)
68
68
  const e_0_1_e_1_1 = e_0_1.rebase_(e_0_0_e_1_0.id)
69
69
  const result = run({
@@ -83,19 +83,19 @@ describe('syncstate', () => {
83
83
  } else {
84
84
  expectEventArraysEqual(result.newSyncState.rollbackTail, [e_0_0_e_1_0, e_0_1_e_1_1])
85
85
  }
86
- expect(result.newSyncState.upstreamHead).toMatchObject(e_0_1_e_1_1.id)
86
+ expect(result.newSyncState.upstreamHead).toBe(e_0_1_e_1_1.id)
87
87
  expect(result.newSyncState.localHead).toMatchObject(e_1_0_e_2_0.id)
88
88
  expectEventArraysEqual(result.newEvents, [e_0_0_e_1_0, e_0_1_e_1_1])
89
89
  expectEventArraysEqual(result.eventsToRollback, [e_0_0, e_0_1, e_1_0])
90
90
  })
91
91
 
92
92
  it('should rollback only to specified point', () => {
93
- const syncState = new SyncState.SyncState({
93
+ const syncState = {
94
94
  pending: [e_1_0],
95
95
  rollbackTail: [e_0_0, e_0_1],
96
96
  upstreamHead: EventId.ROOT,
97
97
  localHead: e_1_0.id,
98
- })
98
+ }
99
99
  const e_0_1_e_1_0 = e_0_1.rebase_(e_0_0.id)
100
100
  const result = run({
101
101
  syncState,
@@ -114,19 +114,14 @@ describe('syncstate', () => {
114
114
  } else {
115
115
  expectEventArraysEqual(result.newSyncState.rollbackTail, [e_0_0, e_0_1_e_1_0])
116
116
  }
117
- expect(result.newSyncState.upstreamHead).toMatchObject(e_0_1_e_1_0.id)
117
+ expect(result.newSyncState.upstreamHead).toBe(e_0_1_e_1_0.id)
118
118
  expect(result.newSyncState.localHead).toMatchObject(e_1_0_e_2_0.id)
119
119
  expectEventArraysEqual(result.newEvents, [e_0_1_e_1_0])
120
120
  expectEventArraysEqual(result.eventsToRollback, [e_0_1, e_1_0])
121
121
  })
122
122
 
123
123
  it('should work for empty pending', () => {
124
- const syncState = new SyncState.SyncState({
125
- pending: [],
126
- rollbackTail: [e_0_0],
127
- upstreamHead: EventId.ROOT,
128
- localHead: e_0_0.id,
129
- })
124
+ const syncState = { pending: [], rollbackTail: [e_0_0], upstreamHead: EventId.ROOT, localHead: e_0_0.id }
130
125
  const result = run({
131
126
  syncState,
132
127
  payload: { _tag: 'upstream-rebase', rollbackUntil: e_0_0.id, newEvents: [e_1_0] },
@@ -134,18 +129,13 @@ describe('syncstate', () => {
134
129
  expectRebase(result)
135
130
  expectEventArraysEqual(result.newSyncState.pending, [])
136
131
  expectEventArraysEqual(result.newSyncState.rollbackTail, [e_1_0])
137
- expect(result.newSyncState.upstreamHead).toMatchObject(e_1_0.id)
132
+ expect(result.newSyncState.upstreamHead).toBe(e_1_0.id)
138
133
  expect(result.newSyncState.localHead).toMatchObject(e_1_0.id)
139
- expect(result.newEvents).toStrictEqual([e_1_0])
134
+ expect(result.newEvents).toEqual([e_1_0])
140
135
  })
141
136
 
142
137
  it('should fail for empty rollback tail', () => {
143
- const syncState = new SyncState.SyncState({
144
- pending: [],
145
- rollbackTail: [],
146
- upstreamHead: EventId.ROOT,
147
- localHead: e_0_0.id,
148
- })
138
+ const syncState = { pending: [], rollbackTail: [], upstreamHead: EventId.ROOT, localHead: e_0_0.id }
149
139
  expect(() =>
150
140
  run({
151
141
  syncState,
@@ -155,12 +145,7 @@ describe('syncstate', () => {
155
145
  })
156
146
 
157
147
  it('should work for empty incoming', () => {
158
- const syncState = new SyncState.SyncState({
159
- pending: [],
160
- rollbackTail: [e_0_0],
161
- upstreamHead: EventId.ROOT,
162
- localHead: e_0_0.id,
163
- })
148
+ const syncState = { pending: [], rollbackTail: [e_0_0], upstreamHead: EventId.ROOT, localHead: e_0_0.id }
164
149
  const result = run({
165
150
  syncState,
166
151
  payload: { _tag: 'upstream-rebase', rollbackUntil: e_0_0.id, newEvents: [] },
@@ -168,92 +153,67 @@ describe('syncstate', () => {
168
153
  expectRebase(result)
169
154
  expectEventArraysEqual(result.newSyncState.pending, [])
170
155
  expectEventArraysEqual(result.newSyncState.rollbackTail, [])
171
- expect(result.newSyncState.upstreamHead).toMatchObject(EventId.ROOT)
156
+ expect(result.newSyncState.upstreamHead).toBe(EventId.ROOT)
172
157
  expect(result.newSyncState.localHead).toMatchObject(EventId.ROOT)
173
- expect(result.newEvents).toStrictEqual([])
158
+ expect(result.newEvents).toEqual([])
174
159
  })
175
160
  },
176
161
  )
177
162
 
178
163
  describe('upstream-advance: advance', () => {
179
164
  it('should throw error if newEvents are not sorted in ascending order by eventId (local)', () => {
180
- const syncState = new SyncState.SyncState({
181
- pending: [e_0_0],
182
- rollbackTail: [],
183
- upstreamHead: EventId.ROOT,
184
- localHead: e_0_0.id,
185
- })
165
+ const syncState = { pending: [e_0_0], rollbackTail: [], upstreamHead: EventId.ROOT, localHead: e_0_0.id }
186
166
  expect(() => run({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e_0_1, e_0_0] } })).toThrow()
187
167
  })
188
168
 
189
169
  it('should throw error if newEvents are not sorted in ascending order by eventId (global)', () => {
190
- const syncState = new SyncState.SyncState({
191
- pending: [e_0_0],
192
- rollbackTail: [],
193
- upstreamHead: EventId.ROOT,
194
- localHead: e_0_0.id,
195
- })
170
+ const syncState = { pending: [e_0_0], rollbackTail: [], upstreamHead: EventId.ROOT, localHead: e_0_0.id }
196
171
  expect(() => run({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e_1_0, e_0_0] } })).toThrow()
197
172
  })
198
173
 
199
174
  it('should acknowledge pending event when receiving matching event', () => {
200
- const syncState = new SyncState.SyncState({
201
- pending: [e_0_0],
202
- rollbackTail: [],
203
- upstreamHead: EventId.ROOT,
204
- localHead: e_0_0.id,
205
- })
175
+ const syncState = { pending: [e_0_0], rollbackTail: [], upstreamHead: EventId.ROOT, localHead: e_0_0.id }
206
176
  const result = run({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e_0_0] } })
207
177
 
208
178
  expectAdvance(result)
209
179
  expectEventArraysEqual(result.newSyncState.pending, [])
210
180
  expectEventArraysEqual(result.newSyncState.rollbackTail, [e_0_0])
211
- expect(result.newSyncState.upstreamHead).toMatchObject(e_0_0.id)
181
+ expect(result.newSyncState.upstreamHead).toBe(e_0_0.id)
212
182
  expect(result.newSyncState.localHead).toMatchObject(e_0_0.id)
213
- expect(result.newEvents).toStrictEqual([])
183
+ expect(result.newEvents).toEqual([])
214
184
  })
215
185
 
216
186
  it('should acknowledge partial pending event when receiving matching event', () => {
217
- const syncState = new SyncState.SyncState({
187
+ const syncState = {
218
188
  pending: [e_0_0, e_1_0],
219
189
  rollbackTail: [],
220
190
  upstreamHead: EventId.ROOT,
221
191
  localHead: e_1_0.id,
222
- })
192
+ }
223
193
  const result = run({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e_0_0] } })
224
194
 
225
195
  expectAdvance(result)
226
196
  expectEventArraysEqual(result.newSyncState.pending, [e_1_0])
227
197
  expectEventArraysEqual(result.newSyncState.rollbackTail, [e_0_0])
228
- expect(result.newSyncState.upstreamHead).toMatchObject(e_0_0.id)
198
+ expect(result.newSyncState.upstreamHead).toBe(e_0_0.id)
229
199
  expect(result.newSyncState.localHead).toMatchObject(e_1_0.id)
230
- expect(result.newEvents).toStrictEqual([])
200
+ expect(result.newEvents).toEqual([])
231
201
  })
232
202
 
233
203
  it('should acknowledge pending event and add new event', () => {
234
- const syncState = new SyncState.SyncState({
235
- pending: [e_0_0],
236
- rollbackTail: [],
237
- upstreamHead: EventId.ROOT,
238
- localHead: e_0_0.id,
239
- })
204
+ const syncState = { pending: [e_0_0], rollbackTail: [], upstreamHead: EventId.ROOT, localHead: e_0_0.id }
240
205
  const result = run({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e_0_0, e_0_1] } })
241
206
 
242
207
  expectAdvance(result)
243
208
  expectEventArraysEqual(result.newSyncState.pending, [])
244
209
  expectEventArraysEqual(result.newSyncState.rollbackTail, [e_0_0, e_0_1])
245
- expect(result.newSyncState.upstreamHead).toMatchObject(e_0_1.id)
210
+ expect(result.newSyncState.upstreamHead).toBe(e_0_1.id)
246
211
  expect(result.newSyncState.localHead).toMatchObject(e_0_1.id)
247
- expect(result.newEvents).toStrictEqual([e_0_1])
212
+ expect(result.newEvents).toEqual([e_0_1])
248
213
  })
249
214
 
250
215
  it('should acknowledge pending event and add multiple new events', () => {
251
- const syncState = new SyncState.SyncState({
252
- pending: [e_0_1],
253
- rollbackTail: [],
254
- upstreamHead: e_0_0.id,
255
- localHead: e_0_1.id,
256
- })
216
+ const syncState = { pending: [e_0_1], rollbackTail: [], upstreamHead: e_0_0.id, localHead: e_0_1.id }
257
217
  const result = run({
258
218
  syncState,
259
219
  payload: { _tag: 'upstream-advance', newEvents: [e_0_1, e_0_2, e_0_3, e_1_0, e_1_1] },
@@ -262,18 +222,18 @@ describe('syncstate', () => {
262
222
  expectAdvance(result)
263
223
  expectEventArraysEqual(result.newSyncState.pending, [])
264
224
  expectEventArraysEqual(result.newSyncState.rollbackTail, [e_0_1, e_0_2, e_0_3, e_1_0, e_1_1])
265
- expect(result.newSyncState.upstreamHead).toMatchObject(e_1_1.id)
225
+ expect(result.newSyncState.upstreamHead).toBe(e_1_1.id)
266
226
  expect(result.newSyncState.localHead).toMatchObject(e_1_1.id)
267
- expect(result.newEvents).toStrictEqual([e_0_2, e_0_3, e_1_0, e_1_1])
227
+ expect(result.newEvents).toEqual([e_0_2, e_0_3, e_1_0, e_1_1])
268
228
  })
269
229
 
270
230
  it('should ignore local events (incoming is subset of pending)', () => {
271
- const syncState = new SyncState.SyncState({
231
+ const syncState = {
272
232
  pending: [e_r_1, e_0_0],
273
233
  rollbackTail: [],
274
234
  upstreamHead: EventId.ROOT,
275
235
  localHead: e_0_0.id,
276
- })
236
+ }
277
237
  const result = run({
278
238
  syncState,
279
239
  payload: { _tag: 'upstream-advance', newEvents: [e_0_0] },
@@ -282,18 +242,18 @@ describe('syncstate', () => {
282
242
  expectAdvance(result)
283
243
  expectEventArraysEqual(result.newSyncState.pending, [])
284
244
  expectEventArraysEqual(result.newSyncState.rollbackTail, [e_r_1, e_0_0])
285
- expect(result.newSyncState.upstreamHead).toMatchObject(e_0_0.id)
245
+ expect(result.newSyncState.upstreamHead).toBe(e_0_0.id)
286
246
  expect(result.newSyncState.localHead).toMatchObject(e_0_0.id)
287
- expect(result.newEvents).toStrictEqual([])
247
+ expect(result.newEvents).toEqual([])
288
248
  })
289
249
 
290
250
  it('should ignore local events (incoming is subset of pending case 2)', () => {
291
- const syncState = new SyncState.SyncState({
251
+ const syncState = {
292
252
  pending: [e_r_1, e_0_0, e_1_0],
293
253
  rollbackTail: [],
294
254
  upstreamHead: EventId.ROOT,
295
255
  localHead: e_0_0.id,
296
- })
256
+ }
297
257
  const result = run({
298
258
  syncState,
299
259
  payload: { _tag: 'upstream-advance', newEvents: [e_0_0] },
@@ -302,18 +262,18 @@ describe('syncstate', () => {
302
262
  expectAdvance(result)
303
263
  expectEventArraysEqual(result.newSyncState.pending, [e_1_0])
304
264
  expectEventArraysEqual(result.newSyncState.rollbackTail, [e_r_1, e_0_0])
305
- expect(result.newSyncState.upstreamHead).toMatchObject(e_0_0.id)
265
+ expect(result.newSyncState.upstreamHead).toBe(e_0_0.id)
306
266
  expect(result.newSyncState.localHead).toMatchObject(e_1_0.id)
307
- expect(result.newEvents).toStrictEqual([])
267
+ expect(result.newEvents).toEqual([])
308
268
  })
309
269
 
310
270
  it('should ignore local events (incoming goes beyond pending)', () => {
311
- const syncState = new SyncState.SyncState({
271
+ const syncState = {
312
272
  pending: [e_r_1, e_0_0, e_0_1],
313
273
  rollbackTail: [],
314
274
  upstreamHead: EventId.ROOT,
315
275
  localHead: e_0_1.id,
316
- })
276
+ }
317
277
  const result = run({
318
278
  syncState,
319
279
  payload: { _tag: 'upstream-advance', newEvents: [e_0_0, e_1_0] },
@@ -323,20 +283,15 @@ describe('syncstate', () => {
323
283
  expectAdvance(result)
324
284
  expectEventArraysEqual(result.newSyncState.pending, [])
325
285
  expectEventArraysEqual(result.newSyncState.rollbackTail, [e_r_1, e_0_0, e_0_1, e_1_0])
326
- expect(result.newSyncState.upstreamHead).toMatchObject(e_1_0.id)
286
+ expect(result.newSyncState.upstreamHead).toBe(e_1_0.id)
327
287
  expect(result.newSyncState.localHead).toMatchObject(e_1_0.id)
328
- expect(result.newEvents).toStrictEqual([e_1_0])
288
+ expect(result.newEvents).toEqual([e_1_0])
329
289
  })
330
290
  })
331
291
 
332
292
  describe('upstream-advance: rebase', () => {
333
293
  it('should rebase single local event to end', () => {
334
- const syncState = new SyncState.SyncState({
335
- pending: [e_0_0],
336
- rollbackTail: [],
337
- upstreamHead: EventId.ROOT,
338
- localHead: e_0_0.id,
339
- })
294
+ const syncState = { pending: [e_0_0], rollbackTail: [], upstreamHead: EventId.ROOT, localHead: e_0_0.id }
340
295
  const result = run({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e_0_1] } })
341
296
 
342
297
  const e_0_0_e_0_2 = e_0_0.rebase_(e_0_1.id)
@@ -344,7 +299,7 @@ describe('syncstate', () => {
344
299
  expectRebase(result)
345
300
  expectEventArraysEqual(result.newSyncState.pending, [e_0_0_e_0_2])
346
301
  expectEventArraysEqual(result.newSyncState.rollbackTail, [e_0_1])
347
- expect(result.newSyncState.upstreamHead).toMatchObject(e_0_1.id)
302
+ expect(result.newSyncState.upstreamHead).toBe(e_0_1.id)
348
303
  expect(result.newSyncState.localHead).toMatchObject(e_0_0_e_0_2.id)
349
304
  expectEventArraysEqual(result.eventsToRollback, [e_0_0])
350
305
  expectEventArraysEqual(result.newEvents, [e_0_1, e_0_0_e_0_2])
@@ -352,12 +307,7 @@ describe('syncstate', () => {
352
307
 
353
308
  it('should rebase different event with same id (no rollback tail)', () => {
354
309
  const e_0_0_b = new TestEvent({ global: 0, local: 0 }, EventId.ROOT, '0_0_b', true)
355
- const syncState = new SyncState.SyncState({
356
- pending: [e_0_0_b],
357
- rollbackTail: [],
358
- upstreamHead: EventId.ROOT,
359
- localHead: e_0_0_b.id,
360
- })
310
+ const syncState = { pending: [e_0_0_b], rollbackTail: [], upstreamHead: EventId.ROOT, localHead: e_0_0_b.id }
361
311
  const result = run({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e_0_0] } })
362
312
 
363
313
  const e_0_0_e_1_0 = e_0_0_b.rebase_(e_0_0.id)
@@ -367,18 +317,18 @@ describe('syncstate', () => {
367
317
  expectEventArraysEqual(result.newSyncState.rollbackTail, [e_0_0])
368
318
  expectEventArraysEqual(result.newEvents, [e_0_0, e_0_0_e_1_0])
369
319
  expectEventArraysEqual(result.eventsToRollback, [e_0_0_b])
370
- expect(result.newSyncState.upstreamHead).toMatchObject(e_0_0.id)
320
+ expect(result.newSyncState.upstreamHead).toBe(e_0_0.id)
371
321
  expect(result.newSyncState.localHead).toMatchObject(e_0_0_e_1_0.id)
372
322
  })
373
323
 
374
324
  it('should rebase different event with same id', () => {
375
325
  const e_1_0_b = new TestEvent({ global: 1, local: 0 }, e_0_0.id, '1_0_b', false)
376
- const syncState = new SyncState.SyncState({
326
+ const syncState = {
377
327
  pending: [e_1_0_b],
378
328
  rollbackTail: [e_0_0, e_0_1],
379
329
  upstreamHead: EventId.ROOT,
380
330
  localHead: e_1_0_b.id,
381
- })
331
+ }
382
332
  const result = run({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e_1_0] } })
383
333
  const e_1_0_e_2_0 = e_1_0_b.rebase_(e_1_0.id)
384
334
 
@@ -387,17 +337,12 @@ describe('syncstate', () => {
387
337
  expectEventArraysEqual(result.newSyncState.rollbackTail, [e_0_0, e_0_1, e_1_0])
388
338
  expectEventArraysEqual(result.newEvents, [e_1_0, e_1_0_e_2_0])
389
339
  expectEventArraysEqual(result.eventsToRollback, [e_0_0, e_0_1, e_1_0_b])
390
- expect(result.newSyncState.upstreamHead).toMatchObject(e_1_0.id)
340
+ expect(result.newSyncState.upstreamHead).toBe(e_1_0.id)
391
341
  expect(result.newSyncState.localHead).toMatchObject(e_1_0_e_2_0.id)
392
342
  })
393
343
 
394
344
  it('should rebase single local event to end (more incoming events)', () => {
395
- const syncState = new SyncState.SyncState({
396
- pending: [e_0_0],
397
- rollbackTail: [],
398
- upstreamHead: EventId.ROOT,
399
- localHead: e_0_0.id,
400
- })
345
+ const syncState = { pending: [e_0_0], rollbackTail: [], upstreamHead: EventId.ROOT, localHead: e_0_0.id }
401
346
  const result = run({
402
347
  syncState,
403
348
  payload: { _tag: 'upstream-advance', newEvents: [e_0_1, e_0_2, e_0_3, e_1_0] },
@@ -408,17 +353,17 @@ describe('syncstate', () => {
408
353
  expectRebase(result)
409
354
  expectEventArraysEqual(result.newSyncState.pending, [e_0_0_e_2_0])
410
355
  expectEventArraysEqual(result.newSyncState.rollbackTail, [e_0_1, e_0_2, e_0_3, e_1_0])
411
- expect(result.newSyncState.upstreamHead).toMatchObject(e_1_0.id)
356
+ expect(result.newSyncState.upstreamHead).toBe(e_1_0.id)
412
357
  expect(result.newSyncState.localHead).toMatchObject(e_0_0_e_2_0.id)
413
358
  })
414
359
 
415
360
  it('should only rebase divergent events when first event matches', () => {
416
- const syncState = new SyncState.SyncState({
361
+ const syncState = {
417
362
  pending: [e_0_0, e_0_1],
418
363
  rollbackTail: [],
419
364
  upstreamHead: EventId.ROOT,
420
365
  localHead: e_0_0.id,
421
- })
366
+ }
422
367
  const result = run({
423
368
  syncState,
424
369
  payload: { _tag: 'upstream-advance', newEvents: [e_0_0, e_0_2, e_0_3, e_1_0] },
@@ -431,17 +376,17 @@ describe('syncstate', () => {
431
376
  expectEventArraysEqual(result.newSyncState.rollbackTail, [e_0_0, e_0_2, e_0_3, e_1_0])
432
377
  expectEventArraysEqual(result.eventsToRollback, [e_0_1])
433
378
  expectEventArraysEqual(result.newEvents, [e_0_2, e_0_3, e_1_0, e_0_1_e_1_1])
434
- expect(result.newSyncState.upstreamHead).toMatchObject(e_1_0.id)
379
+ expect(result.newSyncState.upstreamHead).toBe(e_1_0.id)
435
380
  expect(result.newSyncState.localHead).toMatchObject(e_0_1_e_1_1.id)
436
381
  })
437
382
 
438
383
  it('should rebase all local events when incoming chain starts differently', () => {
439
- const syncState = new SyncState.SyncState({
384
+ const syncState = {
440
385
  pending: [e_0_0, e_0_1],
441
386
  rollbackTail: [],
442
387
  upstreamHead: EventId.ROOT,
443
388
  localHead: e_0_1.id,
444
- })
389
+ }
445
390
  const result = run({
446
391
  syncState,
447
392
  payload: { _tag: 'upstream-advance', newEvents: [e_0_1, e_0_2, e_0_3, e_1_0] },
@@ -455,25 +400,20 @@ describe('syncstate', () => {
455
400
  expectEventArraysEqual(result.newSyncState.rollbackTail, [e_0_1, e_0_2, e_0_3, e_1_0])
456
401
  expectEventArraysEqual(result.newEvents, [e_0_1, e_0_2, e_0_3, e_1_0, e_0_0_e_1_1, e_0_1_e_1_2])
457
402
  expectEventArraysEqual(result.eventsToRollback, [e_0_0, e_0_1])
458
- expect(result.newSyncState.upstreamHead).toMatchObject(e_1_0.id)
403
+ expect(result.newSyncState.upstreamHead).toBe(e_1_0.id)
459
404
  expect(result.newSyncState.localHead).toMatchObject(e_0_1_e_1_2.id)
460
405
  })
461
406
 
462
407
  describe('local-push', () => {
463
408
  describe('advance', () => {
464
409
  it('should advance with new events', () => {
465
- const syncState = new SyncState.SyncState({
466
- pending: [e_0_0],
467
- rollbackTail: [],
468
- upstreamHead: EventId.ROOT,
469
- localHead: e_0_0.id,
470
- })
410
+ const syncState = { pending: [e_0_0], rollbackTail: [], upstreamHead: EventId.ROOT, localHead: e_0_0.id }
471
411
  const result = run({ syncState, payload: { _tag: 'local-push', newEvents: [e_0_1, e_0_2, e_0_3] } })
472
412
 
473
413
  expectAdvance(result)
474
414
  expectEventArraysEqual(result.newSyncState.pending, [e_0_0, e_0_1, e_0_2, e_0_3])
475
415
  expectEventArraysEqual(result.newSyncState.rollbackTail, [])
476
- expect(result.newSyncState.upstreamHead).toMatchObject(EventId.ROOT)
416
+ expect(result.newSyncState.upstreamHead).toBe(EventId.ROOT)
477
417
  expect(result.newSyncState.localHead).toMatchObject(e_0_3.id)
478
418
  expectEventArraysEqual(result.newEvents, [e_0_1, e_0_2, e_0_3])
479
419
  })
@@ -481,12 +421,12 @@ describe('syncstate', () => {
481
421
 
482
422
  describe('reject', () => {
483
423
  it('should reject when new events are greater than pending events', () => {
484
- const syncState = new SyncState.SyncState({
424
+ const syncState = {
485
425
  pending: [e_0_0, e_0_1],
486
426
  rollbackTail: [],
487
427
  upstreamHead: EventId.ROOT,
488
428
  localHead: e_0_1.id,
489
- })
429
+ }
490
430
  const result = run({ syncState, payload: { _tag: 'local-push', newEvents: [e_0_1, e_0_2] } })
491
431
 
492
432
  expectReject(result)
@@ -504,10 +444,10 @@ const expectEventArraysEqual = (
504
444
  ) => {
505
445
  expect(actual.length).toBe(expected.length)
506
446
  actual.forEach((event, i) => {
507
- expect(event.id).toStrictEqual(expected[i]!.id)
508
- expect(event.parentId).toStrictEqual(expected[i]!.parentId)
509
- expect(event.mutation).toStrictEqual(expected[i]!.mutation)
510
- expect(event.args).toStrictEqual(expected[i]!.args)
447
+ expect(event.id).toEqual(expected[i]!.id)
448
+ expect(event.parentId).toEqual(expected[i]!.parentId)
449
+ expect(event.mutation).toEqual(expected[i]!.mutation)
450
+ expect(event.args).toEqual(expected[i]!.args)
511
451
  })
512
452
  }
513
453
 
@@ -39,21 +39,19 @@ import * as MutationEvent from '../schema/MutationEvent.js'
39
39
  * The `updateSyncState` function processes updates to the sync state based on incoming payloads,
40
40
  * handling cases such as upstream rebase, advance, local push, and rollback tail trimming.
41
41
  */
42
- export class SyncState extends Schema.Class<SyncState>('SyncState')({
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
50
  pending: Schema.Array(MutationEvent.EncodedWithMeta),
44
51
  rollbackTail: Schema.Array(MutationEvent.EncodedWithMeta),
45
52
  upstreamHead: EventId.EventId,
46
53
  localHead: EventId.EventId,
47
- }) {
48
- toJSON = (): any => {
49
- return {
50
- pending: this.pending.map((e) => e.toJSON()),
51
- rollbackTail: this.rollbackTail.map((e) => e.toJSON()),
52
- upstreamHead: `(${this.upstreamHead.global},${this.upstreamHead.local})`,
53
- localHead: `(${this.localHead.global},${this.localHead.local})`,
54
- }
55
- }
56
- }
54
+ }).annotations({ title: 'SyncState' })
57
55
 
58
56
  export class PayloadUpstreamRebase extends Schema.TaggedStruct('upstream-rebase', {
59
57
  /** Rollback until this event in the rollback tail (inclusive). Starting from the end of the rollback tail. */
@@ -155,12 +153,12 @@ export const updateSyncState = ({
155
153
 
156
154
  return {
157
155
  _tag: 'rebase',
158
- newSyncState: new SyncState({
156
+ newSyncState: {
159
157
  pending: rebasedPending,
160
158
  rollbackTail: trimRollbackTail([...syncState.rollbackTail.slice(0, rollbackIndex), ...payload.newEvents]),
161
159
  upstreamHead: newUpstreamHead,
162
160
  localHead: rebasedPending.at(-1)?.id ?? newUpstreamHead,
163
- }),
161
+ },
164
162
  previousSyncState: syncState,
165
163
  newEvents: payload.newEvents,
166
164
  eventsToRollback,
@@ -171,12 +169,12 @@ export const updateSyncState = ({
171
169
  if (payload.newEvents.length === 0) {
172
170
  return {
173
171
  _tag: 'advance',
174
- newSyncState: new SyncState({
172
+ newSyncState: {
175
173
  pending: syncState.pending,
176
174
  rollbackTail: trimRollbackTail(syncState.rollbackTail),
177
175
  upstreamHead: syncState.upstreamHead,
178
176
  localHead: syncState.localHead,
179
- }),
177
+ },
180
178
  previousSyncState: syncState,
181
179
  newEvents: [],
182
180
  }
@@ -237,12 +235,12 @@ export const updateSyncState = ({
237
235
 
238
236
  return {
239
237
  _tag: 'advance',
240
- newSyncState: new SyncState({
238
+ newSyncState: {
241
239
  pending: pendingRemaining,
242
240
  rollbackTail: trimRollbackTail([...syncState.rollbackTail, ...pendingAndNewEvents]),
243
241
  upstreamHead: newUpstreamHead,
244
242
  localHead: pendingRemaining.at(-1)?.id ?? newUpstreamHead,
245
- }),
243
+ },
246
244
  previousSyncState: syncState,
247
245
  newEvents,
248
246
  }
@@ -264,12 +262,12 @@ export const updateSyncState = ({
264
262
 
265
263
  return {
266
264
  _tag: 'rebase',
267
- newSyncState: new SyncState({
265
+ newSyncState: {
268
266
  pending: rebasedPending,
269
267
  rollbackTail: trimRollbackTail([...syncState.rollbackTail, ...payload.newEvents]),
270
268
  upstreamHead: newUpstreamHead,
271
269
  localHead: rebasedPending.at(-1)!.id,
272
- }),
270
+ },
273
271
  previousSyncState: syncState,
274
272
  newEvents: [...payload.newEvents.slice(divergentNewEventsIndex), ...rebasedPending],
275
273
  eventsToRollback: [...syncState.rollbackTail, ...divergentPending],
@@ -291,12 +289,12 @@ export const updateSyncState = ({
291
289
  } else {
292
290
  return {
293
291
  _tag: 'advance',
294
- newSyncState: new SyncState({
292
+ newSyncState: {
295
293
  pending: [...syncState.pending, ...payload.newEvents],
296
294
  rollbackTail: syncState.rollbackTail,
297
295
  upstreamHead: syncState.upstreamHead,
298
296
  localHead: payload.newEvents.at(-1)!.id,
299
- }),
297
+ },
300
298
  previousSyncState: syncState,
301
299
  newEvents: payload.newEvents,
302
300
  }
@@ -1,20 +1,17 @@
1
1
  import { Effect } from '@livestore/utils/effect'
2
2
 
3
- import type { EventId, MutationEvent } from '../schema/mod.js'
3
+ import type { MutationEvent } from '../schema/mod.js'
4
4
  import { InvalidPushError } from './sync.js'
5
5
 
6
6
  // TODO proper batch validation
7
- export const validatePushPayload = (
8
- batch: ReadonlyArray<MutationEvent.AnyEncodedGlobal>,
9
- currentEventId: EventId.GlobalEventId,
10
- ) =>
7
+ export const validatePushPayload = (batch: ReadonlyArray<MutationEvent.AnyEncoded>, currentEventId: number) =>
11
8
  Effect.gen(function* () {
12
- if (batch[0]!.id <= currentEventId) {
9
+ if (batch[0]!.id.global <= currentEventId) {
13
10
  return yield* InvalidPushError.make({
14
11
  reason: {
15
12
  _tag: 'ServerAhead',
16
13
  minimumExpectedId: currentEventId + 1,
17
- providedId: batch[0]!.id,
14
+ providedId: batch[0]!.id.global,
18
15
  },
19
16
  })
20
17
  }
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.10' as const
5
+ export const liveStoreVersion = '0.3.0-dev.0' as const
6
6
 
7
7
  /**
8
8
  * This version number is incremented whenever the internal storage format changes in a breaking way.
@@ -1,37 +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, LeaderSyncProcessor } from './types.js';
7
- /**
8
- * The LeaderSyncProcessor manages synchronization of mutations between
9
- * the local state and the sync backend, ensuring efficient and orderly processing.
10
- *
11
- * In the LeaderSyncProcessor, pulling always has precedence over pushing.
12
- *
13
- * Responsibilities:
14
- * - Queueing incoming local mutations in a localPushMailbox.
15
- * - Broadcasting mutations to client sessions via pull queues.
16
- * - Pushing mutations to the sync backend.
17
- *
18
- * Notes:
19
- *
20
- * local push processing:
21
- * - localPushMailbox:
22
- * - Maintains events in ascending order.
23
- * - Uses `Deferred` objects to resolve/reject events based on application success.
24
- * - Processes events from the mailbox, applying mutations in batches.
25
- * - Controlled by a `Latch` to manage execution flow.
26
- * - The latch closes on pull receipt and re-opens post-pull completion.
27
- * - Processes up to `maxBatchSize` events per cycle.
28
- *
29
- */
30
- export declare const makeLeaderSyncProcessor: ({ schema, dbMissing, dbLog, initialBlockingSyncContext, }: {
31
- schema: LiveStoreSchema;
32
- /** Only used to know whether we can safely query dbLog during setup execution */
33
- dbMissing: boolean;
34
- dbLog: SynchronousDatabase;
35
- initialBlockingSyncContext: InitialBlockingSyncContext;
36
- }) => Effect.Effect<LeaderSyncProcessor, UnexpectedError, Scope.Scope>;
37
- //# sourceMappingURL=LeaderSyncProcessor.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"LeaderSyncProcessor.d.ts","sourceRoot":"","sources":["../../src/leader-thread/LeaderSyncProcessor.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,mBAAmB,EAAE,MAAM,YAAY,CAAA;AAQlG;;;;;;;;;;;;;;;;;;;;;;GAsBG;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,mBAAmB,EAAE,eAAe,EAAE,KAAK,CAAC,KAAK,CAwK/D,CAAA"}