@livestore/common 0.0.0-snapshot-f5ece014485b5ab43795c218f7ba7cfa32c81707 → 0.0.0-snapshot-057a9e3a18ca69a310d4eb8cf35a34e94fa1841e

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 (228) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/ClientSessionLeaderThreadProxy.d.ts +35 -0
  3. package/dist/ClientSessionLeaderThreadProxy.d.ts.map +1 -0
  4. package/dist/ClientSessionLeaderThreadProxy.js +6 -0
  5. package/dist/ClientSessionLeaderThreadProxy.js.map +1 -0
  6. package/dist/adapter-types.d.ts +10 -161
  7. package/dist/adapter-types.d.ts.map +1 -1
  8. package/dist/adapter-types.js +5 -49
  9. package/dist/adapter-types.js.map +1 -1
  10. package/dist/defs.d.ts +20 -0
  11. package/dist/defs.d.ts.map +1 -0
  12. package/dist/defs.js +12 -0
  13. package/dist/defs.js.map +1 -0
  14. package/dist/devtools/devtools-messages-client-session.d.ts +23 -21
  15. package/dist/devtools/devtools-messages-client-session.d.ts.map +1 -1
  16. package/dist/devtools/devtools-messages-common.d.ts +6 -6
  17. package/dist/devtools/devtools-messages-common.d.ts.map +1 -1
  18. package/dist/devtools/devtools-messages-leader.d.ts +26 -24
  19. package/dist/devtools/devtools-messages-leader.d.ts.map +1 -1
  20. package/dist/devtools/devtools-messages.d.ts +1 -1
  21. package/dist/devtools/devtools-messages.d.ts.map +1 -1
  22. package/dist/devtools/devtools-messages.js +1 -1
  23. package/dist/devtools/devtools-messages.js.map +1 -1
  24. package/dist/errors.d.ts +50 -0
  25. package/dist/errors.d.ts.map +1 -0
  26. package/dist/errors.js +36 -0
  27. package/dist/errors.js.map +1 -0
  28. package/dist/index.d.ts +11 -11
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +11 -11
  31. package/dist/index.js.map +1 -1
  32. package/dist/leader-thread/LeaderSyncProcessor.d.ts +6 -7
  33. package/dist/leader-thread/LeaderSyncProcessor.d.ts.map +1 -1
  34. package/dist/leader-thread/LeaderSyncProcessor.js +112 -122
  35. package/dist/leader-thread/LeaderSyncProcessor.js.map +1 -1
  36. package/dist/leader-thread/eventlog.d.ts +17 -6
  37. package/dist/leader-thread/eventlog.d.ts.map +1 -1
  38. package/dist/leader-thread/eventlog.js +33 -18
  39. package/dist/leader-thread/eventlog.js.map +1 -1
  40. package/dist/leader-thread/leader-worker-devtools.d.ts.map +1 -1
  41. package/dist/leader-thread/leader-worker-devtools.js +1 -2
  42. package/dist/leader-thread/leader-worker-devtools.js.map +1 -1
  43. package/dist/leader-thread/make-leader-thread-layer.d.ts.map +1 -1
  44. package/dist/leader-thread/make-leader-thread-layer.js +37 -7
  45. package/dist/leader-thread/make-leader-thread-layer.js.map +1 -1
  46. package/dist/leader-thread/materialize-event.d.ts.map +1 -1
  47. package/dist/leader-thread/materialize-event.js +7 -1
  48. package/dist/leader-thread/materialize-event.js.map +1 -1
  49. package/dist/leader-thread/mod.d.ts +4 -3
  50. package/dist/leader-thread/mod.d.ts.map +1 -1
  51. package/dist/leader-thread/mod.js +4 -3
  52. package/dist/leader-thread/mod.js.map +1 -1
  53. package/dist/leader-thread/recreate-db.d.ts +13 -6
  54. package/dist/leader-thread/recreate-db.d.ts.map +1 -1
  55. package/dist/leader-thread/recreate-db.js +1 -3
  56. package/dist/leader-thread/recreate-db.js.map +1 -1
  57. package/dist/leader-thread/types.d.ts +5 -7
  58. package/dist/leader-thread/types.d.ts.map +1 -1
  59. package/dist/make-client-session.d.ts +1 -1
  60. package/dist/make-client-session.d.ts.map +1 -1
  61. package/dist/make-client-session.js +1 -1
  62. package/dist/make-client-session.js.map +1 -1
  63. package/dist/rematerialize-from-eventlog.d.ts +1 -1
  64. package/dist/rematerialize-from-eventlog.d.ts.map +1 -1
  65. package/dist/rematerialize-from-eventlog.js +10 -2
  66. package/dist/rematerialize-from-eventlog.js.map +1 -1
  67. package/dist/schema/EventDef.d.ts +2 -2
  68. package/dist/schema/EventDef.d.ts.map +1 -1
  69. package/dist/schema/EventDef.js +2 -2
  70. package/dist/schema/EventDef.js.map +1 -1
  71. package/dist/schema/EventSequenceNumber.d.ts +20 -2
  72. package/dist/schema/EventSequenceNumber.d.ts.map +1 -1
  73. package/dist/schema/EventSequenceNumber.js +71 -19
  74. package/dist/schema/EventSequenceNumber.js.map +1 -1
  75. package/dist/schema/EventSequenceNumber.test.js +88 -3
  76. package/dist/schema/EventSequenceNumber.test.js.map +1 -1
  77. package/dist/schema/LiveStoreEvent.d.ts +23 -9
  78. package/dist/schema/LiveStoreEvent.d.ts.map +1 -1
  79. package/dist/schema/LiveStoreEvent.js +12 -4
  80. package/dist/schema/LiveStoreEvent.js.map +1 -1
  81. package/dist/schema/events.d.ts +1 -1
  82. package/dist/schema/events.d.ts.map +1 -1
  83. package/dist/schema/events.js +1 -1
  84. package/dist/schema/events.js.map +1 -1
  85. package/dist/schema/mod.d.ts +6 -6
  86. package/dist/schema/mod.d.ts.map +1 -1
  87. package/dist/schema/mod.js +6 -6
  88. package/dist/schema/mod.js.map +1 -1
  89. package/dist/schema/state/sqlite/client-document-def.d.ts.map +1 -1
  90. package/dist/schema/state/sqlite/client-document-def.js.map +1 -1
  91. package/dist/schema/state/sqlite/client-document-def.test.js +3 -5
  92. package/dist/schema/state/sqlite/client-document-def.test.js.map +1 -1
  93. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.js +2 -2
  94. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.js.map +1 -1
  95. package/dist/schema/state/sqlite/db-schema/dsl/mod.d.ts.map +1 -1
  96. package/dist/schema/state/sqlite/db-schema/dsl/mod.js.map +1 -1
  97. package/dist/schema/state/sqlite/db-schema/hash.d.ts.map +1 -1
  98. package/dist/schema/state/sqlite/db-schema/hash.js +3 -2
  99. package/dist/schema/state/sqlite/db-schema/hash.js.map +1 -1
  100. package/dist/schema/state/sqlite/db-schema/mod.d.ts +1 -1
  101. package/dist/schema/state/sqlite/db-schema/mod.d.ts.map +1 -1
  102. package/dist/schema/state/sqlite/db-schema/mod.js +1 -1
  103. package/dist/schema/state/sqlite/db-schema/mod.js.map +1 -1
  104. package/dist/schema/state/sqlite/mod.d.ts +3 -3
  105. package/dist/schema/state/sqlite/mod.d.ts.map +1 -1
  106. package/dist/schema/state/sqlite/mod.js +2 -2
  107. package/dist/schema/state/sqlite/mod.js.map +1 -1
  108. package/dist/schema/state/sqlite/query-builder/api.d.ts +35 -8
  109. package/dist/schema/state/sqlite/query-builder/api.d.ts.map +1 -1
  110. package/dist/schema/state/sqlite/query-builder/api.js.map +1 -1
  111. package/dist/schema/state/sqlite/query-builder/impl.d.ts.map +1 -1
  112. package/dist/schema/state/sqlite/query-builder/impl.js +18 -23
  113. package/dist/schema/state/sqlite/query-builder/impl.js.map +1 -1
  114. package/dist/schema/state/sqlite/query-builder/impl.test.d.ts +1 -81
  115. package/dist/schema/state/sqlite/query-builder/impl.test.d.ts.map +1 -1
  116. package/dist/schema/state/sqlite/query-builder/impl.test.js +34 -20
  117. package/dist/schema/state/sqlite/query-builder/impl.test.js.map +1 -1
  118. package/dist/schema/state/sqlite/system-tables.d.ts +67 -62
  119. package/dist/schema/state/sqlite/system-tables.d.ts.map +1 -1
  120. package/dist/schema/state/sqlite/system-tables.js +8 -17
  121. package/dist/schema/state/sqlite/system-tables.js.map +1 -1
  122. package/dist/schema/state/sqlite/table-def.d.ts +1 -1
  123. package/dist/schema/state/sqlite/table-def.d.ts.map +1 -1
  124. package/dist/schema-management/migrations.d.ts +3 -1
  125. package/dist/schema-management/migrations.d.ts.map +1 -1
  126. package/dist/schema-management/migrations.js.map +1 -1
  127. package/dist/sql-queries/sql-queries.d.ts.map +1 -1
  128. package/dist/sql-queries/sql-queries.js +2 -0
  129. package/dist/sql-queries/sql-queries.js.map +1 -1
  130. package/dist/sqlite-types.d.ts +72 -0
  131. package/dist/sqlite-types.d.ts.map +1 -0
  132. package/dist/sqlite-types.js +5 -0
  133. package/dist/sqlite-types.js.map +1 -0
  134. package/dist/sync/ClientSessionSyncProcessor.d.ts +7 -4
  135. package/dist/sync/ClientSessionSyncProcessor.d.ts.map +1 -1
  136. package/dist/sync/ClientSessionSyncProcessor.js +17 -16
  137. package/dist/sync/ClientSessionSyncProcessor.js.map +1 -1
  138. package/dist/sync/index.d.ts +1 -1
  139. package/dist/sync/index.d.ts.map +1 -1
  140. package/dist/sync/index.js +1 -1
  141. package/dist/sync/index.js.map +1 -1
  142. package/dist/sync/next/graphology.d.ts.map +1 -1
  143. package/dist/sync/next/graphology.js +0 -6
  144. package/dist/sync/next/graphology.js.map +1 -1
  145. package/dist/sync/next/graphology_.d.ts +1 -1
  146. package/dist/sync/next/graphology_.d.ts.map +1 -1
  147. package/dist/sync/next/graphology_.js +1 -1
  148. package/dist/sync/next/graphology_.js.map +1 -1
  149. package/dist/sync/next/mod.d.ts +3 -3
  150. package/dist/sync/next/mod.d.ts.map +1 -1
  151. package/dist/sync/next/mod.js +3 -3
  152. package/dist/sync/next/mod.js.map +1 -1
  153. package/dist/sync/next/rebase-events.d.ts.map +1 -1
  154. package/dist/sync/next/rebase-events.js +1 -0
  155. package/dist/sync/next/rebase-events.js.map +1 -1
  156. package/dist/sync/next/test/compact-events.test.js +1 -1
  157. package/dist/sync/next/test/compact-events.test.js.map +1 -1
  158. package/dist/sync/next/test/event-fixtures.d.ts.map +1 -1
  159. package/dist/sync/next/test/event-fixtures.js +12 -3
  160. package/dist/sync/next/test/event-fixtures.js.map +1 -1
  161. package/dist/sync/sync.d.ts +2 -0
  162. package/dist/sync/sync.d.ts.map +1 -1
  163. package/dist/sync/sync.js +3 -0
  164. package/dist/sync/sync.js.map +1 -1
  165. package/dist/sync/syncstate.d.ts +13 -4
  166. package/dist/sync/syncstate.d.ts.map +1 -1
  167. package/dist/sync/syncstate.js +23 -10
  168. package/dist/sync/syncstate.js.map +1 -1
  169. package/dist/sync/syncstate.test.js +17 -18
  170. package/dist/sync/syncstate.test.js.map +1 -1
  171. package/dist/util.d.ts.map +1 -1
  172. package/dist/util.js +0 -1
  173. package/dist/util.js.map +1 -1
  174. package/dist/version.d.ts +1 -1
  175. package/dist/version.d.ts.map +1 -1
  176. package/dist/version.js +1 -1
  177. package/dist/version.js.map +1 -1
  178. package/package.json +6 -5
  179. package/src/ClientSessionLeaderThreadProxy.ts +40 -0
  180. package/src/adapter-types.ts +19 -165
  181. package/src/defs.ts +17 -0
  182. package/src/devtools/devtools-messages.ts +1 -1
  183. package/src/errors.ts +49 -0
  184. package/src/index.ts +11 -11
  185. package/src/leader-thread/LeaderSyncProcessor.ts +141 -180
  186. package/src/leader-thread/eventlog.ts +79 -57
  187. package/src/leader-thread/leader-worker-devtools.ts +1 -2
  188. package/src/leader-thread/make-leader-thread-layer.ts +52 -8
  189. package/src/leader-thread/materialize-event.ts +8 -1
  190. package/src/leader-thread/mod.ts +4 -3
  191. package/src/leader-thread/recreate-db.ts +99 -91
  192. package/src/leader-thread/types.ts +6 -11
  193. package/src/make-client-session.ts +2 -3
  194. package/src/rematerialize-from-eventlog.ts +10 -2
  195. package/src/schema/EventDef.ts +5 -3
  196. package/src/schema/EventSequenceNumber.test.ts +120 -3
  197. package/src/schema/EventSequenceNumber.ts +95 -23
  198. package/src/schema/LiveStoreEvent.ts +20 -4
  199. package/src/schema/events.ts +1 -1
  200. package/src/schema/mod.ts +6 -6
  201. package/src/schema/state/sqlite/client-document-def.test.ts +7 -5
  202. package/src/schema/state/sqlite/client-document-def.ts +36 -24
  203. package/src/schema/state/sqlite/db-schema/dsl/field-defs.ts +2 -2
  204. package/src/schema/state/sqlite/db-schema/dsl/mod.ts +16 -10
  205. package/src/schema/state/sqlite/db-schema/hash.ts +3 -4
  206. package/src/schema/state/sqlite/db-schema/mod.ts +1 -1
  207. package/src/schema/state/sqlite/mod.ts +6 -6
  208. package/src/schema/state/sqlite/query-builder/api.ts +38 -8
  209. package/src/schema/state/sqlite/query-builder/impl.test.ts +60 -20
  210. package/src/schema/state/sqlite/query-builder/impl.ts +19 -24
  211. package/src/schema/state/sqlite/system-tables.ts +9 -22
  212. package/src/schema/state/sqlite/table-def.ts +1 -1
  213. package/src/schema-management/migrations.ts +3 -1
  214. package/src/sql-queries/sql-queries.ts +2 -0
  215. package/src/sqlite-types.ts +76 -0
  216. package/src/sync/ClientSessionSyncProcessor.ts +29 -23
  217. package/src/sync/index.ts +1 -1
  218. package/src/sync/next/graphology.ts +3 -11
  219. package/src/sync/next/graphology_.ts +1 -1
  220. package/src/sync/next/mod.ts +3 -3
  221. package/src/sync/next/rebase-events.ts +2 -1
  222. package/src/sync/next/test/compact-events.test.ts +1 -1
  223. package/src/sync/next/test/event-fixtures.ts +12 -3
  224. package/src/sync/sync.ts +3 -0
  225. package/src/sync/syncstate.test.ts +17 -18
  226. package/src/sync/syncstate.ts +31 -10
  227. package/src/util.ts +0 -1
  228. package/src/version.ts +1 -1
@@ -1,14 +1,23 @@
1
1
  /// <reference lib="dom" />
2
2
  import { LS_DEV, shouldNeverHappen, TRACE_VERBOSE } from '@livestore/utils'
3
- import { Option, type Runtime, type Scope } from '@livestore/utils/effect'
4
- import { BucketQueue, Effect, FiberHandle, Queue, Schema, Stream, Subscribable } from '@livestore/utils/effect'
3
+ import {
4
+ BucketQueue,
5
+ Effect,
6
+ FiberHandle,
7
+ Option,
8
+ Queue,
9
+ type Runtime,
10
+ Schema,
11
+ type Scope,
12
+ Stream,
13
+ Subscribable,
14
+ } from '@livestore/utils/effect'
5
15
  import * as otel from '@opentelemetry/api'
6
16
 
7
- import type { ClientSession, UnexpectedError } from '../adapter-types.js'
17
+ import { type ClientSession, SyncError, type UnexpectedError } from '../adapter-types.js'
8
18
  import * as EventSequenceNumber from '../schema/EventSequenceNumber.js'
9
19
  import * as LiveStoreEvent from '../schema/LiveStoreEvent.js'
10
- import { getEventDef, type LiveStoreSchema, SystemTables } from '../schema/mod.js'
11
- import { sql } from '../util.js'
20
+ import { getEventDef, type LiveStoreSchema } from '../schema/mod.js'
12
21
  import * as SyncState from './syncstate.js'
13
22
 
14
23
  /**
@@ -21,6 +30,10 @@ import * as SyncState from './syncstate.js'
21
30
  * - We might need to make the rebase behaviour configurable e.g. to let users manually trigger a rebase
22
31
  *
23
32
  * Longer term we should evalutate whether we can unify the ClientSessionSyncProcessor with the LeaderSyncProcessor.
33
+ *
34
+ * The session and leader sync processor are different in the following ways:
35
+ * - The leader sync processor pulls regular LiveStore events, while the session sync processor pulls SyncState.PayloadUpstream items
36
+ * - The session sync processor has no downstream nodes.
24
37
  */
25
38
  export const makeClientSessionSyncProcessor = ({
26
39
  schema,
@@ -37,7 +50,7 @@ export const makeClientSessionSyncProcessor = ({
37
50
  clientSession: ClientSession
38
51
  runtime: Runtime.Runtime<Scope.Scope>
39
52
  materializeEvent: (
40
- eventDecoded: LiveStoreEvent.PartialAnyDecoded,
53
+ eventDecoded: LiveStoreEvent.AnyDecoded,
41
54
  options: { otelContext: otel.Context; withChangeset: boolean; materializerHashLeader: Option.Option<number> },
42
55
  ) => {
43
56
  writeTables: Set<string>
@@ -82,7 +95,10 @@ export const makeClientSessionSyncProcessor = ({
82
95
  let baseEventSequenceNumber = syncStateRef.current.localHead
83
96
  const encodedEventDefs = batch.map(({ name, args }) => {
84
97
  const eventDef = getEventDef(schema, name)
85
- const nextNumPair = EventSequenceNumber.nextPair(baseEventSequenceNumber, eventDef.eventDef.options.clientOnly)
98
+ const nextNumPair = EventSequenceNumber.nextPair({
99
+ seqNum: baseEventSequenceNumber,
100
+ isClient: eventDef.eventDef.options.clientOnly,
101
+ })
86
102
  baseEventSequenceNumber = nextNumPair.seqNum
87
103
  return new LiveStoreEvent.EncodedWithMeta(
88
104
  Schema.encodeUnknownSync(eventSchema)({
@@ -103,7 +119,7 @@ export const makeClientSessionSyncProcessor = ({
103
119
  })
104
120
 
105
121
  if (mergeResult._tag === 'unexpected-error') {
106
- return shouldNeverHappen('Unexpected error in client-session-sync-processor', mergeResult.cause)
122
+ return shouldNeverHappen('Unexpected error in client-session-sync-processor', mergeResult.message)
107
123
  }
108
124
 
109
125
  span.addEvent('local-push', {
@@ -155,7 +171,6 @@ export const makeClientSessionSyncProcessor = ({
155
171
  const otelContext = otel.trace.setSpan(otel.context.active(), span)
156
172
 
157
173
  const boot: ClientSessionSyncProcessor['boot'] = Effect.gen(function* () {
158
- // eslint-disable-next-line unicorn/prefer-global-this
159
174
  if (confirmUnsavedChanges && typeof window !== 'undefined' && typeof window.addEventListener === 'function') {
160
175
  const onBeforeUnload = (event: BeforeUnloadEvent) => {
161
176
  if (syncStateRef.current.pending.length > 0) {
@@ -184,18 +199,11 @@ export const makeClientSessionSyncProcessor = ({
184
199
 
185
200
  yield* FiberHandle.run(leaderPushingFiberHandle, backgroundLeaderPushing)
186
201
 
187
- const getMergeCounter = () =>
188
- clientSession.sqliteDb.select<{ mergeCounter: number }>(
189
- sql`SELECT mergeCounter FROM ${SystemTables.LEADER_MERGE_COUNTER_TABLE} WHERE id = 0`,
190
- )[0]?.mergeCounter ?? 0
191
-
192
202
  // NOTE We need to lazily call `.pull` as we want the cursor to be updated
193
203
  yield* Stream.suspend(() =>
194
- clientSession.leaderThread.events.pull({
195
- cursor: { mergeCounter: getMergeCounter(), eventNum: syncStateRef.current.localHead },
196
- }),
204
+ clientSession.leaderThread.events.pull({ cursor: syncStateRef.current.upstreamHead }),
197
205
  ).pipe(
198
- Stream.tap(({ payload, mergeCounter: leaderMergeCounter }) =>
206
+ Stream.tap(({ payload }) =>
199
207
  Effect.gen(function* () {
200
208
  // yield* Effect.logDebug('ClientSessionSyncProcessor:pull', payload)
201
209
 
@@ -211,13 +219,13 @@ export const makeClientSessionSyncProcessor = ({
211
219
  })
212
220
 
213
221
  if (mergeResult._tag === 'unexpected-error') {
214
- return yield* Effect.fail(mergeResult.cause)
222
+ return yield* new SyncError({ cause: mergeResult.message })
215
223
  } else if (mergeResult._tag === 'reject') {
216
224
  return shouldNeverHappen('Unexpected reject in client-session-sync-processor', mergeResult)
217
225
  }
218
226
 
219
227
  syncStateRef.current = mergeResult.newSyncState
220
- syncStateUpdateQueue.offer(mergeResult.newSyncState).pipe(Effect.runSync)
228
+ yield* syncStateUpdateQueue.offer(mergeResult.newSyncState)
221
229
 
222
230
  if (mergeResult._tag === 'rebase') {
223
231
  span.addEvent('merge:pull:rebase', {
@@ -226,7 +234,7 @@ export const makeClientSessionSyncProcessor = ({
226
234
  newEventsCount: mergeResult.newEvents.length,
227
235
  rollbackCount: mergeResult.rollbackEvents.length,
228
236
  res: TRACE_VERBOSE ? JSON.stringify(mergeResult) : undefined,
229
- leaderMergeCounter,
237
+ rebaseGeneration: mergeResult.newSyncState.localHead.rebaseGeneration,
230
238
  })
231
239
 
232
240
  debugInfo.rebaseCount++
@@ -243,7 +251,6 @@ export const makeClientSessionSyncProcessor = ({
243
251
  'merge:pull:rebase: rollback',
244
252
  mergeResult.rollbackEvents.length,
245
253
  ...mergeResult.rollbackEvents.slice(0, 10).map((_) => _.toJSON()),
246
- { leaderMergeCounter },
247
254
  ).pipe(Effect.provide(runtime), Effect.runSync)
248
255
  }
249
256
 
@@ -263,7 +270,6 @@ export const makeClientSessionSyncProcessor = ({
263
270
  payload: TRACE_VERBOSE ? JSON.stringify(payload) : undefined,
264
271
  newEventsCount: mergeResult.newEvents.length,
265
272
  res: TRACE_VERBOSE ? JSON.stringify(mergeResult) : undefined,
266
- leaderMergeCounter,
267
273
  })
268
274
 
269
275
  debugInfo.advanceCount++
package/src/sync/index.ts CHANGED
@@ -1,3 +1,3 @@
1
+ export * from './ClientSessionSyncProcessor.js'
1
2
  export * from './sync.js'
2
3
  export * from './validate-push-payload.js'
3
- export * from './ClientSessionSyncProcessor.js'
@@ -13,17 +13,9 @@ export declare class IGraph<
13
13
  constructor(options?: graphologyTypes.GraphOptions)
14
14
  }
15
15
 
16
- export const DirectedGraph = class DirectedGraph extends graphology.DirectedGraph {
17
- constructor(options?: graphologyTypes.GraphOptions) {
18
- super(options)
19
- }
20
- } as typeof IGraph
21
-
22
- export const Graph = class Graph extends graphology.Graph {
23
- constructor(options?: graphologyTypes.GraphOptions) {
24
- super(options)
25
- }
26
- } as typeof IGraph
16
+ export const DirectedGraph = class DirectedGraph extends graphology.DirectedGraph {} as typeof IGraph
17
+
18
+ export const Graph = class Graph extends graphology.Graph {} as typeof IGraph
27
19
 
28
20
  // export const graphology = graphology_ as graphologyTypes
29
21
 
@@ -1,2 +1,2 @@
1
- export * as graphology from './graphology.js'
2
1
  export { default as graphologyDag } from 'graphology-dag'
2
+ export * as graphology from './graphology.js'
@@ -1,5 +1,5 @@
1
- export * from './history-dag-common.js'
2
- export * from './history-dag.js'
3
- export * from './facts.js'
4
1
  export * from './compact-events.js'
2
+ export * from './facts.js'
3
+ export * from './history-dag.js'
4
+ export * from './history-dag-common.js'
5
5
  export * from './rebase-events.js'
@@ -3,8 +3,8 @@ import * as EventSequenceNumber from '../../schema/EventSequenceNumber.js'
3
3
  import type * as LiveStoreEvent from '../../schema/LiveStoreEvent.js'
4
4
  import {
5
5
  applyFactGroups,
6
- factsIntersect,
7
6
  type FactValidationResult,
7
+ factsIntersect,
8
8
  getFactsGroupForEventArgs,
9
9
  validateFacts,
10
10
  } from './facts.js'
@@ -38,6 +38,7 @@ export const defaultRebaseFn: RebaseFn = ({ pendingLocalEvents }) => {
38
38
  return { rebasedLocalEvents: pendingLocalEvents }
39
39
  }
40
40
 
41
+ // TODO replace in favour of current rebase impl
41
42
  export const rebaseEvents = ({
42
43
  rebaseFn,
43
44
  pendingLocalEvents,
@@ -64,7 +64,7 @@ const factsSetToString = (facts: EventDefFacts, prefix: string) =>
64
64
  export const customSerializer = {
65
65
  test: (val: unknown) => Array.isArray(val),
66
66
  print: (val: unknown[], _serialize: (item: unknown) => string) => {
67
- return '[\n' + (val as any[]).map((item) => ' ' + customStringify(item)).join('\n') + '\n]'
67
+ return `[\n${(val as any[]).map((item) => ` ${customStringify(item)}`).join('\n')}\n]`
68
68
  },
69
69
  } as any
70
70
 
@@ -144,7 +144,10 @@ export const toEventNodes = (
144
144
 
145
145
  const eventNodes = partialEvents.map((partialEvent) => {
146
146
  const eventDef = eventDefs[partialEvent.name]!
147
- const eventNum = EventSequenceNumber.nextPair(currentEventSequenceNumber, eventDef.options.clientOnly).seqNum
147
+ const eventNum = EventSequenceNumber.nextPair({
148
+ seqNum: currentEventSequenceNumber,
149
+ isClient: eventDef.options.clientOnly,
150
+ }).seqNum
148
151
  currentEventSequenceNumber = eventNum
149
152
 
150
153
  const factsSnapshot = factsSnapshotForDag(historyDagFromNodes(nodesAcc, { skipFactsCheck: true }), undefined)
@@ -221,8 +224,14 @@ const getParentNum = (eventNum: EventSequenceNumber.EventSequenceNumber): EventS
221
224
  const clientParentNum = eventNum.client - 1
222
225
 
223
226
  if (clientParentNum < 0) {
224
- return EventSequenceNumber.make({ global: globalParentNum - 1, client: EventSequenceNumber.clientDefault })
227
+ return EventSequenceNumber.make({
228
+ global: globalParentNum - 1,
229
+ client: EventSequenceNumber.clientDefault,
230
+ })
225
231
  }
226
232
 
227
- return EventSequenceNumber.make({ global: globalParentNum, client: clientParentNum })
233
+ return EventSequenceNumber.make({
234
+ global: globalParentNum,
235
+ client: clientParentNum,
236
+ })
228
237
  }
package/src/sync/sync.ts CHANGED
@@ -80,6 +80,7 @@ export type SyncBackend<TSyncMetadata = Schema.JsonValue> = {
80
80
 
81
81
  export class IsOfflineError extends Schema.TaggedError<IsOfflineError>()('IsOfflineError', {}) {}
82
82
 
83
+ // TODO gt rid of this error in favour of SyncError
83
84
  export class InvalidPushError extends Schema.TaggedError<InvalidPushError>()('InvalidPushError', {
84
85
  reason: Schema.Union(
85
86
  Schema.TaggedStruct('Unexpected', {
@@ -92,10 +93,12 @@ export class InvalidPushError extends Schema.TaggedError<InvalidPushError>()('In
92
93
  ),
93
94
  }) {}
94
95
 
96
+ // TODO gt rid of this error in favour of SyncError
95
97
  export class InvalidPullError extends Schema.TaggedError<InvalidPullError>()('InvalidPullError', {
96
98
  message: Schema.String,
97
99
  }) {}
98
100
 
101
+ // TODO gt rid of this error in favour of SyncError
99
102
  export class LeaderAheadError extends Schema.TaggedError<LeaderAheadError>()('LeaderAheadError', {
100
103
  minimumExpectedNum: EventSequenceNumber.EventSequenceNumber,
101
104
  providedNum: EventSequenceNumber.EventSequenceNumber,
@@ -1,4 +1,3 @@
1
- /* eslint-disable prefer-arrow/prefer-arrow-functions */
2
1
  import { describe, expect, it } from 'vitest'
3
2
 
4
3
  import * as EventSequenceNumber from '../schema/EventSequenceNumber.js'
@@ -7,10 +6,10 @@ import * as SyncState from './syncstate.js'
7
6
 
8
7
  class TestEvent extends LiveStoreEvent.EncodedWithMeta {
9
8
  constructor(
10
- seqNum: EventSequenceNumber.EventSequenceNumber | typeof EventSequenceNumber.EventSequenceNumber.Encoded,
11
- parentSeqNum: EventSequenceNumber.EventSequenceNumber,
9
+ seqNum: EventSequenceNumber.EventSequenceNumberInput,
10
+ parentSeqNum: EventSequenceNumber.EventSequenceNumberInput,
12
11
  public readonly payload: string,
13
- public readonly isLocal: boolean,
12
+ public readonly isClient: boolean,
14
13
  ) {
15
14
  super({
16
15
  seqNum: EventSequenceNumber.make(seqNum),
@@ -22,8 +21,8 @@ class TestEvent extends LiveStoreEvent.EncodedWithMeta {
22
21
  })
23
22
  }
24
23
 
25
- rebase_ = (parentSeqNum: EventSequenceNumber.EventSequenceNumber) => {
26
- return this.rebase(parentSeqNum, this.isLocal)
24
+ rebase_ = (parentSeqNum: EventSequenceNumber.EventSequenceNumber, rebaseGeneration: number) => {
25
+ return this.rebase({ parentSeqNum, isClient: this.isClient, rebaseGeneration })
27
26
  }
28
27
 
29
28
  // Only used for Vitest printing
@@ -41,7 +40,7 @@ const e2_1 = new TestEvent({ global: 2, client: 1 }, e2_0.seqNum, 'a', true)
41
40
 
42
41
  const isEqualEvent = LiveStoreEvent.isEqualEncoded
43
42
 
44
- const isClientEvent = (event: LiveStoreEvent.EncodedWithMeta) => (event as TestEvent).isLocal
43
+ const isClientEvent = (event: LiveStoreEvent.EncodedWithMeta) => (event as TestEvent).isClient
45
44
 
46
45
  describe('syncstate', () => {
47
46
  describe('merge', () => {
@@ -62,8 +61,8 @@ describe('syncstate', () => {
62
61
  upstreamHead: EventSequenceNumber.ROOT,
63
62
  localHead: e2_0.seqNum,
64
63
  })
65
- const e1_0_e2_0 = e1_0.rebase_(e2_0.seqNum)
66
- const e1_1_e2_1 = e1_1.rebase_(e1_0_e2_0.seqNum)
64
+ const e1_0_e2_0 = e1_0.rebase_(e2_0.seqNum, 0)
65
+ const e1_1_e2_1 = e1_1.rebase_(e1_0_e2_0.seqNum, 0)
67
66
  const result = merge({
68
67
  syncState,
69
68
  payload: SyncState.PayloadUpstreamRebase.make({
@@ -71,7 +70,7 @@ describe('syncstate', () => {
71
70
  newEvents: [e1_0_e2_0, e1_1_e2_1],
72
71
  }),
73
72
  })
74
- const e2_0_e3_0 = e2_0.rebase_(e1_0_e2_0.seqNum)
73
+ const e2_0_e3_0 = e2_0.rebase_(e1_0_e2_0.seqNum, 1)
75
74
  expectRebase(result)
76
75
  expectEventArraysEqual(result.newSyncState.pending, [e2_0_e3_0])
77
76
  expect(result.newSyncState.upstreamHead).toMatchObject(e1_1_e2_1.seqNum)
@@ -86,7 +85,7 @@ describe('syncstate', () => {
86
85
  upstreamHead: EventSequenceNumber.ROOT,
87
86
  localHead: e2_0.seqNum,
88
87
  })
89
- const e1_1_e2_0 = e1_1.rebase_(e1_0.seqNum)
88
+ const e1_1_e2_0 = e1_1.rebase_(e1_0.seqNum, 0)
90
89
  const result = merge({
91
90
  syncState,
92
91
  payload: SyncState.PayloadUpstreamRebase.make({
@@ -94,7 +93,7 @@ describe('syncstate', () => {
94
93
  rollbackEvents: [e1_1],
95
94
  }),
96
95
  })
97
- const e2_0_e3_0 = e2_0.rebase_(e1_1_e2_0.seqNum)
96
+ const e2_0_e3_0 = e2_0.rebase_(e1_1_e2_0.seqNum, 1)
98
97
  expectRebase(result)
99
98
  expectEventArraysEqual(result.newSyncState.pending, [e2_0_e3_0])
100
99
  expect(result.newSyncState.upstreamHead).toMatchObject(e1_1_e2_0.seqNum)
@@ -326,7 +325,7 @@ describe('syncstate', () => {
326
325
  })
327
326
  const result = merge({ syncState, payload: SyncState.PayloadUpstreamAdvance.make({ newEvents: [e1_1] }) })
328
327
 
329
- const e1_0_e1_2 = e1_0.rebase_(e1_1.seqNum)
328
+ const e1_0_e1_2 = e1_0.rebase_(e1_1.seqNum, 1)
330
329
 
331
330
  expectRebase(result)
332
331
  expectEventArraysEqual(result.newSyncState.pending, [e1_0_e1_2])
@@ -344,7 +343,7 @@ describe('syncstate', () => {
344
343
  localHead: e2_0_b.seqNum,
345
344
  })
346
345
  const result = merge({ syncState, payload: SyncState.PayloadUpstreamAdvance.make({ newEvents: [e2_0] }) })
347
- const e2_0_e3_0 = e2_0_b.rebase_(e2_0.seqNum)
346
+ const e2_0_e3_0 = e2_0_b.rebase_(e2_0.seqNum, 1)
348
347
 
349
348
  expectRebase(result)
350
349
  expectEventArraysEqual(result.newSyncState.pending, [e2_0_e3_0])
@@ -365,7 +364,7 @@ describe('syncstate', () => {
365
364
  payload: SyncState.PayloadUpstreamAdvance.make({ newEvents: [e1_1, e1_2, e1_3, e2_0] }),
366
365
  })
367
366
 
368
- const e1_0_e3_0 = e1_0.rebase_(e2_0.seqNum)
367
+ const e1_0_e3_0 = e1_0.rebase_(e2_0.seqNum, 1)
369
368
 
370
369
  expectRebase(result)
371
370
  expectEventArraysEqual(result.newSyncState.pending, [e1_0_e3_0])
@@ -384,7 +383,7 @@ describe('syncstate', () => {
384
383
  payload: SyncState.PayloadUpstreamAdvance.make({ newEvents: [e1_0, e1_2, e1_3, e2_0] }),
385
384
  })
386
385
 
387
- const e1_1_e2_1 = e1_1.rebase_(e2_0.seqNum)
386
+ const e1_1_e2_1 = e1_1.rebase_(e2_0.seqNum, 1)
388
387
 
389
388
  expectRebase(result)
390
389
  expectEventArraysEqual(result.newSyncState.pending, [e1_1_e2_1])
@@ -405,8 +404,8 @@ describe('syncstate', () => {
405
404
  payload: SyncState.PayloadUpstreamAdvance.make({ newEvents: [e1_1, e1_2, e1_3, e2_0] }),
406
405
  })
407
406
 
408
- const e1_0_e2_1 = e1_0.rebase_(e2_0.seqNum)
409
- const e1_1_e2_2 = e1_1.rebase_(e1_0_e2_1.seqNum)
407
+ const e1_0_e2_1 = e1_0.rebase_(e2_0.seqNum, 1)
408
+ const e1_1_e2_2 = e1_1.rebase_(e1_0_e2_1.seqNum, 1)
410
409
 
411
410
  expectRebase(result)
412
411
  expectEventArraysEqual(result.newSyncState.pending, [e1_0_e2_1, e1_1_e2_2])
@@ -1,7 +1,6 @@
1
1
  import { casesHandled, LS_DEV, shouldNeverHappen } from '@livestore/utils'
2
2
  import { Match, ReadonlyArray, Schema } from '@livestore/utils/effect'
3
3
 
4
- import { UnexpectedError } from '../adapter-types.js'
5
4
  import * as EventSequenceNumber from '../schema/EventSequenceNumber.js'
6
5
  import * as LiveStoreEvent from '../schema/LiveStoreEvent.js'
7
6
 
@@ -162,7 +161,7 @@ export class MergeResultReject extends Schema.Class<MergeResultReject>('MergeRes
162
161
 
163
162
  export class MergeResultUnexpectedError extends Schema.Class<MergeResultUnexpectedError>('MergeResultUnexpectedError')({
164
163
  _tag: Schema.Literal('unexpected-error'),
165
- cause: UnexpectedError,
164
+ message: Schema.String,
166
165
  }) {}
167
166
 
168
167
  export class MergeResult extends Schema.Union(
@@ -172,15 +171,29 @@ export class MergeResult extends Schema.Union(
172
171
  MergeResultUnexpectedError,
173
172
  ) {}
174
173
 
175
- const unexpectedError = (cause: unknown): MergeResultUnexpectedError => {
174
+ export const payloadFromMergeResult = (
175
+ mergeResult: typeof MergeResultAdvance.Type | typeof MergeResultRebase.Type,
176
+ ): typeof PayloadUpstream.Type =>
177
+ Match.value(mergeResult).pipe(
178
+ Match.tag('advance', (result) => ({
179
+ _tag: 'upstream-advance' as const,
180
+ newEvents: result.newEvents,
181
+ })),
182
+ Match.tag('rebase', (result) => ({
183
+ _tag: 'upstream-rebase' as const,
184
+ newEvents: result.newEvents,
185
+ rollbackEvents: result.rollbackEvents,
186
+ })),
187
+ Match.exhaustive,
188
+ )
189
+
190
+ const unexpectedError = (message: string): MergeResultUnexpectedError => {
176
191
  if (LS_DEV) {
192
+ // biome-ignore lint/suspicious/noDebugger: debug
177
193
  debugger
178
194
  }
179
195
 
180
- return MergeResultUnexpectedError.make({
181
- _tag: 'unexpected-error',
182
- cause: new UnexpectedError({ cause }),
183
- })
196
+ return MergeResultUnexpectedError.make({ _tag: 'unexpected-error', message })
184
197
  }
185
198
 
186
199
  // TODO Idea: call merge recursively through hierarchy levels
@@ -382,7 +395,10 @@ export const merge = ({
382
395
  EventSequenceNumber.isGreaterThan(newEventsFirst.seqNum, syncState.localHead) === false
383
396
 
384
397
  if (invalidEventSequenceNumber) {
385
- const expectedMinimumId = EventSequenceNumber.nextPair(syncState.localHead, true).seqNum
398
+ const expectedMinimumId = EventSequenceNumber.nextPair({
399
+ seqNum: syncState.localHead,
400
+ isClient: true,
401
+ }).seqNum
386
402
  return validateMergeResult(
387
403
  MergeResultReject.make({
388
404
  _tag: 'reject',
@@ -466,9 +482,14 @@ const rebaseEvents = ({
466
482
  isClientEvent: (event: LiveStoreEvent.EncodedWithMeta) => boolean
467
483
  }): ReadonlyArray<LiveStoreEvent.EncodedWithMeta> => {
468
484
  let prevEventSequenceNumber = baseEventSequenceNumber
485
+ const rebaseGeneration = baseEventSequenceNumber.rebaseGeneration + 1
469
486
  return events.map((event) => {
470
- const isLocal = isClientEvent(event)
471
- const newEvent = event.rebase(prevEventSequenceNumber, isLocal)
487
+ const isClient = isClientEvent(event)
488
+ const newEvent = event.rebase({
489
+ parentSeqNum: prevEventSequenceNumber,
490
+ isClient,
491
+ rebaseGeneration,
492
+ })
472
493
  prevEventSequenceNumber = newEvent.seqNum
473
494
  return newEvent
474
495
  })
package/src/util.ts CHANGED
@@ -30,7 +30,6 @@ export const sql = (template: TemplateStringsArray, ...args: unknown[]): string
30
30
  str += template[i] + String(arg)
31
31
  }
32
32
 
33
- // eslint-disable-next-line unicorn/prefer-at
34
33
  return str + template[template.length - 1]
35
34
  }
36
35
 
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.0.0-snapshot-f5ece014485b5ab43795c218f7ba7cfa32c81707' as const
5
+ export const liveStoreVersion = '0.0.0-snapshot-057a9e3a18ca69a310d4eb8cf35a34e94fa1841e' as const
6
6
 
7
7
  /**
8
8
  * This version number is incremented whenever the internal storage format changes in a breaking way.