@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.
- package/dist/.tsbuildinfo +1 -1
- package/dist/ClientSessionLeaderThreadProxy.d.ts +35 -0
- package/dist/ClientSessionLeaderThreadProxy.d.ts.map +1 -0
- package/dist/ClientSessionLeaderThreadProxy.js +6 -0
- package/dist/ClientSessionLeaderThreadProxy.js.map +1 -0
- package/dist/adapter-types.d.ts +10 -161
- package/dist/adapter-types.d.ts.map +1 -1
- package/dist/adapter-types.js +5 -49
- package/dist/adapter-types.js.map +1 -1
- package/dist/defs.d.ts +20 -0
- package/dist/defs.d.ts.map +1 -0
- package/dist/defs.js +12 -0
- package/dist/defs.js.map +1 -0
- package/dist/devtools/devtools-messages-client-session.d.ts +23 -21
- package/dist/devtools/devtools-messages-client-session.d.ts.map +1 -1
- package/dist/devtools/devtools-messages-common.d.ts +6 -6
- package/dist/devtools/devtools-messages-common.d.ts.map +1 -1
- package/dist/devtools/devtools-messages-leader.d.ts +26 -24
- package/dist/devtools/devtools-messages-leader.d.ts.map +1 -1
- package/dist/devtools/devtools-messages.d.ts +1 -1
- package/dist/devtools/devtools-messages.d.ts.map +1 -1
- package/dist/devtools/devtools-messages.js +1 -1
- package/dist/devtools/devtools-messages.js.map +1 -1
- package/dist/errors.d.ts +50 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +36 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +11 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -11
- package/dist/index.js.map +1 -1
- package/dist/leader-thread/LeaderSyncProcessor.d.ts +6 -7
- package/dist/leader-thread/LeaderSyncProcessor.d.ts.map +1 -1
- package/dist/leader-thread/LeaderSyncProcessor.js +112 -122
- package/dist/leader-thread/LeaderSyncProcessor.js.map +1 -1
- package/dist/leader-thread/eventlog.d.ts +17 -6
- package/dist/leader-thread/eventlog.d.ts.map +1 -1
- package/dist/leader-thread/eventlog.js +33 -18
- package/dist/leader-thread/eventlog.js.map +1 -1
- package/dist/leader-thread/leader-worker-devtools.d.ts.map +1 -1
- package/dist/leader-thread/leader-worker-devtools.js +1 -2
- package/dist/leader-thread/leader-worker-devtools.js.map +1 -1
- package/dist/leader-thread/make-leader-thread-layer.d.ts.map +1 -1
- package/dist/leader-thread/make-leader-thread-layer.js +37 -7
- package/dist/leader-thread/make-leader-thread-layer.js.map +1 -1
- package/dist/leader-thread/materialize-event.d.ts.map +1 -1
- package/dist/leader-thread/materialize-event.js +7 -1
- package/dist/leader-thread/materialize-event.js.map +1 -1
- package/dist/leader-thread/mod.d.ts +4 -3
- package/dist/leader-thread/mod.d.ts.map +1 -1
- package/dist/leader-thread/mod.js +4 -3
- package/dist/leader-thread/mod.js.map +1 -1
- package/dist/leader-thread/recreate-db.d.ts +13 -6
- package/dist/leader-thread/recreate-db.d.ts.map +1 -1
- package/dist/leader-thread/recreate-db.js +1 -3
- package/dist/leader-thread/recreate-db.js.map +1 -1
- package/dist/leader-thread/types.d.ts +5 -7
- package/dist/leader-thread/types.d.ts.map +1 -1
- package/dist/make-client-session.d.ts +1 -1
- package/dist/make-client-session.d.ts.map +1 -1
- package/dist/make-client-session.js +1 -1
- package/dist/make-client-session.js.map +1 -1
- package/dist/rematerialize-from-eventlog.d.ts +1 -1
- package/dist/rematerialize-from-eventlog.d.ts.map +1 -1
- package/dist/rematerialize-from-eventlog.js +10 -2
- package/dist/rematerialize-from-eventlog.js.map +1 -1
- package/dist/schema/EventDef.d.ts +2 -2
- package/dist/schema/EventDef.d.ts.map +1 -1
- package/dist/schema/EventDef.js +2 -2
- package/dist/schema/EventDef.js.map +1 -1
- package/dist/schema/EventSequenceNumber.d.ts +20 -2
- package/dist/schema/EventSequenceNumber.d.ts.map +1 -1
- package/dist/schema/EventSequenceNumber.js +71 -19
- package/dist/schema/EventSequenceNumber.js.map +1 -1
- package/dist/schema/EventSequenceNumber.test.js +88 -3
- package/dist/schema/EventSequenceNumber.test.js.map +1 -1
- package/dist/schema/LiveStoreEvent.d.ts +23 -9
- package/dist/schema/LiveStoreEvent.d.ts.map +1 -1
- package/dist/schema/LiveStoreEvent.js +12 -4
- package/dist/schema/LiveStoreEvent.js.map +1 -1
- package/dist/schema/events.d.ts +1 -1
- package/dist/schema/events.d.ts.map +1 -1
- package/dist/schema/events.js +1 -1
- package/dist/schema/events.js.map +1 -1
- package/dist/schema/mod.d.ts +6 -6
- package/dist/schema/mod.d.ts.map +1 -1
- package/dist/schema/mod.js +6 -6
- package/dist/schema/mod.js.map +1 -1
- package/dist/schema/state/sqlite/client-document-def.d.ts.map +1 -1
- package/dist/schema/state/sqlite/client-document-def.js.map +1 -1
- package/dist/schema/state/sqlite/client-document-def.test.js +3 -5
- package/dist/schema/state/sqlite/client-document-def.test.js.map +1 -1
- package/dist/schema/state/sqlite/db-schema/dsl/field-defs.js +2 -2
- package/dist/schema/state/sqlite/db-schema/dsl/field-defs.js.map +1 -1
- package/dist/schema/state/sqlite/db-schema/dsl/mod.d.ts.map +1 -1
- package/dist/schema/state/sqlite/db-schema/dsl/mod.js.map +1 -1
- package/dist/schema/state/sqlite/db-schema/hash.d.ts.map +1 -1
- package/dist/schema/state/sqlite/db-schema/hash.js +3 -2
- package/dist/schema/state/sqlite/db-schema/hash.js.map +1 -1
- package/dist/schema/state/sqlite/db-schema/mod.d.ts +1 -1
- package/dist/schema/state/sqlite/db-schema/mod.d.ts.map +1 -1
- package/dist/schema/state/sqlite/db-schema/mod.js +1 -1
- package/dist/schema/state/sqlite/db-schema/mod.js.map +1 -1
- package/dist/schema/state/sqlite/mod.d.ts +3 -3
- package/dist/schema/state/sqlite/mod.d.ts.map +1 -1
- package/dist/schema/state/sqlite/mod.js +2 -2
- package/dist/schema/state/sqlite/mod.js.map +1 -1
- package/dist/schema/state/sqlite/query-builder/api.d.ts +35 -8
- package/dist/schema/state/sqlite/query-builder/api.d.ts.map +1 -1
- package/dist/schema/state/sqlite/query-builder/api.js.map +1 -1
- package/dist/schema/state/sqlite/query-builder/impl.d.ts.map +1 -1
- package/dist/schema/state/sqlite/query-builder/impl.js +18 -23
- package/dist/schema/state/sqlite/query-builder/impl.js.map +1 -1
- package/dist/schema/state/sqlite/query-builder/impl.test.d.ts +1 -81
- package/dist/schema/state/sqlite/query-builder/impl.test.d.ts.map +1 -1
- package/dist/schema/state/sqlite/query-builder/impl.test.js +34 -20
- package/dist/schema/state/sqlite/query-builder/impl.test.js.map +1 -1
- package/dist/schema/state/sqlite/system-tables.d.ts +67 -62
- package/dist/schema/state/sqlite/system-tables.d.ts.map +1 -1
- package/dist/schema/state/sqlite/system-tables.js +8 -17
- package/dist/schema/state/sqlite/system-tables.js.map +1 -1
- package/dist/schema/state/sqlite/table-def.d.ts +1 -1
- package/dist/schema/state/sqlite/table-def.d.ts.map +1 -1
- package/dist/schema-management/migrations.d.ts +3 -1
- package/dist/schema-management/migrations.d.ts.map +1 -1
- package/dist/schema-management/migrations.js.map +1 -1
- package/dist/sql-queries/sql-queries.d.ts.map +1 -1
- package/dist/sql-queries/sql-queries.js +2 -0
- package/dist/sql-queries/sql-queries.js.map +1 -1
- package/dist/sqlite-types.d.ts +72 -0
- package/dist/sqlite-types.d.ts.map +1 -0
- package/dist/sqlite-types.js +5 -0
- package/dist/sqlite-types.js.map +1 -0
- package/dist/sync/ClientSessionSyncProcessor.d.ts +7 -4
- package/dist/sync/ClientSessionSyncProcessor.d.ts.map +1 -1
- package/dist/sync/ClientSessionSyncProcessor.js +17 -16
- package/dist/sync/ClientSessionSyncProcessor.js.map +1 -1
- package/dist/sync/index.d.ts +1 -1
- package/dist/sync/index.d.ts.map +1 -1
- package/dist/sync/index.js +1 -1
- package/dist/sync/index.js.map +1 -1
- package/dist/sync/next/graphology.d.ts.map +1 -1
- package/dist/sync/next/graphology.js +0 -6
- package/dist/sync/next/graphology.js.map +1 -1
- package/dist/sync/next/graphology_.d.ts +1 -1
- package/dist/sync/next/graphology_.d.ts.map +1 -1
- package/dist/sync/next/graphology_.js +1 -1
- package/dist/sync/next/graphology_.js.map +1 -1
- package/dist/sync/next/mod.d.ts +3 -3
- package/dist/sync/next/mod.d.ts.map +1 -1
- package/dist/sync/next/mod.js +3 -3
- package/dist/sync/next/mod.js.map +1 -1
- package/dist/sync/next/rebase-events.d.ts.map +1 -1
- package/dist/sync/next/rebase-events.js +1 -0
- package/dist/sync/next/rebase-events.js.map +1 -1
- package/dist/sync/next/test/compact-events.test.js +1 -1
- package/dist/sync/next/test/compact-events.test.js.map +1 -1
- package/dist/sync/next/test/event-fixtures.d.ts.map +1 -1
- package/dist/sync/next/test/event-fixtures.js +12 -3
- package/dist/sync/next/test/event-fixtures.js.map +1 -1
- package/dist/sync/sync.d.ts +2 -0
- package/dist/sync/sync.d.ts.map +1 -1
- package/dist/sync/sync.js +3 -0
- package/dist/sync/sync.js.map +1 -1
- package/dist/sync/syncstate.d.ts +13 -4
- package/dist/sync/syncstate.d.ts.map +1 -1
- package/dist/sync/syncstate.js +23 -10
- package/dist/sync/syncstate.js.map +1 -1
- package/dist/sync/syncstate.test.js +17 -18
- package/dist/sync/syncstate.test.js.map +1 -1
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +0 -1
- package/dist/util.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +6 -5
- package/src/ClientSessionLeaderThreadProxy.ts +40 -0
- package/src/adapter-types.ts +19 -165
- package/src/defs.ts +17 -0
- package/src/devtools/devtools-messages.ts +1 -1
- package/src/errors.ts +49 -0
- package/src/index.ts +11 -11
- package/src/leader-thread/LeaderSyncProcessor.ts +141 -180
- package/src/leader-thread/eventlog.ts +79 -57
- package/src/leader-thread/leader-worker-devtools.ts +1 -2
- package/src/leader-thread/make-leader-thread-layer.ts +52 -8
- package/src/leader-thread/materialize-event.ts +8 -1
- package/src/leader-thread/mod.ts +4 -3
- package/src/leader-thread/recreate-db.ts +99 -91
- package/src/leader-thread/types.ts +6 -11
- package/src/make-client-session.ts +2 -3
- package/src/rematerialize-from-eventlog.ts +10 -2
- package/src/schema/EventDef.ts +5 -3
- package/src/schema/EventSequenceNumber.test.ts +120 -3
- package/src/schema/EventSequenceNumber.ts +95 -23
- package/src/schema/LiveStoreEvent.ts +20 -4
- package/src/schema/events.ts +1 -1
- package/src/schema/mod.ts +6 -6
- package/src/schema/state/sqlite/client-document-def.test.ts +7 -5
- package/src/schema/state/sqlite/client-document-def.ts +36 -24
- package/src/schema/state/sqlite/db-schema/dsl/field-defs.ts +2 -2
- package/src/schema/state/sqlite/db-schema/dsl/mod.ts +16 -10
- package/src/schema/state/sqlite/db-schema/hash.ts +3 -4
- package/src/schema/state/sqlite/db-schema/mod.ts +1 -1
- package/src/schema/state/sqlite/mod.ts +6 -6
- package/src/schema/state/sqlite/query-builder/api.ts +38 -8
- package/src/schema/state/sqlite/query-builder/impl.test.ts +60 -20
- package/src/schema/state/sqlite/query-builder/impl.ts +19 -24
- package/src/schema/state/sqlite/system-tables.ts +9 -22
- package/src/schema/state/sqlite/table-def.ts +1 -1
- package/src/schema-management/migrations.ts +3 -1
- package/src/sql-queries/sql-queries.ts +2 -0
- package/src/sqlite-types.ts +76 -0
- package/src/sync/ClientSessionSyncProcessor.ts +29 -23
- package/src/sync/index.ts +1 -1
- package/src/sync/next/graphology.ts +3 -11
- package/src/sync/next/graphology_.ts +1 -1
- package/src/sync/next/mod.ts +3 -3
- package/src/sync/next/rebase-events.ts +2 -1
- package/src/sync/next/test/compact-events.test.ts +1 -1
- package/src/sync/next/test/event-fixtures.ts +12 -3
- package/src/sync/sync.ts +3 -0
- package/src/sync/syncstate.test.ts +17 -18
- package/src/sync/syncstate.ts +31 -10
- package/src/util.ts +0 -1
- 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 {
|
|
4
|
-
|
|
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
|
|
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
|
|
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.
|
|
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(
|
|
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.
|
|
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
|
|
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*
|
|
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)
|
|
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
|
-
|
|
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
|
@@ -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
|
-
|
|
18
|
-
|
|
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
|
|
package/src/sync/next/mod.ts
CHANGED
|
@@ -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
|
|
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(
|
|
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({
|
|
227
|
+
return EventSequenceNumber.make({
|
|
228
|
+
global: globalParentNum - 1,
|
|
229
|
+
client: EventSequenceNumber.clientDefault,
|
|
230
|
+
})
|
|
225
231
|
}
|
|
226
232
|
|
|
227
|
-
return EventSequenceNumber.make({
|
|
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.
|
|
11
|
-
parentSeqNum: EventSequenceNumber.
|
|
9
|
+
seqNum: EventSequenceNumber.EventSequenceNumberInput,
|
|
10
|
+
parentSeqNum: EventSequenceNumber.EventSequenceNumberInput,
|
|
12
11
|
public readonly payload: string,
|
|
13
|
-
public readonly
|
|
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.
|
|
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).
|
|
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])
|
package/src/sync/syncstate.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
|
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(
|
|
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
|
|
471
|
-
const newEvent = event.rebase(
|
|
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
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-
|
|
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.
|