@livestore/common 0.3.0-dev.11 → 0.3.0-dev.3
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/adapter-types.d.ts +35 -47
- package/dist/adapter-types.d.ts.map +1 -1
- package/dist/adapter-types.js.map +1 -1
- package/dist/derived-mutations.d.ts +4 -4
- package/dist/derived-mutations.d.ts.map +1 -1
- package/dist/derived-mutations.test.js.map +1 -1
- package/dist/devtools/devtools-bridge.d.ts +1 -2
- package/dist/devtools/devtools-bridge.d.ts.map +1 -1
- package/dist/devtools/devtools-messages.d.ts +592 -3
- package/dist/devtools/devtools-messages.d.ts.map +1 -1
- package/dist/devtools/devtools-messages.js +171 -3
- package/dist/devtools/devtools-messages.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/init-singleton-tables.d.ts +2 -2
- package/dist/init-singleton-tables.d.ts.map +1 -1
- package/dist/init-singleton-tables.js.map +1 -1
- package/dist/leader-thread/apply-mutation.d.ts +2 -5
- package/dist/leader-thread/apply-mutation.d.ts.map +1 -1
- package/dist/leader-thread/apply-mutation.js +29 -41
- package/dist/leader-thread/apply-mutation.js.map +1 -1
- package/dist/leader-thread/connection.d.ts +4 -4
- package/dist/leader-thread/connection.d.ts.map +1 -1
- package/dist/leader-thread/connection.js +5 -5
- package/dist/leader-thread/connection.js.map +1 -1
- package/dist/leader-thread/leader-sync-processor.d.ts +2 -2
- package/dist/leader-thread/leader-sync-processor.d.ts.map +1 -1
- package/dist/leader-thread/leader-sync-processor.js +12 -20
- package/dist/leader-thread/leader-sync-processor.js.map +1 -1
- package/dist/leader-thread/leader-worker-devtools.d.ts +1 -1
- package/dist/leader-thread/leader-worker-devtools.d.ts.map +1 -1
- package/dist/leader-thread/leader-worker-devtools.js +81 -37
- package/dist/leader-thread/leader-worker-devtools.js.map +1 -1
- package/dist/leader-thread/make-leader-thread-layer.d.ts +11 -12
- package/dist/leader-thread/make-leader-thread-layer.d.ts.map +1 -1
- package/dist/leader-thread/make-leader-thread-layer.js +14 -33
- package/dist/leader-thread/make-leader-thread-layer.js.map +1 -1
- package/dist/leader-thread/mutationlog.d.ts +19 -6
- package/dist/leader-thread/mutationlog.d.ts.map +1 -1
- package/dist/leader-thread/mutationlog.js +6 -7
- package/dist/leader-thread/mutationlog.js.map +1 -1
- package/dist/leader-thread/pull-queue-set.d.ts.map +1 -1
- package/dist/leader-thread/recreate-db.d.ts.map +1 -1
- package/dist/leader-thread/recreate-db.js +18 -24
- package/dist/leader-thread/recreate-db.js.map +1 -1
- package/dist/leader-thread/types.d.ts +16 -36
- package/dist/leader-thread/types.d.ts.map +1 -1
- package/dist/leader-thread/types.js.map +1 -1
- package/dist/mutation.d.ts +2 -9
- package/dist/mutation.d.ts.map +1 -1
- package/dist/mutation.js +5 -5
- package/dist/mutation.js.map +1 -1
- package/dist/query-builder/impl.d.ts +1 -1
- package/dist/rehydrate-from-mutationlog.d.ts +5 -5
- package/dist/rehydrate-from-mutationlog.d.ts.map +1 -1
- package/dist/rehydrate-from-mutationlog.js +19 -13
- package/dist/rehydrate-from-mutationlog.js.map +1 -1
- package/dist/schema/EventId.d.ts +14 -16
- package/dist/schema/EventId.d.ts.map +1 -1
- package/dist/schema/EventId.js +7 -15
- package/dist/schema/EventId.js.map +1 -1
- package/dist/schema/MutationEvent.d.ts +80 -49
- package/dist/schema/MutationEvent.d.ts.map +1 -1
- package/dist/schema/MutationEvent.js +15 -32
- package/dist/schema/MutationEvent.js.map +1 -1
- package/dist/schema/system-tables.d.ts +26 -26
- package/dist/schema/system-tables.d.ts.map +1 -1
- package/dist/schema/system-tables.js +11 -19
- package/dist/schema/system-tables.js.map +1 -1
- package/dist/schema-management/common.d.ts +3 -3
- package/dist/schema-management/common.d.ts.map +1 -1
- package/dist/schema-management/common.js.map +1 -1
- package/dist/schema-management/migrations.d.ts +4 -4
- package/dist/schema-management/migrations.d.ts.map +1 -1
- package/dist/schema-management/migrations.js +6 -6
- package/dist/schema-management/migrations.js.map +1 -1
- package/dist/sync/client-session-sync-processor.d.ts +4 -4
- package/dist/sync/client-session-sync-processor.d.ts.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/history-dag-common.d.ts +4 -1
- package/dist/sync/next/history-dag-common.d.ts.map +1 -1
- package/dist/sync/next/history-dag-common.js +1 -1
- package/dist/sync/next/history-dag-common.js.map +1 -1
- package/dist/sync/next/rebase-events.d.ts +3 -3
- package/dist/sync/next/rebase-events.d.ts.map +1 -1
- package/dist/sync/next/rebase-events.js +2 -3
- package/dist/sync/next/rebase-events.js.map +1 -1
- package/dist/sync/next/test/mutation-fixtures.d.ts +7 -7
- package/dist/sync/next/test/mutation-fixtures.d.ts.map +1 -1
- package/dist/sync/next/test/mutation-fixtures.js +9 -3
- package/dist/sync/next/test/mutation-fixtures.js.map +1 -1
- package/dist/sync/sync.d.ts +11 -21
- package/dist/sync/sync.d.ts.map +1 -1
- package/dist/sync/sync.js.map +1 -1
- package/dist/sync/syncstate.d.ts +23 -45
- package/dist/sync/syncstate.d.ts.map +1 -1
- package/dist/sync/syncstate.js +12 -56
- package/dist/sync/syncstate.js.map +1 -1
- package/dist/sync/syncstate.test.js +69 -125
- package/dist/sync/syncstate.test.js.map +1 -1
- package/dist/sync/validate-push-payload.d.ts +2 -2
- package/dist/sync/validate-push-payload.d.ts.map +1 -1
- package/dist/sync/validate-push-payload.js +2 -2
- package/dist/sync/validate-push-payload.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 +5 -6
- package/src/adapter-types.ts +40 -39
- package/src/derived-mutations.test.ts +1 -1
- package/src/derived-mutations.ts +5 -9
- package/src/devtools/devtools-bridge.ts +1 -2
- package/src/devtools/devtools-messages.ts +243 -3
- package/src/index.ts +6 -0
- package/src/init-singleton-tables.ts +2 -2
- package/src/leader-thread/apply-mutation.ts +35 -53
- package/src/leader-thread/connection.ts +7 -7
- package/src/leader-thread/{LeaderSyncProcessor.ts → leader-sync-processor.ts} +268 -306
- package/src/leader-thread/leader-worker-devtools.ts +124 -52
- package/src/leader-thread/make-leader-thread-layer.ts +30 -62
- package/src/leader-thread/mutationlog.ts +10 -14
- package/src/leader-thread/recreate-db.ts +20 -24
- package/src/leader-thread/types.ts +20 -41
- package/src/mutation.ts +7 -17
- package/src/rehydrate-from-mutationlog.ts +26 -18
- package/src/schema/EventId.ts +9 -23
- package/src/schema/MutationEvent.ts +24 -46
- package/src/schema/system-tables.ts +11 -19
- package/src/schema-management/common.ts +3 -3
- package/src/schema-management/migrations.ts +10 -10
- package/src/sync/{ClientSessionSyncProcessor.ts → client-session-sync-processor.ts} +19 -26
- package/src/sync/index.ts +1 -1
- package/src/sync/next/history-dag-common.ts +1 -1
- package/src/sync/next/rebase-events.ts +7 -7
- package/src/sync/next/test/mutation-fixtures.ts +10 -3
- package/src/sync/sync.ts +6 -19
- package/src/sync/syncstate.test.ts +67 -127
- package/src/sync/syncstate.ts +19 -21
- package/src/sync/validate-push-payload.ts +4 -7
- package/src/version.ts +1 -1
- package/dist/devtools/devtool-message-leader.d.ts +0 -2
- package/dist/devtools/devtool-message-leader.d.ts.map +0 -1
- package/dist/devtools/devtool-message-leader.js +0 -2
- package/dist/devtools/devtool-message-leader.js.map +0 -1
- package/dist/devtools/devtools-messages-client-session.d.ts +0 -297
- package/dist/devtools/devtools-messages-client-session.d.ts.map +0 -1
- package/dist/devtools/devtools-messages-client-session.js +0 -61
- package/dist/devtools/devtools-messages-client-session.js.map +0 -1
- package/dist/devtools/devtools-messages-common.d.ts +0 -65
- package/dist/devtools/devtools-messages-common.d.ts.map +0 -1
- package/dist/devtools/devtools-messages-common.js +0 -35
- package/dist/devtools/devtools-messages-common.js.map +0 -1
- package/dist/devtools/devtools-messages-leader.d.ts +0 -261
- package/dist/devtools/devtools-messages-leader.d.ts.map +0 -1
- package/dist/devtools/devtools-messages-leader.js +0 -85
- package/dist/devtools/devtools-messages-leader.js.map +0 -1
- package/dist/leader-thread/LeaderSyncProcessor.d.ts +0 -37
- package/dist/leader-thread/LeaderSyncProcessor.d.ts.map +0 -1
- package/dist/leader-thread/LeaderSyncProcessor.js +0 -432
- package/dist/leader-thread/LeaderSyncProcessor.js.map +0 -1
- package/dist/schema/EventId.test.d.ts +0 -2
- package/dist/schema/EventId.test.d.ts.map +0 -1
- package/dist/schema/EventId.test.js +0 -11
- package/dist/schema/EventId.test.js.map +0 -1
- package/dist/schema/MutationEvent.test.d.ts +0 -2
- package/dist/schema/MutationEvent.test.d.ts.map +0 -1
- package/dist/schema/MutationEvent.test.js +0 -2
- package/dist/schema/MutationEvent.test.js.map +0 -1
- package/dist/sync/ClientSessionSyncProcessor.d.ts +0 -43
- package/dist/sync/ClientSessionSyncProcessor.d.ts.map +0 -1
- package/dist/sync/ClientSessionSyncProcessor.js +0 -141
- package/dist/sync/ClientSessionSyncProcessor.js.map +0 -1
- package/src/devtools/devtools-messages-client-session.ts +0 -109
- package/src/devtools/devtools-messages-common.ts +0 -52
- package/src/devtools/devtools-messages-leader.ts +0 -115
- package/src/schema/EventId.test.ts +0 -12
@@ -6,7 +6,6 @@ import type {
|
|
6
6
|
Option,
|
7
7
|
Queue,
|
8
8
|
Scope,
|
9
|
-
Subscribable,
|
10
9
|
SubscriptionRef,
|
11
10
|
WebChannel,
|
12
11
|
} from '@livestore/utils/effect'
|
@@ -16,14 +15,14 @@ import type {
|
|
16
15
|
BootStatus,
|
17
16
|
Devtools,
|
18
17
|
InvalidPushError,
|
19
|
-
|
18
|
+
MakeSynchronousDatabase,
|
20
19
|
PersistenceInfo,
|
21
|
-
SqliteDb,
|
22
20
|
SyncBackend,
|
21
|
+
SynchronousDatabase,
|
23
22
|
UnexpectedError,
|
24
23
|
} from '../index.js'
|
25
24
|
import type { EventId, LiveStoreSchema, MutationEvent } from '../schema/mod.js'
|
26
|
-
import type
|
25
|
+
import type { PayloadUpstream, SyncState } from '../sync/syncstate.js'
|
27
26
|
import type { ShutdownChannel } from './shutdown-channel.js'
|
28
27
|
|
29
28
|
export type ShutdownState = 'running' | 'shutting-down'
|
@@ -56,8 +55,8 @@ export type InitialSyncInfo = Option.Option<{
|
|
56
55
|
// | { _tag: 'Recreate'; snapshotRef: Ref.Ref<Uint8Array | undefined>; syncInfo: InitialSyncInfo }
|
57
56
|
// | { _tag: 'Reuse'; syncInfo: InitialSyncInfo }
|
58
57
|
|
59
|
-
export type
|
60
|
-
export type PersistenceInfoPair = {
|
58
|
+
export type LeaderDatabase = SynchronousDatabase<{ dbPointer: number; persistenceInfo: PersistenceInfo }>
|
59
|
+
export type PersistenceInfoPair = { db: PersistenceInfo; mutationLog: PersistenceInfo }
|
61
60
|
|
62
61
|
export type DevtoolsOptions =
|
63
62
|
| {
|
@@ -65,9 +64,10 @@ export type DevtoolsOptions =
|
|
65
64
|
}
|
66
65
|
| {
|
67
66
|
enabled: true
|
68
|
-
|
67
|
+
makeContext: Effect.Effect<
|
69
68
|
{
|
70
69
|
devtoolsWebChannel: WebChannel.WebChannel<Devtools.MessageToAppLeader, Devtools.MessageFromAppLeader>
|
70
|
+
shutdownChannel: ShutdownChannel
|
71
71
|
persistenceInfo: PersistenceInfoPair
|
72
72
|
},
|
73
73
|
UnexpectedError,
|
@@ -75,40 +75,23 @@ export type DevtoolsOptions =
|
|
75
75
|
>
|
76
76
|
}
|
77
77
|
|
78
|
-
export type DevtoolsContext =
|
79
|
-
| {
|
80
|
-
enabled: true
|
81
|
-
syncBackendPullLatch: Effect.Latch
|
82
|
-
syncBackendPushLatch: Effect.Latch
|
83
|
-
}
|
84
|
-
| {
|
85
|
-
enabled: false
|
86
|
-
}
|
87
|
-
|
88
78
|
export class LeaderThreadCtx extends Context.Tag('LeaderThreadCtx')<
|
89
79
|
LeaderThreadCtx,
|
90
80
|
{
|
91
81
|
schema: LiveStoreSchema
|
92
82
|
storeId: string
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
83
|
+
originId: string
|
84
|
+
makeSyncDb: MakeSynchronousDatabase
|
85
|
+
db: LeaderDatabase
|
86
|
+
dbLog: LeaderDatabase
|
97
87
|
bootStatusQueue: Queue.Queue<BootStatus>
|
98
88
|
// TODO we should find a more elegant way to handle cases which need this ref for their implementation
|
99
89
|
shutdownStateSubRef: SubscriptionRef.SubscriptionRef<ShutdownState>
|
100
|
-
shutdownChannel: ShutdownChannel
|
101
90
|
mutationEventSchema: MutationEvent.ForMutationDefRecord<any>
|
102
|
-
devtools: DevtoolsContext
|
91
|
+
// devtools: DevtoolsContext
|
103
92
|
syncBackend: SyncBackend | undefined
|
104
|
-
syncProcessor:
|
93
|
+
syncProcessor: SyncProcessor
|
105
94
|
connectedClientSessionPullQueues: PullQueueSet
|
106
|
-
/**
|
107
|
-
* e.g. used for `store._dev` APIs
|
108
|
-
*
|
109
|
-
* This is currently separated from `.devtools` as it also needs to work when devtools are disabled
|
110
|
-
*/
|
111
|
-
extraIncomingMessagesQueue: Queue.Queue<Devtools.MessageToAppLeader>
|
112
95
|
}
|
113
96
|
>() {}
|
114
97
|
|
@@ -118,28 +101,24 @@ export type InitialBlockingSyncContext = {
|
|
118
101
|
}
|
119
102
|
|
120
103
|
export type PullQueueItem = {
|
121
|
-
|
104
|
+
// mutationEvents: ReadonlyArray<MutationEvent.AnyEncoded>
|
105
|
+
// backendHead: number
|
106
|
+
payload: PayloadUpstream
|
107
|
+
// TODO move `remaining` into `PayloadUpstream`
|
122
108
|
remaining: number
|
123
109
|
}
|
124
110
|
|
125
|
-
export interface
|
111
|
+
export interface SyncProcessor {
|
126
112
|
push: (
|
127
113
|
/** `batch` needs to follow the same rules as `batch` in `SyncBackend.push` */
|
128
114
|
batch: ReadonlyArray<MutationEvent.EncodedWithMeta>,
|
129
|
-
|
130
|
-
/**
|
131
|
-
* If true, the effect will only finish when the local push has been processed (i.e. succeeded or was rejected).
|
132
|
-
* @default false
|
133
|
-
*/
|
134
|
-
waitForProcessing?: boolean
|
135
|
-
},
|
136
|
-
) => Effect.Effect<void, InvalidPushError>
|
115
|
+
) => Effect.Effect<void, UnexpectedError | InvalidPushError, HttpClient.HttpClient | LeaderThreadCtx>
|
137
116
|
|
138
117
|
pushPartial: (mutationEvent: MutationEvent.PartialAnyEncoded) => Effect.Effect<void, UnexpectedError, LeaderThreadCtx>
|
139
118
|
boot: (args: {
|
140
119
|
dbReady: Deferred.Deferred<void>
|
141
120
|
}) => Effect.Effect<void, UnexpectedError, LeaderThreadCtx | Scope.Scope | HttpClient.HttpClient>
|
142
|
-
syncState:
|
121
|
+
syncState: Effect.Effect<SyncState, UnexpectedError>
|
143
122
|
}
|
144
123
|
|
145
124
|
export interface PullQueueSet {
|
package/src/mutation.ts
CHANGED
@@ -8,19 +8,10 @@ import { prepareBindValues } from './util.js'
|
|
8
8
|
|
9
9
|
export const getExecArgsFromMutation = ({
|
10
10
|
mutationDef,
|
11
|
-
|
11
|
+
mutationEventDecoded,
|
12
12
|
}: {
|
13
13
|
mutationDef: MutationDef.Any
|
14
|
-
|
15
|
-
mutationEvent:
|
16
|
-
| {
|
17
|
-
decoded: MutationEvent.AnyDecoded | MutationEvent.PartialAnyDecoded
|
18
|
-
encoded: undefined
|
19
|
-
}
|
20
|
-
| {
|
21
|
-
decoded: undefined
|
22
|
-
encoded: MutationEvent.AnyEncoded | MutationEvent.PartialAnyEncoded
|
23
|
-
}
|
14
|
+
mutationEventDecoded: MutationEvent.Any | MutationEvent.PartialAny
|
24
15
|
}): ReadonlyArray<{
|
25
16
|
statementSql: string
|
26
17
|
bindValues: PreparedBindValues
|
@@ -32,9 +23,7 @@ export const getExecArgsFromMutation = ({
|
|
32
23
|
|
33
24
|
switch (typeof mutationDef.sql) {
|
34
25
|
case 'function': {
|
35
|
-
const
|
36
|
-
mutationEvent.decoded?.args ?? Schema.decodeUnknownSync(mutationDef.schema)(mutationEvent.encoded!.args)
|
37
|
-
const res = mutationDef.sql(mutationArgsDecoded)
|
26
|
+
const res = mutationDef.sql(mutationEventDecoded.args)
|
38
27
|
statementRes = Array.isArray(res) ? res : [res]
|
39
28
|
break
|
40
29
|
}
|
@@ -51,9 +40,10 @@ export const getExecArgsFromMutation = ({
|
|
51
40
|
return statementRes.map((statementRes) => {
|
52
41
|
const statementSql = typeof statementRes === 'string' ? statementRes : statementRes.sql
|
53
42
|
|
54
|
-
const
|
55
|
-
|
56
|
-
|
43
|
+
const bindValues =
|
44
|
+
typeof statementRes === 'string'
|
45
|
+
? Schema.encodeUnknownSync(mutationDef.schema)(mutationEventDecoded.args)
|
46
|
+
: statementRes.bindValues
|
57
47
|
|
58
48
|
const writeTables = typeof statementRes === 'string' ? undefined : statementRes.writeTables
|
59
49
|
|
@@ -1,8 +1,8 @@
|
|
1
|
-
import { memoizeByRef, shouldNeverHappen } from '@livestore/utils'
|
1
|
+
import { isDevEnv, memoizeByRef, shouldNeverHappen } from '@livestore/utils'
|
2
2
|
import { Chunk, Effect, Option, Schema, Stream } from '@livestore/utils/effect'
|
3
3
|
|
4
|
-
import { type MigrationOptionsFromMutationLog, type
|
5
|
-
import {
|
4
|
+
import { type MigrationOptionsFromMutationLog, type SynchronousDatabase, UnexpectedError } from './adapter-types.js'
|
5
|
+
import { getExecArgsFromMutation } from './mutation.js'
|
6
6
|
import type { LiveStoreSchema, MutationDef, MutationEvent, MutationLogMetaRow } from './schema/mod.js'
|
7
7
|
import { EventId, MUTATION_LOG_META_TABLE } from './schema/mod.js'
|
8
8
|
import type { PreparedBindValues } from './util.js'
|
@@ -10,14 +10,13 @@ import { sql } from './util.js'
|
|
10
10
|
|
11
11
|
export const rehydrateFromMutationLog = ({
|
12
12
|
logDb,
|
13
|
-
|
14
|
-
// db,
|
13
|
+
db,
|
15
14
|
schema,
|
16
15
|
migrationOptions,
|
17
16
|
onProgress,
|
18
17
|
}: {
|
19
|
-
logDb:
|
20
|
-
db:
|
18
|
+
logDb: SynchronousDatabase
|
19
|
+
db: SynchronousDatabase
|
21
20
|
schema: LiveStoreSchema
|
22
21
|
migrationOptions: MigrationOptionsFromMutationLog
|
23
22
|
onProgress: (_: { done: number; total: number }) => Effect.Effect<void>
|
@@ -29,8 +28,6 @@ export const rehydrateFromMutationLog = ({
|
|
29
28
|
|
30
29
|
const hashMutation = memoizeByRef((mutation: MutationDef.Any) => Schema.hash(mutation.schema))
|
31
30
|
|
32
|
-
const applyMutation = yield* makeApplyMutation
|
33
|
-
|
34
31
|
const processMutation = (row: MutationLogMetaRow) =>
|
35
32
|
Effect.gen(function* () {
|
36
33
|
const mutationDef = schema.mutations.get(row.mutation) ?? shouldNeverHappen(`Unknown mutation ${row.mutation}`)
|
@@ -43,10 +40,7 @@ export const rehydrateFromMutationLog = ({
|
|
43
40
|
)
|
44
41
|
}
|
45
42
|
|
46
|
-
const
|
47
|
-
|
48
|
-
// Checking whether the schema has changed in an incompatible way
|
49
|
-
yield* Schema.decodeUnknown(mutationDef.schema)(args).pipe(
|
43
|
+
const argsDecoded = yield* Schema.decodeUnknown(Schema.parseJson(mutationDef.schema))(row.argsJson).pipe(
|
50
44
|
Effect.mapError((cause) =>
|
51
45
|
UnexpectedError.make({
|
52
46
|
cause,
|
@@ -59,14 +53,28 @@ This likely means the schema has changed in an incompatible way.
|
|
59
53
|
),
|
60
54
|
)
|
61
55
|
|
62
|
-
const
|
56
|
+
const mutationEventDecoded = {
|
63
57
|
id: { global: row.idGlobal, local: row.idLocal },
|
64
58
|
parentId: { global: row.parentIdGlobal, local: row.parentIdLocal },
|
65
59
|
mutation: row.mutation,
|
66
|
-
args,
|
67
|
-
} satisfies MutationEvent.
|
68
|
-
|
69
|
-
|
60
|
+
args: argsDecoded,
|
61
|
+
} satisfies MutationEvent.Any
|
62
|
+
|
63
|
+
const execArgsArr = getExecArgsFromMutation({ mutationDef, mutationEventDecoded })
|
64
|
+
|
65
|
+
const makeExecuteOptions = (statementSql: string, bindValues: any) => ({
|
66
|
+
onRowsChanged: (rowsChanged: number) => {
|
67
|
+
if (rowsChanged === 0 && migrationOptions.logging?.excludeAffectedRows?.(statementSql) !== true) {
|
68
|
+
console.warn(`Mutation "${mutationDef.name}" did not affect any rows:`, statementSql, bindValues)
|
69
|
+
}
|
70
|
+
},
|
71
|
+
})
|
72
|
+
|
73
|
+
for (const { statementSql, bindValues } of execArgsArr) {
|
74
|
+
// TODO cache prepared statements for mutations
|
75
|
+
db.execute(statementSql, bindValues, isDevEnv() ? makeExecuteOptions(statementSql, bindValues) : undefined)
|
76
|
+
// console.log(`Re-executed mutation ${mutationSql}`, bindValues)
|
77
|
+
}
|
70
78
|
}).pipe(Effect.withSpan(`@livestore/common:rehydrateFromMutationLog:processMutation`))
|
71
79
|
|
72
80
|
const CHUNK_SIZE = 100
|
package/src/schema/EventId.ts
CHANGED
@@ -1,14 +1,4 @@
|
|
1
|
-
import {
|
2
|
-
|
3
|
-
export type LocalEventId = Brand.Branded<number, 'LocalEventId'>
|
4
|
-
export const localEventId = Brand.nominal<LocalEventId>()
|
5
|
-
export const LocalEventId = Schema.fromBrand(localEventId)(Schema.Int)
|
6
|
-
|
7
|
-
export type GlobalEventId = Brand.Branded<number, 'GlobalEventId'>
|
8
|
-
export const globalEventId = Brand.nominal<GlobalEventId>()
|
9
|
-
export const GlobalEventId = Schema.fromBrand(globalEventId)(Schema.Int)
|
10
|
-
|
11
|
-
export const localDefault = 0 as any as LocalEventId
|
1
|
+
import { Schema } from '@livestore/utils/effect'
|
12
2
|
|
13
3
|
/**
|
14
4
|
* LiveStore event id value consisting of a globally unique event sequence number
|
@@ -16,11 +6,11 @@ export const localDefault = 0 as any as LocalEventId
|
|
16
6
|
*
|
17
7
|
* The local sequence number is only used for localOnly mutations and starts from 0 for each global sequence number.
|
18
8
|
*/
|
19
|
-
export type EventId = { global:
|
9
|
+
export type EventId = { global: number; local: number }
|
20
10
|
|
21
11
|
export const EventId = Schema.Struct({
|
22
|
-
global:
|
23
|
-
local:
|
12
|
+
global: Schema.Number,
|
13
|
+
local: Schema.Number,
|
24
14
|
}).annotations({ title: 'LiveStore.EventId' })
|
25
15
|
|
26
16
|
/**
|
@@ -37,24 +27,20 @@ export const isEqual = (a: EventId, b: EventId) => a.global === b.global && a.lo
|
|
37
27
|
|
38
28
|
export type EventIdPair = { id: EventId; parentId: EventId }
|
39
29
|
|
40
|
-
export const ROOT = { global: -1
|
30
|
+
export const ROOT = { global: -1, local: 0 } satisfies EventId
|
41
31
|
|
42
32
|
export const isGreaterThan = (a: EventId, b: EventId) => {
|
43
33
|
return a.global > b.global || (a.global === b.global && a.local > b.local)
|
44
34
|
}
|
45
35
|
|
46
|
-
export const
|
47
|
-
return Schema.is(EventId)(id) ? id : Schema.decodeSync(EventId)(id)
|
48
|
-
}
|
49
|
-
|
50
|
-
export const nextPair = (id: EventId, isLocal: boolean): EventIdPair => {
|
36
|
+
export const nextPair = (id: EventId, isLocal: boolean) => {
|
51
37
|
if (isLocal) {
|
52
|
-
return { id: { global: id.global, local:
|
38
|
+
return { id: { global: id.global, local: id.local + 1 }, parentId: id }
|
53
39
|
}
|
54
40
|
|
55
41
|
return {
|
56
|
-
id: { global:
|
42
|
+
id: { global: id.global + 1, local: 0 },
|
57
43
|
// NOTE we always point to `local: 0` for non-localOnly mutations
|
58
|
-
parentId: { global: id.global, local:
|
44
|
+
parentId: { global: id.global, local: 0 },
|
59
45
|
}
|
60
46
|
}
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import { memoizeByRef } from '@livestore/utils'
|
2
|
+
import type { Deferred } from '@livestore/utils/effect'
|
2
3
|
import { Schema } from '@livestore/utils/effect'
|
3
4
|
|
4
5
|
import * as EventId from './EventId.js'
|
@@ -29,31 +30,10 @@ export type MutationEventEncoded<TMutationsDef extends MutationDef.Any> = {
|
|
29
30
|
parentId: EventId.EventId
|
30
31
|
}
|
31
32
|
|
32
|
-
export type
|
33
|
-
export const AnyDecoded = Schema.Struct({
|
34
|
-
mutation: Schema.String,
|
35
|
-
args: Schema.Any,
|
36
|
-
id: EventId.EventId,
|
37
|
-
parentId: EventId.EventId,
|
38
|
-
}).annotations({ title: 'MutationEvent.AnyDecoded' })
|
39
|
-
|
33
|
+
export type Any = MutationEvent<MutationDef.Any>
|
40
34
|
export type AnyEncoded = MutationEventEncoded<MutationDef.Any>
|
41
|
-
export const AnyEncoded = Schema.Struct({
|
42
|
-
mutation: Schema.String,
|
43
|
-
args: Schema.Any,
|
44
|
-
id: EventId.EventId,
|
45
|
-
parentId: EventId.EventId,
|
46
|
-
}).annotations({ title: 'MutationEvent.AnyEncoded' })
|
47
|
-
|
48
|
-
export const AnyEncodedGlobal = Schema.Struct({
|
49
|
-
mutation: Schema.String,
|
50
|
-
args: Schema.Any,
|
51
|
-
id: EventId.GlobalEventId,
|
52
|
-
parentId: EventId.GlobalEventId,
|
53
|
-
}).annotations({ title: 'MutationEvent.AnyEncodedGlobal' })
|
54
|
-
export type AnyEncodedGlobal = typeof AnyEncodedGlobal.Type
|
55
35
|
|
56
|
-
export type
|
36
|
+
export type PartialAny = MutationEventPartial<MutationDef.Any>
|
57
37
|
export type PartialAnyEncoded = MutationEventPartialEncoded<MutationDef.Any>
|
58
38
|
|
59
39
|
export type PartialForSchema<TSchema extends LiveStoreSchema> = {
|
@@ -64,9 +44,8 @@ export type ForSchema<TSchema extends LiveStoreSchema> = {
|
|
64
44
|
[K in keyof TSchema['_MutationDefMapType']]: MutationEvent<TSchema['_MutationDefMapType'][K]>
|
65
45
|
}[keyof TSchema['_MutationDefMapType']]
|
66
46
|
|
67
|
-
export const isPartialMutationEvent = (
|
68
|
-
mutationEvent
|
69
|
-
): mutationEvent is PartialAnyDecoded => 'id' in mutationEvent === false && 'parentId' in mutationEvent === false
|
47
|
+
export const isPartialMutationEvent = (mutationEvent: Any | PartialAny): mutationEvent is PartialAny =>
|
48
|
+
'id' in mutationEvent === false && 'parentId' in mutationEvent === false
|
70
49
|
|
71
50
|
export type ForMutationDefRecord<TMutationsDefRecord extends MutationDefRecord> = Schema.Schema<
|
72
51
|
{
|
@@ -126,21 +105,33 @@ export const makeMutationEventPartialSchema = <TSchema extends LiveStoreSchema>(
|
|
126
105
|
args: def.schema,
|
127
106
|
}),
|
128
107
|
),
|
129
|
-
).annotations({ title: '
|
108
|
+
).annotations({ title: 'MutationEventSchemaPartial' }) as any
|
130
109
|
|
131
110
|
export const makeMutationEventSchemaMemo = memoizeByRef(makeMutationEventSchema)
|
132
111
|
|
133
|
-
|
112
|
+
export const Any = Schema.Struct({
|
113
|
+
mutation: Schema.String,
|
114
|
+
args: Schema.Any,
|
115
|
+
id: EventId.EventId,
|
116
|
+
parentId: EventId.EventId,
|
117
|
+
}).annotations({ title: 'MutationEvent.Any' })
|
118
|
+
|
119
|
+
export const DecodedAny = Schema.typeSchema(Any).annotations({
|
120
|
+
title: 'MutationEvent.DecodedAny',
|
121
|
+
})
|
122
|
+
|
123
|
+
export const EncodedAny = Schema.encodedSchema(Any).annotations({
|
124
|
+
title: 'MutationEvent.EncodedAny',
|
125
|
+
})
|
126
|
+
|
127
|
+
/** Equivalent to EncodedAny but with a meta field and some convenience methods */
|
134
128
|
export class EncodedWithMeta extends Schema.Class<EncodedWithMeta>('MutationEvent.EncodedWithMeta')({
|
135
129
|
mutation: Schema.String,
|
136
130
|
args: Schema.Any,
|
137
131
|
id: EventId.EventId,
|
138
132
|
parentId: EventId.EventId,
|
139
|
-
// TODO get rid of `meta` again by cleaning up the usage implementations
|
140
133
|
meta: Schema.optionalWith(
|
141
|
-
Schema.Any as Schema.Schema<{
|
142
|
-
sessionChangeset?: Uint8Array
|
143
|
-
}>,
|
134
|
+
Schema.Any as Schema.Schema<{ deferred?: Deferred.Deferred<void>; sessionChangeset?: Uint8Array }>,
|
144
135
|
{ default: () => ({}) },
|
145
136
|
),
|
146
137
|
}) {
|
@@ -158,21 +149,8 @@ export class EncodedWithMeta extends Schema.Class<EncodedWithMeta>('MutationEven
|
|
158
149
|
rebase = (parentId: EventId.EventId, isLocal: boolean) =>
|
159
150
|
new EncodedWithMeta({
|
160
151
|
...this,
|
161
|
-
...EventId.nextPair(
|
152
|
+
...EventId.nextPair(this.id, isLocal),
|
162
153
|
})
|
163
|
-
|
164
|
-
static fromGlobal = (mutationEvent: AnyEncodedGlobal) =>
|
165
|
-
new EncodedWithMeta({
|
166
|
-
...mutationEvent,
|
167
|
-
id: { global: mutationEvent.id, local: EventId.localDefault },
|
168
|
-
parentId: { global: mutationEvent.parentId, local: EventId.localDefault },
|
169
|
-
})
|
170
|
-
|
171
|
-
toGlobal = (): AnyEncodedGlobal => ({
|
172
|
-
...this,
|
173
|
-
id: this.id.global,
|
174
|
-
parentId: this.parentId.global,
|
175
|
-
})
|
176
154
|
}
|
177
155
|
|
178
156
|
export const isEqualEncoded = (a: AnyEncoded, b: AnyEncoded) =>
|
@@ -1,7 +1,6 @@
|
|
1
1
|
import { type SqliteAst as __SqliteAst, SqliteDsl } from '@livestore/db-schema'
|
2
2
|
import { Schema } from '@livestore/utils/effect'
|
3
3
|
|
4
|
-
import * as EventId from './EventId.js'
|
5
4
|
import type { FromTable } from './table-def.js'
|
6
5
|
import { table } from './table-def.js'
|
7
6
|
|
@@ -47,15 +46,14 @@ export const sessionChangesetMetaTable = table(
|
|
47
46
|
SESSION_CHANGESET_META_TABLE,
|
48
47
|
{
|
49
48
|
// TODO bring back primary key
|
50
|
-
idGlobal: SqliteDsl.integer({
|
51
|
-
idLocal: SqliteDsl.integer({
|
52
|
-
|
49
|
+
idGlobal: SqliteDsl.integer({}),
|
50
|
+
idLocal: SqliteDsl.integer({}),
|
51
|
+
// idGlobal: SqliteDsl.integer({ primaryKey: true }),
|
52
|
+
// idLocal: SqliteDsl.integer({ primaryKey: true }),
|
53
|
+
changeset: SqliteDsl.blob({}),
|
53
54
|
debug: SqliteDsl.json({ nullable: true }),
|
54
55
|
},
|
55
|
-
{
|
56
|
-
disableAutomaticIdColumn: true,
|
57
|
-
indexes: [{ columns: ['idGlobal', 'idLocal'], name: 'idx_session_changeset_id' }],
|
58
|
-
},
|
56
|
+
{ disableAutomaticIdColumn: true },
|
59
57
|
)
|
60
58
|
|
61
59
|
export type SessionChangesetMetaRow = FromTable.RowDecoded<typeof sessionChangesetMetaTable>
|
@@ -72,22 +70,16 @@ export const MUTATION_LOG_META_TABLE = 'mutation_log'
|
|
72
70
|
export const mutationLogMetaTable = table(
|
73
71
|
MUTATION_LOG_META_TABLE,
|
74
72
|
{
|
75
|
-
idGlobal: SqliteDsl.integer({ primaryKey: true
|
76
|
-
idLocal: SqliteDsl.integer({ primaryKey: true
|
77
|
-
parentIdGlobal: SqliteDsl.integer({
|
78
|
-
parentIdLocal: SqliteDsl.integer({
|
73
|
+
idGlobal: SqliteDsl.integer({ primaryKey: true }),
|
74
|
+
idLocal: SqliteDsl.integer({ primaryKey: true }),
|
75
|
+
parentIdGlobal: SqliteDsl.integer({}),
|
76
|
+
parentIdLocal: SqliteDsl.integer({}),
|
79
77
|
mutation: SqliteDsl.text({}),
|
80
78
|
argsJson: SqliteDsl.text({ schema: Schema.parseJson(Schema.Any) }),
|
81
79
|
schemaHash: SqliteDsl.integer({}),
|
82
80
|
syncMetadataJson: SqliteDsl.text({ schema: Schema.parseJson(Schema.Option(Schema.JsonValue)) }),
|
83
81
|
},
|
84
|
-
{
|
85
|
-
disableAutomaticIdColumn: true,
|
86
|
-
indexes: [
|
87
|
-
{ columns: ['idGlobal'], name: 'idx_idGlobal' },
|
88
|
-
{ columns: ['idGlobal', 'idLocal'], name: 'idx_mutationlog_id' },
|
89
|
-
],
|
90
|
-
},
|
82
|
+
{ disableAutomaticIdColumn: true, indexes: [] },
|
91
83
|
)
|
92
84
|
|
93
85
|
export type MutationLogMetaRow = FromTable.RowDecoded<typeof mutationLogMetaTable>
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import type {
|
1
|
+
import type { SynchronousDatabase } from '../adapter-types.js'
|
2
2
|
import type { ParamsObject } from '../util.js'
|
3
3
|
import { prepareBindValues } from '../util.js'
|
4
4
|
|
@@ -6,7 +6,7 @@ import { prepareBindValues } from '../util.js'
|
|
6
6
|
// will require proper scope-aware cleanup etc (for testing and apps with multiple LiveStore instances)
|
7
7
|
// const cachedStmts = new Map<string, PreparedStatement>()
|
8
8
|
|
9
|
-
export const dbExecute = (db:
|
9
|
+
export const dbExecute = (db: SynchronousDatabase, queryStr: string, bindValues?: ParamsObject) => {
|
10
10
|
// let stmt = cachedStmts.get(queryStr)
|
11
11
|
// if (!stmt) {
|
12
12
|
const stmt = db.prepare(queryStr)
|
@@ -20,7 +20,7 @@ export const dbExecute = (db: SqliteDb, queryStr: string, bindValues?: ParamsObj
|
|
20
20
|
stmt.finalize()
|
21
21
|
}
|
22
22
|
|
23
|
-
export const dbSelect = <T>(db:
|
23
|
+
export const dbSelect = <T>(db: SynchronousDatabase, queryStr: string, bindValues?: ParamsObject) => {
|
24
24
|
// let stmt = cachedStmts.get(queryStr)
|
25
25
|
// if (!stmt) {
|
26
26
|
const stmt = db.prepare(queryStr)
|
@@ -2,7 +2,7 @@ import { SqliteAst, SqliteDsl } from '@livestore/db-schema'
|
|
2
2
|
import { memoizeByStringifyArgs } from '@livestore/utils'
|
3
3
|
import { Effect, Schema as EffectSchema } from '@livestore/utils/effect'
|
4
4
|
|
5
|
-
import type {
|
5
|
+
import type { SynchronousDatabase } from '../adapter-types.js'
|
6
6
|
import type { LiveStoreSchema } from '../schema/mod.js'
|
7
7
|
import type { SchemaMetaRow, SchemaMutationsMetaRow } from '../schema/system-tables.js'
|
8
8
|
import {
|
@@ -19,7 +19,7 @@ import { validateSchema } from './validate-mutation-defs.js'
|
|
19
19
|
|
20
20
|
const getMemoizedTimestamp = memoizeByStringifyArgs(() => new Date().toISOString())
|
21
21
|
|
22
|
-
export const makeSchemaManager = (db:
|
22
|
+
export const makeSchemaManager = (db: SynchronousDatabase): Effect.Effect<SchemaManager> =>
|
23
23
|
Effect.gen(function* () {
|
24
24
|
yield* migrateTable({
|
25
25
|
db,
|
@@ -51,7 +51,7 @@ export const migrateDb = ({
|
|
51
51
|
schema,
|
52
52
|
onProgress,
|
53
53
|
}: {
|
54
|
-
db:
|
54
|
+
db: SynchronousDatabase
|
55
55
|
schema: LiveStoreSchema
|
56
56
|
onProgress?: (opts: { done: number; total: number }) => Effect.Effect<void>
|
57
57
|
}) =>
|
@@ -116,7 +116,7 @@ export const migrateTable = ({
|
|
116
116
|
behaviour,
|
117
117
|
skipMetaTable = false,
|
118
118
|
}: {
|
119
|
-
db:
|
119
|
+
db: SynchronousDatabase
|
120
120
|
tableAst: SqliteAst.Table
|
121
121
|
schemaHash?: number
|
122
122
|
behaviour: 'drop-and-recreate' | 'create-if-not-exists'
|
@@ -129,10 +129,10 @@ export const migrateTable = ({
|
|
129
129
|
|
130
130
|
if (behaviour === 'drop-and-recreate') {
|
131
131
|
// TODO need to possibly handle cascading deletes due to foreign keys
|
132
|
-
dbExecute(db, sql`drop table if exists
|
133
|
-
dbExecute(db, sql`create table if not exists
|
132
|
+
dbExecute(db, sql`drop table if exists ${tableName}`)
|
133
|
+
dbExecute(db, sql`create table if not exists ${tableName} (${columnSpec}) strict`)
|
134
134
|
} else if (behaviour === 'create-if-not-exists') {
|
135
|
-
dbExecute(db, sql`create table if not exists
|
135
|
+
dbExecute(db, sql`create table if not exists ${tableName} (${columnSpec}) strict`)
|
136
136
|
}
|
137
137
|
|
138
138
|
for (const index of tableAst.indexes) {
|
@@ -162,11 +162,11 @@ export const migrateTable = ({
|
|
162
162
|
|
163
163
|
const createIndexFromDefinition = (tableName: string, index: SqliteAst.Index) => {
|
164
164
|
const uniqueStr = index.unique ? 'UNIQUE' : ''
|
165
|
-
return sql`create ${uniqueStr} index if not exists
|
165
|
+
return sql`create ${uniqueStr} index if not exists ${index.name} on ${tableName} (${index.columns.join(', ')})`
|
166
166
|
}
|
167
167
|
|
168
168
|
export const makeColumnSpec = (tableAst: SqliteAst.Table) => {
|
169
|
-
const primaryKeys = tableAst.columns.filter((_) => _.primaryKey).map((_) =>
|
169
|
+
const primaryKeys = tableAst.columns.filter((_) => _.primaryKey).map((_) => _.name)
|
170
170
|
const columnDefStrs = tableAst.columns.map(toSqliteColumnSpec)
|
171
171
|
if (primaryKeys.length > 0) {
|
172
172
|
columnDefStrs.push(`PRIMARY KEY (${primaryKeys.join(', ')})`)
|
@@ -191,5 +191,5 @@ const toSqliteColumnSpec = (column: SqliteAst.Column) => {
|
|
191
191
|
return `default ${encodedDefaultValue}`
|
192
192
|
})()
|
193
193
|
|
194
|
-
return
|
194
|
+
return `${column.name} ${columnTypeStr} ${nullableStr} ${defaultValueStr}`
|
195
195
|
}
|