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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (146) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/adapter-types.d.ts +23 -26
  3. package/dist/adapter-types.d.ts.map +1 -1
  4. package/dist/adapter-types.js.map +1 -1
  5. package/dist/derived-mutations.d.ts +4 -4
  6. package/dist/derived-mutations.d.ts.map +1 -1
  7. package/dist/derived-mutations.test.js.map +1 -1
  8. package/dist/devtools/devtools-bridge.d.ts +1 -2
  9. package/dist/devtools/devtools-bridge.d.ts.map +1 -1
  10. package/dist/devtools/devtools-messages.d.ts +110 -98
  11. package/dist/devtools/devtools-messages.d.ts.map +1 -1
  12. package/dist/devtools/devtools-messages.js +6 -9
  13. package/dist/devtools/devtools-messages.js.map +1 -1
  14. package/dist/index.d.ts +4 -0
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/leader-thread/apply-mutation.d.ts +2 -5
  17. package/dist/leader-thread/apply-mutation.d.ts.map +1 -1
  18. package/dist/leader-thread/apply-mutation.js +26 -38
  19. package/dist/leader-thread/apply-mutation.js.map +1 -1
  20. package/dist/leader-thread/leader-sync-processor.d.ts +2 -2
  21. package/dist/leader-thread/leader-sync-processor.d.ts.map +1 -1
  22. package/dist/leader-thread/leader-sync-processor.js +12 -20
  23. package/dist/leader-thread/leader-sync-processor.js.map +1 -1
  24. package/dist/leader-thread/leader-worker-devtools.d.ts +1 -1
  25. package/dist/leader-thread/leader-worker-devtools.d.ts.map +1 -1
  26. package/dist/leader-thread/leader-worker-devtools.js +66 -22
  27. package/dist/leader-thread/leader-worker-devtools.js.map +1 -1
  28. package/dist/leader-thread/make-leader-thread-layer.d.ts +7 -8
  29. package/dist/leader-thread/make-leader-thread-layer.d.ts.map +1 -1
  30. package/dist/leader-thread/make-leader-thread-layer.js +5 -11
  31. package/dist/leader-thread/make-leader-thread-layer.js.map +1 -1
  32. package/dist/leader-thread/mutationlog.d.ts +17 -4
  33. package/dist/leader-thread/mutationlog.d.ts.map +1 -1
  34. package/dist/leader-thread/mutationlog.js +1 -2
  35. package/dist/leader-thread/mutationlog.js.map +1 -1
  36. package/dist/leader-thread/pull-queue-set.d.ts.map +1 -1
  37. package/dist/leader-thread/recreate-db.d.ts.map +1 -1
  38. package/dist/leader-thread/recreate-db.js +3 -9
  39. package/dist/leader-thread/recreate-db.js.map +1 -1
  40. package/dist/leader-thread/types.d.ts +9 -17
  41. package/dist/leader-thread/types.d.ts.map +1 -1
  42. package/dist/leader-thread/types.js.map +1 -1
  43. package/dist/mutation.d.ts +2 -9
  44. package/dist/mutation.d.ts.map +1 -1
  45. package/dist/mutation.js +5 -5
  46. package/dist/mutation.js.map +1 -1
  47. package/dist/query-builder/impl.d.ts +1 -1
  48. package/dist/rehydrate-from-mutationlog.d.ts +2 -2
  49. package/dist/rehydrate-from-mutationlog.d.ts.map +1 -1
  50. package/dist/rehydrate-from-mutationlog.js +19 -13
  51. package/dist/rehydrate-from-mutationlog.js.map +1 -1
  52. package/dist/schema/EventId.d.ts +14 -16
  53. package/dist/schema/EventId.d.ts.map +1 -1
  54. package/dist/schema/EventId.js +7 -15
  55. package/dist/schema/EventId.js.map +1 -1
  56. package/dist/schema/MutationEvent.d.ts +80 -49
  57. package/dist/schema/MutationEvent.d.ts.map +1 -1
  58. package/dist/schema/MutationEvent.js +15 -32
  59. package/dist/schema/MutationEvent.js.map +1 -1
  60. package/dist/schema/system-tables.d.ts +26 -26
  61. package/dist/schema/system-tables.d.ts.map +1 -1
  62. package/dist/schema/system-tables.js +11 -19
  63. package/dist/schema/system-tables.js.map +1 -1
  64. package/dist/schema-management/migrations.js +6 -6
  65. package/dist/schema-management/migrations.js.map +1 -1
  66. package/dist/sync/client-session-sync-processor.d.ts +4 -4
  67. package/dist/sync/client-session-sync-processor.d.ts.map +1 -1
  68. package/dist/sync/index.d.ts +1 -1
  69. package/dist/sync/index.d.ts.map +1 -1
  70. package/dist/sync/index.js +1 -1
  71. package/dist/sync/index.js.map +1 -1
  72. package/dist/sync/next/history-dag-common.d.ts +4 -1
  73. package/dist/sync/next/history-dag-common.d.ts.map +1 -1
  74. package/dist/sync/next/history-dag-common.js +1 -1
  75. package/dist/sync/next/history-dag-common.js.map +1 -1
  76. package/dist/sync/next/rebase-events.d.ts +3 -3
  77. package/dist/sync/next/rebase-events.d.ts.map +1 -1
  78. package/dist/sync/next/rebase-events.js +2 -3
  79. package/dist/sync/next/rebase-events.js.map +1 -1
  80. package/dist/sync/next/test/mutation-fixtures.d.ts.map +1 -1
  81. package/dist/sync/next/test/mutation-fixtures.js +9 -3
  82. package/dist/sync/next/test/mutation-fixtures.js.map +1 -1
  83. package/dist/sync/sync.d.ts +11 -21
  84. package/dist/sync/sync.d.ts.map +1 -1
  85. package/dist/sync/sync.js.map +1 -1
  86. package/dist/sync/syncstate.d.ts +23 -45
  87. package/dist/sync/syncstate.d.ts.map +1 -1
  88. package/dist/sync/syncstate.js +12 -56
  89. package/dist/sync/syncstate.js.map +1 -1
  90. package/dist/sync/syncstate.test.js +69 -125
  91. package/dist/sync/syncstate.test.js.map +1 -1
  92. package/dist/sync/validate-push-payload.d.ts +2 -2
  93. package/dist/sync/validate-push-payload.d.ts.map +1 -1
  94. package/dist/sync/validate-push-payload.js +2 -2
  95. package/dist/sync/validate-push-payload.js.map +1 -1
  96. package/dist/version.d.ts +1 -1
  97. package/dist/version.d.ts.map +1 -1
  98. package/dist/version.js +1 -1
  99. package/dist/version.js.map +1 -1
  100. package/package.json +5 -6
  101. package/src/adapter-types.ts +24 -22
  102. package/src/derived-mutations.test.ts +1 -1
  103. package/src/derived-mutations.ts +5 -9
  104. package/src/devtools/devtools-bridge.ts +1 -2
  105. package/src/devtools/devtools-messages.ts +6 -9
  106. package/src/index.ts +6 -0
  107. package/src/leader-thread/apply-mutation.ts +31 -49
  108. package/src/leader-thread/{LeaderSyncProcessor.ts → leader-sync-processor.ts} +230 -235
  109. package/src/leader-thread/leader-worker-devtools.ts +109 -30
  110. package/src/leader-thread/make-leader-thread-layer.ts +13 -24
  111. package/src/leader-thread/mutationlog.ts +5 -9
  112. package/src/leader-thread/recreate-db.ts +5 -9
  113. package/src/leader-thread/types.ts +11 -18
  114. package/src/mutation.ts +7 -17
  115. package/src/rehydrate-from-mutationlog.ts +23 -15
  116. package/src/schema/EventId.ts +9 -23
  117. package/src/schema/MutationEvent.ts +24 -46
  118. package/src/schema/system-tables.ts +11 -19
  119. package/src/schema-management/migrations.ts +6 -6
  120. package/src/sync/{ClientSessionSyncProcessor.ts → client-session-sync-processor.ts} +9 -11
  121. package/src/sync/index.ts +1 -1
  122. package/src/sync/next/history-dag-common.ts +1 -1
  123. package/src/sync/next/rebase-events.ts +7 -7
  124. package/src/sync/next/test/mutation-fixtures.ts +10 -3
  125. package/src/sync/sync.ts +6 -19
  126. package/src/sync/syncstate.test.ts +67 -127
  127. package/src/sync/syncstate.ts +19 -21
  128. package/src/sync/validate-push-payload.ts +4 -7
  129. package/src/version.ts +1 -1
  130. package/dist/leader-thread/LeaderSyncProcessor.d.ts +0 -37
  131. package/dist/leader-thread/LeaderSyncProcessor.d.ts.map +0 -1
  132. package/dist/leader-thread/LeaderSyncProcessor.js +0 -417
  133. package/dist/leader-thread/LeaderSyncProcessor.js.map +0 -1
  134. package/dist/schema/EventId.test.d.ts +0 -2
  135. package/dist/schema/EventId.test.d.ts.map +0 -1
  136. package/dist/schema/EventId.test.js +0 -11
  137. package/dist/schema/EventId.test.js.map +0 -1
  138. package/dist/schema/MutationEvent.test.d.ts +0 -2
  139. package/dist/schema/MutationEvent.test.d.ts.map +0 -1
  140. package/dist/schema/MutationEvent.test.js +0 -2
  141. package/dist/schema/MutationEvent.test.js.map +0 -1
  142. package/dist/sync/ClientSessionSyncProcessor.d.ts +0 -45
  143. package/dist/sync/ClientSessionSyncProcessor.d.ts.map +0 -1
  144. package/dist/sync/ClientSessionSyncProcessor.js +0 -134
  145. package/dist/sync/ClientSessionSyncProcessor.js.map +0 -1
  146. package/src/schema/EventId.test.ts +0 -12
package/package.json CHANGED
@@ -1,8 +1,7 @@
1
1
  {
2
2
  "name": "@livestore/common",
3
- "version": "0.3.0-dev.10",
3
+ "version": "0.3.0-dev.2",
4
4
  "type": "module",
5
- "sideEffects": false,
6
5
  "exports": {
7
6
  ".": {
8
7
  "types": "./dist/index.d.ts",
@@ -50,12 +49,12 @@
50
49
  }
51
50
  },
52
51
  "dependencies": {
53
- "@opentelemetry/api": "1.9.0",
52
+ "@opentelemetry/api": "^1.9.0",
54
53
  "graphology": "0.26.0-alpha1",
55
54
  "graphology-dag": "0.4.1",
56
- "graphology-types": "0.24.8",
57
- "@livestore/db-schema": "0.3.0-dev.10",
58
- "@livestore/utils": "0.3.0-dev.10"
55
+ "graphology-types": "0.24.7",
56
+ "@livestore/utils": "0.3.0-dev.2",
57
+ "@livestore/db-schema": "0.3.0-dev.2"
59
58
  },
60
59
  "devDependencies": {
61
60
  "vitest": "^2.1.4"
@@ -29,28 +29,8 @@ export type SynchronousDatabaseChangeset = {
29
29
  export type ClientSession = {
30
30
  /** SQLite database with synchronous API running in the same thread (usually in-memory) */
31
31
  syncDb: SynchronousDatabase
32
- devtools: { enabled: boolean }
33
- clientId: string
34
- sessionId: string
35
- /** Status info whether current session is leader or not */
36
- lockStatus: SubscriptionRef.SubscriptionRef<LockStatus>
37
- shutdown: (cause: Cause.Cause<UnexpectedError | IntentionalShutdownCause>) => Effect.Effect<void>
38
- /** A proxy API to communicate with the leader thread */
39
- leaderThread: ClientSessionLeaderThreadProxy
40
- }
41
-
42
- export type ClientSessionLeaderThreadProxy = {
43
- mutations: {
44
- pull: Stream.Stream<{ payload: PayloadUpstream; remaining: number }, UnexpectedError>
45
- push(batch: ReadonlyArray<MutationEvent.AnyEncoded>): Effect.Effect<void, UnexpectedError | InvalidPushError>
46
- initialMutationEventId: EventId
47
- }
48
- export: Effect.Effect<Uint8Array, UnexpectedError>
49
- getMutationLogData: Effect.Effect<Uint8Array, UnexpectedError>
50
- getSyncState: Effect.Effect<SyncState, UnexpectedError>
51
- networkStatus: SubscriptionRef.SubscriptionRef<NetworkStatus>
52
- /** For debugging purposes it can be useful to manually trigger devtools messages (e.g. to reset the database) */
53
- sendDevtoolsMessage: (message: Devtools.MessageToAppLeader) => Effect.Effect<void, UnexpectedError>
32
+ /** The coordinator is responsible for persisting the database, syncing etc */
33
+ coordinator: Coordinator
54
34
  }
55
35
 
56
36
  export type SynchronousDatabase<TReq = any, TMetadata extends TReq = TReq> = {
@@ -123,6 +103,28 @@ export const BootStatus = Schema.Union(
123
103
 
124
104
  export type BootStatus = typeof BootStatus.Type
125
105
 
106
+ // TODO refactor `Coordinator` to embrace more of the "leader semantics"
107
+ export type Coordinator = {
108
+ devtools: {
109
+ enabled: boolean
110
+ // TODO incorporate sessionId and rethink appHostId
111
+ appHostId: string
112
+ }
113
+ sessionId: string
114
+ // TODO is exposing the lock status really needed (or only relevant for web adapter?)
115
+ lockStatus: SubscriptionRef.SubscriptionRef<LockStatus>
116
+ mutations: {
117
+ pull: Stream.Stream<{ payload: PayloadUpstream; remaining: number }, UnexpectedError>
118
+ push(batch: ReadonlyArray<MutationEvent.AnyEncoded>): Effect.Effect<void, UnexpectedError | InvalidPushError>
119
+ initialMutationEventId: EventId
120
+ }
121
+ export: Effect.Effect<Uint8Array, UnexpectedError>
122
+ getMutationLogData: Effect.Effect<Uint8Array, UnexpectedError>
123
+ getLeaderSyncState: Effect.Effect<SyncState, UnexpectedError>
124
+ networkStatus: SubscriptionRef.SubscriptionRef<NetworkStatus>
125
+ shutdown: (cause: Cause.Cause<UnexpectedError | IntentionalShutdownCause>) => Effect.Effect<void>
126
+ }
127
+
126
128
  /**
127
129
  * Can be used in queries to refer to the current session id.
128
130
  * Will be replaced with the actual session id at runtime
@@ -94,7 +94,7 @@ describe('derived mutations', () => {
94
94
  })
95
95
  })
96
96
 
97
- const patchId = (muationEvent: MutationEvent.PartialAnyDecoded) => {
97
+ const patchId = (muationEvent: MutationEvent.PartialAny) => {
98
98
  // TODO use new id paradigm
99
99
  const id = `00000000-0000-0000-0000-000000000000`
100
100
  return { ...muationEvent, id }
@@ -136,10 +136,8 @@ export namespace DerivedMutationHelperFns {
136
136
  > = SqliteDsl.AnyIfConstained<
137
137
  TColumns,
138
138
  UseShortcut<TOptions> extends true
139
- ? (
140
- values?: GetValForKey<SqliteDsl.FromColumns.InsertRowDecoded<TColumns>, 'value'>,
141
- ) => MutationEvent.PartialAnyDecoded
142
- : (values: SqliteDsl.FromColumns.InsertRowDecoded<TColumns>) => MutationEvent.PartialAnyDecoded
139
+ ? (values?: GetValForKey<SqliteDsl.FromColumns.InsertRowDecoded<TColumns>, 'value'>) => MutationEvent.PartialAny
140
+ : (values: SqliteDsl.FromColumns.InsertRowDecoded<TColumns>) => MutationEvent.PartialAny
143
141
  >
144
142
 
145
143
  export type UpdateMutationFn<
@@ -148,19 +146,17 @@ export namespace DerivedMutationHelperFns {
148
146
  > = SqliteDsl.AnyIfConstained<
149
147
  TColumns,
150
148
  UseShortcut<TOptions> extends true
151
- ? (
152
- values: Partial<GetValForKey<SqliteDsl.FromColumns.RowDecoded<TColumns>, 'value'>>,
153
- ) => MutationEvent.PartialAnyDecoded
149
+ ? (values: Partial<GetValForKey<SqliteDsl.FromColumns.RowDecoded<TColumns>, 'value'>>) => MutationEvent.PartialAny
154
150
  : (args: {
155
151
  where: Partial<SqliteDsl.FromColumns.RowDecoded<TColumns>>
156
152
  values: Partial<SqliteDsl.FromColumns.RowDecoded<TColumns>>
157
- }) => MutationEvent.PartialAnyDecoded
153
+ }) => MutationEvent.PartialAny
158
154
  >
159
155
 
160
156
  export type DeleteMutationFn<
161
157
  TColumns extends SqliteDsl.ConstraintColumns,
162
158
  _TOptions extends DbSchema.TableOptions,
163
- > = (args: { where: Partial<SqliteDsl.FromColumns.RowDecoded<TColumns>> }) => MutationEvent.PartialAnyDecoded
159
+ > = (args: { where: Partial<SqliteDsl.FromColumns.RowDecoded<TColumns>> }) => MutationEvent.PartialAny
164
160
 
165
161
  type UseShortcut<TOptions extends DbSchema.TableOptions> = TOptions['isSingleColumn'] extends true
166
162
  ? TOptions['isSingleton'] extends true
@@ -6,8 +6,7 @@ export type PrepareDevtoolsBridge = {
6
6
  /** Messages coming from the app host (usually responses to requests) */
7
7
  responsePubSub: PubSub.PubSub<Devtools.MessageFromAppLeader | Devtools.MessageFromAppClientSession>
8
8
  sendToAppHost: (msg: Devtools.MessageToAppLeader | Devtools.MessageToAppClientSession) => Effect.Effect<void>
9
- clientId: string
10
- sessionId: string
9
+ appHostId: string
11
10
  copyToClipboard: (text: string) => Effect.Effect<void>
12
11
  sendEscapeKey?: Effect.Effect<void>
13
12
  isLeader: boolean
@@ -7,8 +7,7 @@ import { PreparedBindValues } from '../util.js'
7
7
  import { liveStoreVersion as pkgVersion } from '../version.js'
8
8
 
9
9
  const requestId = Schema.String
10
- const clientId = Schema.String
11
- const sessionId = Schema.String
10
+ const appHostId = Schema.String
12
11
  const liveStoreVersion = Schema.Literal(pkgVersion)
13
12
 
14
13
  const LSDMessage = <Tag extends string, Fields extends Schema.Struct.Fields>(tag: Tag, fields: Fields) =>
@@ -24,15 +23,13 @@ const LSDChannelMessage = <Tag extends string, Fields extends Schema.Struct.Fiel
24
23
 
25
24
  const LSDStoreChannelMessage = <Tag extends string, Fields extends Schema.Struct.Fields>(tag: Tag, fields: Fields) =>
26
25
  LSDMessage(tag, {
27
- clientId,
28
- sessionId,
26
+ appHostId,
29
27
  ...fields,
30
28
  })
31
29
 
32
30
  const LSDStoreReqResMessage = <Tag extends string, Fields extends Schema.Struct.Fields>(tag: Tag, fields: Fields) =>
33
31
  LSDMessage(tag, {
34
- clientId,
35
- sessionId,
32
+ appHostId,
36
33
  requestId,
37
34
  ...fields,
38
35
  })
@@ -85,12 +82,12 @@ export class DebugInfoRerunQueryRes extends LSDStoreReqResMessage('LSD.DebugInfo
85
82
 
86
83
  // TODO refactor this to use push/pull semantics
87
84
  export class MutationBroadcast extends LSDMessage('LSD.Leader.MutationBroadcast', {
88
- mutationEventEncoded: MutationEvent.AnyEncoded,
85
+ mutationEventEncoded: MutationEvent.EncodedAny,
89
86
  }) {}
90
87
 
91
88
  // TODO refactor this to use push/pull semantics
92
89
  export class RunMutationReq extends LSDReqResMessage('LSD.Leader.RunMutationReq', {
93
- mutationEventEncoded: MutationEvent.AnyEncoded.pipe(Schema.omit('id', 'parentId')),
90
+ mutationEventEncoded: MutationEvent.EncodedAny.pipe(Schema.omit('id', 'parentId')),
94
91
  }) {}
95
92
 
96
93
  export class RunMutationRes extends LSDReqResMessage('LSD.Leader.RunMutationRes', {}) {}
@@ -170,7 +167,7 @@ export class SyncingInfoRes extends LSDReqResMessage('LSD.Leader.SyncingInfoRes'
170
167
  export class SyncHistorySubscribe extends LSDReqResMessage('LSD.Leader.SyncHistorySubscribe', {}) {}
171
168
  export class SyncHistoryUnsubscribe extends LSDReqResMessage('LSD.Leader.SyncHistoryUnsubscribe', {}) {}
172
169
  export class SyncHistoryRes extends LSDReqResMessage('LSD.Leader.SyncHistoryRes', {
173
- mutationEventEncoded: MutationEvent.AnyEncodedGlobal,
170
+ mutationEventEncoded: MutationEvent.EncodedAny,
174
171
  metadata: Schema.Option(Schema.JsonValue),
175
172
  }) {}
176
173
 
package/src/index.ts CHANGED
@@ -15,3 +15,9 @@ export * from './version.js'
15
15
  export * from './query-builder/mod.js'
16
16
  export * from './sync/syncstate.js'
17
17
  export * from './otel.js'
18
+
19
+ declare global {
20
+ interface LiveStoreGlobal {
21
+ // syncBackend: never
22
+ }
23
+ }
@@ -3,25 +3,20 @@ import type { Scope } from '@livestore/utils/effect'
3
3
  import { Effect, Option, Schema } from '@livestore/utils/effect'
4
4
 
5
5
  import type { SqliteError, SynchronousDatabase, UnexpectedError } from '../index.js'
6
- import { getExecArgsFromMutation } from '../mutation.js'
7
6
  import {
8
- type LiveStoreSchema,
7
+ getExecArgsFromMutation,
9
8
  MUTATION_LOG_META_TABLE,
10
- type MutationEvent,
11
9
  mutationLogMetaTable,
12
10
  SESSION_CHANGESET_META_TABLE,
13
11
  sessionChangesetMetaTable,
14
- } from '../schema/mod.js'
12
+ } from '../index.js'
13
+ import type { LiveStoreSchema, MutationEvent } from '../schema/mod.js'
15
14
  import { insertRow } from '../sql-queries/index.js'
16
15
  import { execSql, execSqlPrepared } from './connection.js'
17
16
  import { LeaderThreadCtx } from './types.js'
18
17
 
19
18
  export type ApplyMutation = (
20
19
  mutationEventEncoded: MutationEvent.AnyEncoded,
21
- options?: {
22
- /** Needed for rehydrateFromMutationLog */
23
- skipMutationLog?: boolean
24
- },
25
20
  ) => Effect.Effect<void, SqliteError | UnexpectedError>
26
21
 
27
22
  export const makeApplyMutation: Effect.Effect<ApplyMutation, never, Scope.Scope | LeaderThreadCtx> = Effect.gen(
@@ -36,27 +31,15 @@ export const makeApplyMutation: Effect.Effect<ApplyMutation, never, Scope.Scope
36
31
  [...leaderThreadCtx.schema.mutations.entries()].map(([k, v]) => [k, Schema.hash(v.schema)] as const),
37
32
  )
38
33
 
39
- return (mutationEventEncoded, options) =>
34
+ return (mutationEventEncoded) =>
40
35
  Effect.gen(function* () {
41
- const { schema, db, dbLog } = leaderThreadCtx
42
- const skipMutationLog = options?.skipMutationLog ?? false
36
+ const { mutationEventSchema, schema, db, dbLog } = leaderThreadCtx
37
+ const mutationEventDecoded = Schema.decodeUnknownSync(mutationEventSchema)(mutationEventEncoded)
43
38
 
44
- const mutationName = mutationEventEncoded.mutation
39
+ const mutationName = mutationEventDecoded.mutation
45
40
  const mutationDef = schema.mutations.get(mutationName) ?? shouldNeverHappen(`Unknown mutation: ${mutationName}`)
46
41
 
47
- const execArgsArr = getExecArgsFromMutation({
48
- mutationDef,
49
- mutationEvent: { decoded: undefined, encoded: mutationEventEncoded },
50
- })
51
-
52
- // NOTE we might want to bring this back if we want to debug no-op mutations
53
- // const makeExecuteOptions = (statementSql: string, bindValues: any) => ({
54
- // onRowsChanged: (rowsChanged: number) => {
55
- // if (rowsChanged === 0) {
56
- // console.warn(`Mutation "${mutationDef.name}" did not affect any rows:`, statementSql, bindValues)
57
- // }
58
- // },
59
- // })
42
+ const execArgsArr = getExecArgsFromMutation({ mutationDef, mutationEventDecoded })
60
43
 
61
44
  // console.group('[@livestore/common:leader-thread:applyMutation]', { mutationName })
62
45
 
@@ -70,28 +53,30 @@ export const makeApplyMutation: Effect.Effect<ApplyMutation, never, Scope.Scope
70
53
 
71
54
  const changeset = session.changeset()
72
55
  session.finish()
73
-
74
- // TODO use prepared statements
75
- yield* execSql(
76
- db,
77
- ...insertRow({
78
- tableName: SESSION_CHANGESET_META_TABLE,
79
- columns: sessionChangesetMetaTable.sqliteDef.columns,
80
- values: {
81
- idGlobal: mutationEventEncoded.id.global,
82
- idLocal: mutationEventEncoded.id.local,
83
- // NOTE the changeset will be empty (i.e. null) for no-op mutations
84
- changeset: changeset ?? null,
85
- debug: execArgsArr,
86
- },
87
- }),
88
- )
56
+ // NOTE for no-op mutations (e.g. if the state didn't change) the changeset will be empty
57
+ // TODO possibly write a null value instead of omitting the row
58
+ if (changeset !== undefined && changeset.length > 0) {
59
+ // TODO use prepared statements
60
+ yield* execSql(
61
+ db,
62
+ ...insertRow({
63
+ tableName: SESSION_CHANGESET_META_TABLE,
64
+ columns: sessionChangesetMetaTable.sqliteDef.columns,
65
+ values: {
66
+ idGlobal: mutationEventEncoded.id.global,
67
+ idLocal: mutationEventEncoded.id.local,
68
+ changeset,
69
+ debug: execArgsArr,
70
+ },
71
+ }),
72
+ )
73
+ }
89
74
 
90
75
  // console.groupEnd()
91
76
 
92
77
  // write to mutation_log
93
- const excludeFromMutationLog = shouldExcludeMutationFromLog(mutationName, mutationEventEncoded)
94
- if (skipMutationLog === false && excludeFromMutationLog === false) {
78
+ const excludeFromMutationLog = shouldExcludeMutationFromLog(mutationName, mutationEventDecoded)
79
+ if (excludeFromMutationLog === false) {
95
80
  yield* insertIntoMutationLog(mutationEventEncoded, dbLog, mutationDefSchemaHashMap)
96
81
  } else {
97
82
  // console.debug('[@livestore/common:leader-thread] skipping mutation log write', mutation, statementSql, bindValues)
@@ -101,7 +86,7 @@ export const makeApplyMutation: Effect.Effect<ApplyMutation, never, Scope.Scope
101
86
  attributes: {
102
87
  mutationName: mutationEventEncoded.mutation,
103
88
  mutationId: mutationEventEncoded.id,
104
- 'span.label': `(${mutationEventEncoded.id.global},${mutationEventEncoded.id.local}) ${mutationEventEncoded.mutation}`,
89
+ 'span.label': mutationEventEncoded.mutation,
105
90
  },
106
91
  }),
107
92
  // Effect.logDuration('@livestore/common:leader-thread:applyMutation'),
@@ -147,14 +132,11 @@ const makeShouldExcludeMutationFromLog = memoizeByRef((schema: LiveStoreSchema)
147
132
  ? (migrationOptions.excludeMutations ?? new Set(['livestore.RawSql']))
148
133
  : new Set(['livestore.RawSql'])
149
134
 
150
- return (mutationName: string, mutationEventEncoded: MutationEvent.AnyEncoded): boolean => {
135
+ return (mutationName: string, mutationEventDecoded: MutationEvent.Any): boolean => {
151
136
  if (mutationLogExclude.has(mutationName)) return true
152
137
 
153
138
  const mutationDef = schema.mutations.get(mutationName) ?? shouldNeverHappen(`Unknown mutation: ${mutationName}`)
154
- const execArgsArr = getExecArgsFromMutation({
155
- mutationDef,
156
- mutationEvent: { decoded: undefined, encoded: mutationEventEncoded },
157
- })
139
+ const execArgsArr = getExecArgsFromMutation({ mutationDef, mutationEventDecoded })
158
140
 
159
141
  return execArgsArr.some((_) => _.statementSql.includes('__livestore'))
160
142
  }