@livestore/common 0.0.0-snapshot-2ef046b02334f52613d31dbe06af53487685edc0 → 0.0.0-snapshot-8115ad48d5a57244358c943ecc92bb0a30274b87

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 (272) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/__tests__/fixture.d.ts +83 -221
  3. package/dist/__tests__/fixture.d.ts.map +1 -1
  4. package/dist/__tests__/fixture.js +33 -11
  5. package/dist/__tests__/fixture.js.map +1 -1
  6. package/dist/adapter-types.d.ts +34 -13
  7. package/dist/adapter-types.d.ts.map +1 -1
  8. package/dist/adapter-types.js +20 -2
  9. package/dist/adapter-types.js.map +1 -1
  10. package/dist/bounded-collections.d.ts +1 -1
  11. package/dist/bounded-collections.d.ts.map +1 -1
  12. package/dist/debug-info.d.ts.map +1 -1
  13. package/dist/debug-info.js +1 -0
  14. package/dist/debug-info.js.map +1 -1
  15. package/dist/devtools/devtools-messages-client-session.d.ts +21 -21
  16. package/dist/devtools/devtools-messages-common.d.ts +6 -6
  17. package/dist/devtools/devtools-messages-leader.d.ts +45 -45
  18. package/dist/devtools/devtools-messages-leader.d.ts.map +1 -1
  19. package/dist/devtools/devtools-messages-leader.js +11 -11
  20. package/dist/devtools/devtools-messages-leader.js.map +1 -1
  21. package/dist/index.d.ts +2 -5
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +2 -5
  24. package/dist/index.js.map +1 -1
  25. package/dist/leader-thread/LeaderSyncProcessor.d.ts +25 -12
  26. package/dist/leader-thread/LeaderSyncProcessor.d.ts.map +1 -1
  27. package/dist/leader-thread/LeaderSyncProcessor.js +146 -98
  28. package/dist/leader-thread/LeaderSyncProcessor.js.map +1 -1
  29. package/dist/leader-thread/{apply-mutation.d.ts → apply-event.d.ts} +7 -7
  30. package/dist/leader-thread/apply-event.d.ts.map +1 -0
  31. package/dist/leader-thread/{apply-mutation.js → apply-event.js} +45 -45
  32. package/dist/leader-thread/apply-event.js.map +1 -0
  33. package/dist/leader-thread/eventlog.d.ts +27 -0
  34. package/dist/leader-thread/eventlog.d.ts.map +1 -0
  35. package/dist/leader-thread/eventlog.js +123 -0
  36. package/dist/leader-thread/eventlog.js.map +1 -0
  37. package/dist/leader-thread/leader-worker-devtools.d.ts.map +1 -1
  38. package/dist/leader-thread/leader-worker-devtools.js +21 -19
  39. package/dist/leader-thread/leader-worker-devtools.js.map +1 -1
  40. package/dist/leader-thread/make-leader-thread-layer.d.ts +16 -4
  41. package/dist/leader-thread/make-leader-thread-layer.d.ts.map +1 -1
  42. package/dist/leader-thread/make-leader-thread-layer.js +23 -16
  43. package/dist/leader-thread/make-leader-thread-layer.js.map +1 -1
  44. package/dist/leader-thread/mod.d.ts +1 -1
  45. package/dist/leader-thread/mod.d.ts.map +1 -1
  46. package/dist/leader-thread/mod.js +1 -1
  47. package/dist/leader-thread/mod.js.map +1 -1
  48. package/dist/leader-thread/recreate-db.d.ts.map +1 -1
  49. package/dist/leader-thread/recreate-db.js +6 -7
  50. package/dist/leader-thread/recreate-db.js.map +1 -1
  51. package/dist/leader-thread/types.d.ts +14 -15
  52. package/dist/leader-thread/types.d.ts.map +1 -1
  53. package/dist/materializer-helper.d.ts +23 -0
  54. package/dist/materializer-helper.d.ts.map +1 -0
  55. package/dist/materializer-helper.js +70 -0
  56. package/dist/materializer-helper.js.map +1 -0
  57. package/dist/query-builder/api.d.ts +56 -51
  58. package/dist/query-builder/api.d.ts.map +1 -1
  59. package/dist/query-builder/api.js +3 -5
  60. package/dist/query-builder/api.js.map +1 -1
  61. package/dist/query-builder/astToSql.d.ts.map +1 -1
  62. package/dist/query-builder/astToSql.js +59 -37
  63. package/dist/query-builder/astToSql.js.map +1 -1
  64. package/dist/query-builder/impl.d.ts +2 -3
  65. package/dist/query-builder/impl.d.ts.map +1 -1
  66. package/dist/query-builder/impl.js +48 -46
  67. package/dist/query-builder/impl.js.map +1 -1
  68. package/dist/query-builder/impl.test.d.ts +86 -1
  69. package/dist/query-builder/impl.test.d.ts.map +1 -1
  70. package/dist/query-builder/impl.test.js +223 -36
  71. package/dist/query-builder/impl.test.js.map +1 -1
  72. package/dist/rehydrate-from-eventlog.d.ts +15 -0
  73. package/dist/rehydrate-from-eventlog.d.ts.map +1 -0
  74. package/dist/{rehydrate-from-mutationlog.js → rehydrate-from-eventlog.js} +26 -25
  75. package/dist/rehydrate-from-eventlog.js.map +1 -0
  76. package/dist/schema/EventDef.d.ts +136 -0
  77. package/dist/schema/EventDef.d.ts.map +1 -0
  78. package/dist/schema/EventDef.js +58 -0
  79. package/dist/schema/EventDef.js.map +1 -0
  80. package/dist/schema/EventId.d.ts +7 -2
  81. package/dist/schema/EventId.d.ts.map +1 -1
  82. package/dist/schema/EventId.js +18 -3
  83. package/dist/schema/EventId.js.map +1 -1
  84. package/dist/schema/{MutationEvent.d.ts → LiveStoreEvent.d.ts} +56 -56
  85. package/dist/schema/LiveStoreEvent.d.ts.map +1 -0
  86. package/dist/schema/{MutationEvent.js → LiveStoreEvent.js} +25 -25
  87. package/dist/schema/LiveStoreEvent.js.map +1 -0
  88. package/dist/schema/client-document-def.d.ts +223 -0
  89. package/dist/schema/client-document-def.d.ts.map +1 -0
  90. package/dist/schema/client-document-def.js +170 -0
  91. package/dist/schema/client-document-def.js.map +1 -0
  92. package/dist/schema/client-document-def.test.d.ts +2 -0
  93. package/dist/schema/client-document-def.test.d.ts.map +1 -0
  94. package/dist/schema/client-document-def.test.js +201 -0
  95. package/dist/schema/client-document-def.test.js.map +1 -0
  96. package/dist/schema/db-schema/dsl/mod.d.ts.map +1 -1
  97. package/dist/schema/events.d.ts +2 -0
  98. package/dist/schema/events.d.ts.map +1 -0
  99. package/dist/schema/events.js +2 -0
  100. package/dist/schema/events.js.map +1 -0
  101. package/dist/schema/mod.d.ts +4 -3
  102. package/dist/schema/mod.d.ts.map +1 -1
  103. package/dist/schema/mod.js +4 -3
  104. package/dist/schema/mod.js.map +1 -1
  105. package/dist/schema/schema.d.ts +26 -22
  106. package/dist/schema/schema.d.ts.map +1 -1
  107. package/dist/schema/schema.js +45 -43
  108. package/dist/schema/schema.js.map +1 -1
  109. package/dist/schema/sqlite-state.d.ts +12 -0
  110. package/dist/schema/sqlite-state.d.ts.map +1 -0
  111. package/dist/schema/sqlite-state.js +36 -0
  112. package/dist/schema/sqlite-state.js.map +1 -0
  113. package/dist/schema/system-tables.d.ts +67 -98
  114. package/dist/schema/system-tables.d.ts.map +1 -1
  115. package/dist/schema/system-tables.js +62 -48
  116. package/dist/schema/system-tables.js.map +1 -1
  117. package/dist/schema/table-def.d.ts +26 -96
  118. package/dist/schema/table-def.d.ts.map +1 -1
  119. package/dist/schema/table-def.js +14 -64
  120. package/dist/schema/table-def.js.map +1 -1
  121. package/dist/schema/view.d.ts +3 -0
  122. package/dist/schema/view.d.ts.map +1 -0
  123. package/dist/schema/view.js +3 -0
  124. package/dist/schema/view.js.map +1 -0
  125. package/dist/schema-management/common.d.ts +4 -4
  126. package/dist/schema-management/common.d.ts.map +1 -1
  127. package/dist/schema-management/migrations.d.ts.map +1 -1
  128. package/dist/schema-management/migrations.js +6 -6
  129. package/dist/schema-management/migrations.js.map +1 -1
  130. package/dist/schema-management/validate-mutation-defs.d.ts +3 -3
  131. package/dist/schema-management/validate-mutation-defs.d.ts.map +1 -1
  132. package/dist/schema-management/validate-mutation-defs.js +17 -17
  133. package/dist/schema-management/validate-mutation-defs.js.map +1 -1
  134. package/dist/sync/ClientSessionSyncProcessor.d.ts +7 -7
  135. package/dist/sync/ClientSessionSyncProcessor.d.ts.map +1 -1
  136. package/dist/sync/ClientSessionSyncProcessor.js +33 -30
  137. package/dist/sync/ClientSessionSyncProcessor.js.map +1 -1
  138. package/dist/sync/next/facts.d.ts +19 -19
  139. package/dist/sync/next/facts.d.ts.map +1 -1
  140. package/dist/sync/next/facts.js +2 -2
  141. package/dist/sync/next/facts.js.map +1 -1
  142. package/dist/sync/next/history-dag-common.d.ts +3 -3
  143. package/dist/sync/next/history-dag-common.d.ts.map +1 -1
  144. package/dist/sync/next/history-dag-common.js +1 -1
  145. package/dist/sync/next/history-dag-common.js.map +1 -1
  146. package/dist/sync/next/history-dag.js +1 -1
  147. package/dist/sync/next/history-dag.js.map +1 -1
  148. package/dist/sync/next/rebase-events.d.ts +7 -7
  149. package/dist/sync/next/rebase-events.d.ts.map +1 -1
  150. package/dist/sync/next/rebase-events.js +5 -5
  151. package/dist/sync/next/rebase-events.js.map +1 -1
  152. package/dist/sync/next/test/compact-events.calculator.test.js +38 -33
  153. package/dist/sync/next/test/compact-events.calculator.test.js.map +1 -1
  154. package/dist/sync/next/test/compact-events.test.js +71 -71
  155. package/dist/sync/next/test/compact-events.test.js.map +1 -1
  156. package/dist/sync/next/test/{mutation-fixtures.d.ts → event-fixtures.d.ts} +25 -25
  157. package/dist/sync/next/test/event-fixtures.d.ts.map +1 -0
  158. package/dist/sync/next/test/{mutation-fixtures.js → event-fixtures.js} +60 -25
  159. package/dist/sync/next/test/event-fixtures.js.map +1 -0
  160. package/dist/sync/next/test/mod.d.ts +1 -1
  161. package/dist/sync/next/test/mod.d.ts.map +1 -1
  162. package/dist/sync/next/test/mod.js +1 -1
  163. package/dist/sync/next/test/mod.js.map +1 -1
  164. package/dist/sync/sync.d.ts +3 -3
  165. package/dist/sync/sync.d.ts.map +1 -1
  166. package/dist/sync/syncstate.d.ts +30 -30
  167. package/dist/sync/syncstate.d.ts.map +1 -1
  168. package/dist/sync/syncstate.js +73 -40
  169. package/dist/sync/syncstate.js.map +1 -1
  170. package/dist/sync/syncstate.test.js +175 -184
  171. package/dist/sync/syncstate.test.js.map +1 -1
  172. package/dist/sync/validate-push-payload.d.ts +2 -2
  173. package/dist/sync/validate-push-payload.d.ts.map +1 -1
  174. package/dist/sync/validate-push-payload.js.map +1 -1
  175. package/dist/version.d.ts +1 -1
  176. package/dist/version.js +1 -1
  177. package/package.json +3 -3
  178. package/src/__tests__/fixture.ts +36 -15
  179. package/src/adapter-types.ts +33 -13
  180. package/src/debug-info.ts +1 -0
  181. package/src/devtools/devtools-messages-leader.ts +13 -13
  182. package/src/index.ts +2 -5
  183. package/src/leader-thread/LeaderSyncProcessor.ts +210 -138
  184. package/src/leader-thread/{apply-mutation.ts → apply-event.ts} +61 -61
  185. package/src/leader-thread/eventlog.ts +199 -0
  186. package/src/leader-thread/leader-worker-devtools.ts +22 -19
  187. package/src/leader-thread/make-leader-thread-layer.ts +51 -29
  188. package/src/leader-thread/mod.ts +1 -1
  189. package/src/leader-thread/recreate-db.ts +6 -8
  190. package/src/leader-thread/types.ts +15 -16
  191. package/src/materializer-helper.ts +110 -0
  192. package/src/query-builder/api.ts +77 -103
  193. package/src/query-builder/astToSql.ts +68 -39
  194. package/src/query-builder/impl.test.ts +239 -42
  195. package/src/query-builder/impl.ts +72 -56
  196. package/src/{rehydrate-from-mutationlog.ts → rehydrate-from-eventlog.ts} +35 -38
  197. package/src/schema/EventDef.ts +216 -0
  198. package/src/schema/EventId.ts +23 -4
  199. package/src/schema/{MutationEvent.ts → LiveStoreEvent.ts} +68 -69
  200. package/src/schema/client-document-def.test.ts +239 -0
  201. package/src/schema/client-document-def.ts +444 -0
  202. package/src/schema/db-schema/dsl/mod.ts +0 -1
  203. package/src/schema/events.ts +1 -0
  204. package/src/schema/mod.ts +4 -3
  205. package/src/schema/schema.ts +78 -68
  206. package/src/schema/sqlite-state.ts +62 -0
  207. package/src/schema/system-tables.ts +42 -53
  208. package/src/schema/table-def.ts +51 -209
  209. package/src/schema/view.ts +2 -0
  210. package/src/schema-management/common.ts +4 -4
  211. package/src/schema-management/migrations.ts +8 -9
  212. package/src/schema-management/validate-mutation-defs.ts +22 -24
  213. package/src/sync/ClientSessionSyncProcessor.ts +41 -36
  214. package/src/sync/next/facts.ts +31 -32
  215. package/src/sync/next/history-dag-common.ts +4 -4
  216. package/src/sync/next/history-dag.ts +1 -1
  217. package/src/sync/next/rebase-events.ts +13 -13
  218. package/src/sync/next/test/compact-events.calculator.test.ts +45 -45
  219. package/src/sync/next/test/compact-events.test.ts +73 -73
  220. package/src/sync/next/test/event-fixtures.ts +219 -0
  221. package/src/sync/next/test/mod.ts +1 -1
  222. package/src/sync/sync.ts +3 -3
  223. package/src/sync/syncstate.test.ts +180 -189
  224. package/src/sync/syncstate.ts +162 -100
  225. package/src/sync/validate-push-payload.ts +2 -2
  226. package/src/version.ts +1 -1
  227. package/tsconfig.json +1 -0
  228. package/dist/derived-mutations.d.ts +0 -109
  229. package/dist/derived-mutations.d.ts.map +0 -1
  230. package/dist/derived-mutations.js +0 -54
  231. package/dist/derived-mutations.js.map +0 -1
  232. package/dist/derived-mutations.test.d.ts +0 -2
  233. package/dist/derived-mutations.test.d.ts.map +0 -1
  234. package/dist/derived-mutations.test.js +0 -93
  235. package/dist/derived-mutations.test.js.map +0 -1
  236. package/dist/init-singleton-tables.d.ts +0 -4
  237. package/dist/init-singleton-tables.d.ts.map +0 -1
  238. package/dist/init-singleton-tables.js +0 -16
  239. package/dist/init-singleton-tables.js.map +0 -1
  240. package/dist/leader-thread/apply-mutation.d.ts.map +0 -1
  241. package/dist/leader-thread/apply-mutation.js.map +0 -1
  242. package/dist/leader-thread/mutationlog.d.ts +0 -27
  243. package/dist/leader-thread/mutationlog.d.ts.map +0 -1
  244. package/dist/leader-thread/mutationlog.js +0 -124
  245. package/dist/leader-thread/mutationlog.js.map +0 -1
  246. package/dist/mutation.d.ts +0 -20
  247. package/dist/mutation.d.ts.map +0 -1
  248. package/dist/mutation.js +0 -68
  249. package/dist/mutation.js.map +0 -1
  250. package/dist/query-info.d.ts +0 -41
  251. package/dist/query-info.d.ts.map +0 -1
  252. package/dist/query-info.js +0 -7
  253. package/dist/query-info.js.map +0 -1
  254. package/dist/rehydrate-from-mutationlog.d.ts +0 -15
  255. package/dist/rehydrate-from-mutationlog.d.ts.map +0 -1
  256. package/dist/rehydrate-from-mutationlog.js.map +0 -1
  257. package/dist/schema/MutationEvent.d.ts.map +0 -1
  258. package/dist/schema/MutationEvent.js.map +0 -1
  259. package/dist/schema/mutations.d.ts +0 -115
  260. package/dist/schema/mutations.d.ts.map +0 -1
  261. package/dist/schema/mutations.js +0 -42
  262. package/dist/schema/mutations.js.map +0 -1
  263. package/dist/sync/next/test/mutation-fixtures.d.ts.map +0 -1
  264. package/dist/sync/next/test/mutation-fixtures.js.map +0 -1
  265. package/src/derived-mutations.test.ts +0 -101
  266. package/src/derived-mutations.ts +0 -170
  267. package/src/init-singleton-tables.ts +0 -24
  268. package/src/leader-thread/mutationlog.ts +0 -202
  269. package/src/mutation.ts +0 -108
  270. package/src/query-info.ts +0 -83
  271. package/src/schema/mutations.ts +0 -193
  272. package/src/sync/next/test/mutation-fixtures.ts +0 -228
@@ -2,67 +2,67 @@ import { LS_DEV, memoizeByRef, shouldNeverHappen } from '@livestore/utils'
2
2
  import { Effect, ReadonlyArray, Schema } from '@livestore/utils/effect'
3
3
 
4
4
  import type { SqliteDb } from '../adapter-types.js'
5
- import { getExecArgsFromMutation } from '../mutation.js'
6
- import type { LiveStoreSchema, MutationEvent, SessionChangesetMetaRow } from '../schema/mod.js'
5
+ import { getExecArgsFromEvent } from '../materializer-helper.js'
6
+ import type { LiveStoreEvent, LiveStoreSchema, SessionChangesetMetaRow } from '../schema/mod.js'
7
7
  import {
8
8
  EventId,
9
- getMutationDef,
10
- MUTATION_LOG_META_TABLE,
9
+ EVENTLOG_META_TABLE,
10
+ getEventDef,
11
11
  SESSION_CHANGESET_META_TABLE,
12
12
  sessionChangesetMetaTable,
13
13
  } from '../schema/mod.js'
14
14
  import { insertRow } from '../sql-queries/index.js'
15
15
  import { sql } from '../util.js'
16
16
  import { execSql, execSqlPrepared } from './connection.js'
17
- import * as Mutationlog from './mutationlog.js'
18
- import type { ApplyMutation } from './types.js'
17
+ import * as Eventlog from './eventlog.js'
18
+ import type { ApplyEvent } from './types.js'
19
19
 
20
- export const makeApplyMutation = ({
20
+ export const makeApplyEvent = ({
21
21
  schema,
22
22
  dbReadModel: db,
23
- dbMutationLog,
23
+ dbEventlog,
24
24
  }: {
25
25
  schema: LiveStoreSchema
26
26
  dbReadModel: SqliteDb
27
- dbMutationLog: SqliteDb
28
- }): Effect.Effect<ApplyMutation, never> =>
27
+ dbEventlog: SqliteDb
28
+ }): Effect.Effect<ApplyEvent, never> =>
29
29
  Effect.gen(function* () {
30
- const shouldExcludeMutationFromLog = makeShouldExcludeMutationFromLog(schema)
30
+ const shouldExcludeEventFromLog = makeShouldExcludeEventFromLog(schema)
31
31
 
32
- const mutationDefSchemaHashMap = new Map(
32
+ const eventDefSchemaHashMap = new Map(
33
33
  // TODO Running `Schema.hash` can be a bottleneck for larger schemas. There is an opportunity to run this
34
34
  // at build time and lookup the pre-computed hash at runtime.
35
35
  // Also see https://github.com/Effect-TS/effect/issues/2719
36
- [...schema.mutations.map.entries()].map(([k, v]) => [k, Schema.hash(v.schema)] as const),
36
+ [...schema.eventsDefsMap.entries()].map(([k, v]) => [k, Schema.hash(v.schema)] as const),
37
37
  )
38
38
 
39
- return (mutationEventEncoded, options) =>
39
+ return (eventEncoded, options) =>
40
40
  Effect.gen(function* () {
41
- const skipMutationLog = options?.skipMutationLog ?? false
41
+ const skipEventlog = options?.skipEventlog ?? false
42
42
 
43
- const mutationName = mutationEventEncoded.mutation
44
- const mutationDef = getMutationDef(schema, mutationName)
43
+ const eventName = eventEncoded.name
44
+ const eventDef = getEventDef(schema, eventName)
45
45
 
46
- const execArgsArr = getExecArgsFromMutation({
47
- mutationDef,
48
- mutationEvent: { decoded: undefined, encoded: mutationEventEncoded },
46
+ const execArgsArr = getExecArgsFromEvent({
47
+ eventDef,
48
+ event: { decoded: undefined, encoded: eventEncoded },
49
49
  })
50
50
 
51
- // NOTE we might want to bring this back if we want to debug no-op mutations
51
+ // NOTE we might want to bring this back if we want to debug no-op events
52
52
  // const makeExecuteOptions = (statementSql: string, bindValues: any) => ({
53
53
  // onRowsChanged: (rowsChanged: number) => {
54
54
  // if (rowsChanged === 0) {
55
- // console.warn(`Mutation "${mutationDef.name}" did not affect any rows:`, statementSql, bindValues)
55
+ // console.warn(`Event "${eventDef.name}" did not affect any rows:`, statementSql, bindValues)
56
56
  // }
57
57
  // },
58
58
  // })
59
59
 
60
- // console.group('[@livestore/common:leader-thread:applyMutation]', { mutationName })
60
+ // console.group('[@livestore/common:leader-thread:applyEvent]', { eventName })
61
61
 
62
62
  const session = db.session()
63
63
 
64
64
  for (const { statementSql, bindValues } of execArgsArr) {
65
- // console.debug(mutationName, statementSql, bindValues)
65
+ // console.debug(eventName, statementSql, bindValues)
66
66
  // TODO use cached prepared statements instead of exec
67
67
  yield* execSqlPrepared(db, statementSql, bindValues)
68
68
  }
@@ -77,9 +77,9 @@ export const makeApplyMutation = ({
77
77
  tableName: SESSION_CHANGESET_META_TABLE,
78
78
  columns: sessionChangesetMetaTable.sqliteDef.columns,
79
79
  values: {
80
- idGlobal: mutationEventEncoded.id.global,
81
- idClient: mutationEventEncoded.id.client,
82
- // NOTE the changeset will be empty (i.e. null) for no-op mutations
80
+ idGlobal: eventEncoded.id.global,
81
+ idClient: eventEncoded.id.client,
82
+ // NOTE the changeset will be empty (i.e. null) for no-op events
83
83
  changeset: changeset ?? null,
84
84
  debug: LS_DEV ? execArgsArr : null,
85
85
  },
@@ -88,22 +88,22 @@ export const makeApplyMutation = ({
88
88
 
89
89
  // console.groupEnd()
90
90
 
91
- // write to mutation_log
92
- const excludeFromMutationLog = shouldExcludeMutationFromLog(mutationName, mutationEventEncoded)
93
- if (skipMutationLog === false && excludeFromMutationLog === false) {
94
- const mutationName = mutationEventEncoded.mutation
95
- const mutationDefSchemaHash =
96
- mutationDefSchemaHashMap.get(mutationName) ?? shouldNeverHappen(`Unknown mutation: ${mutationName}`)
97
-
98
- yield* Mutationlog.insertIntoMutationLog(
99
- mutationEventEncoded,
100
- dbMutationLog,
101
- mutationDefSchemaHash,
102
- mutationEventEncoded.clientId,
103
- mutationEventEncoded.sessionId,
91
+ // write to eventlog
92
+ const excludeFromEventlog = shouldExcludeEventFromLog(eventName, eventEncoded)
93
+ if (skipEventlog === false && excludeFromEventlog === false) {
94
+ const eventName = eventEncoded.name
95
+ const eventDefSchemaHash =
96
+ eventDefSchemaHashMap.get(eventName) ?? shouldNeverHappen(`Unknown event definition: ${eventName}`)
97
+
98
+ yield* Eventlog.insertIntoEventlog(
99
+ eventEncoded,
100
+ dbEventlog,
101
+ eventDefSchemaHash,
102
+ eventEncoded.clientId,
103
+ eventEncoded.sessionId,
104
104
  )
105
105
  } else {
106
- // console.debug('[@livestore/common:leader-thread] skipping mutation log write', mutation, statementSql, bindValues)
106
+ // console.debug('[@livestore/common:leader-thread] skipping eventlog write', mutation, statementSql, bindValues)
107
107
  }
108
108
 
109
109
  return {
@@ -116,24 +116,24 @@ export const makeApplyMutation = ({
116
116
  : { _tag: 'no-op' as const },
117
117
  }
118
118
  }).pipe(
119
- Effect.withSpan(`@livestore/common:leader-thread:applyMutation`, {
119
+ Effect.withSpan(`@livestore/common:leader-thread:applyEvent`, {
120
120
  attributes: {
121
- mutationName: mutationEventEncoded.mutation,
122
- mutationId: mutationEventEncoded.id,
123
- 'span.label': `${EventId.toString(mutationEventEncoded.id)} ${mutationEventEncoded.mutation}`,
121
+ eventName: eventEncoded.name,
122
+ mutationId: eventEncoded.id,
123
+ 'span.label': `${EventId.toString(eventEncoded.id)} ${eventEncoded.name}`,
124
124
  },
125
125
  }),
126
- // Effect.logDuration('@livestore/common:leader-thread:applyMutation'),
126
+ // Effect.logDuration('@livestore/common:leader-thread:applyEvent'),
127
127
  )
128
128
  })
129
129
 
130
130
  export const rollback = ({
131
131
  db,
132
- dbMutationLog,
132
+ dbEventlog,
133
133
  eventIdsToRollback,
134
134
  }: {
135
135
  db: SqliteDb
136
- dbMutationLog: SqliteDb
136
+ dbEventlog: SqliteDb
137
137
  eventIdsToRollback: EventId.EventId[]
138
138
  }) =>
139
139
  Effect.gen(function* () {
@@ -163,10 +163,10 @@ export const rollback = ({
163
163
  )
164
164
  }
165
165
 
166
- // Delete the mutation log rows
166
+ // Delete the eventlog rows
167
167
  for (const eventIdPairChunk of eventIdPairChunks) {
168
- dbMutationLog.execute(
169
- sql`DELETE FROM ${MUTATION_LOG_META_TABLE} WHERE (idGlobal, idClient) IN (${eventIdPairChunk.join(', ')})`,
168
+ dbEventlog.execute(
169
+ sql`DELETE FROM ${EVENTLOG_META_TABLE} WHERE (idGlobal, idClient) IN (${eventIdPairChunk.join(', ')})`,
170
170
  )
171
171
  }
172
172
  }).pipe(
@@ -176,20 +176,20 @@ export const rollback = ({
176
176
  )
177
177
 
178
178
  // TODO let's consider removing this "should exclude" mechanism in favour of log compaction etc
179
- const makeShouldExcludeMutationFromLog = memoizeByRef((schema: LiveStoreSchema) => {
179
+ const makeShouldExcludeEventFromLog = memoizeByRef((schema: LiveStoreSchema) => {
180
180
  const migrationOptions = schema.migrationOptions
181
- const mutationLogExclude =
182
- migrationOptions.strategy === 'from-mutation-log'
183
- ? (migrationOptions.excludeMutations ?? new Set(['livestore.RawSql']))
181
+ const eventlogExclude =
182
+ migrationOptions.strategy === 'from-eventlog'
183
+ ? (migrationOptions.excludeEvents ?? new Set(['livestore.RawSql']))
184
184
  : new Set(['livestore.RawSql'])
185
185
 
186
- return (mutationName: string, mutationEventEncoded: MutationEvent.AnyEncoded): boolean => {
187
- if (mutationLogExclude.has(mutationName)) return true
186
+ return (eventName: string, eventEncoded: LiveStoreEvent.AnyEncoded): boolean => {
187
+ if (eventlogExclude.has(eventName)) return true
188
188
 
189
- const mutationDef = getMutationDef(schema, mutationName)
190
- const execArgsArr = getExecArgsFromMutation({
191
- mutationDef,
192
- mutationEvent: { decoded: undefined, encoded: mutationEventEncoded },
189
+ const eventDef = getEventDef(schema, eventName)
190
+ const execArgsArr = getExecArgsFromEvent({
191
+ eventDef,
192
+ event: { decoded: undefined, encoded: eventEncoded },
193
193
  })
194
194
 
195
195
  return execArgsArr.some((_) => _.statementSql.includes('__livestore'))
@@ -0,0 +1,199 @@
1
+ import { LS_DEV, shouldNeverHappen } from '@livestore/utils'
2
+ import { Effect, Option, Schema } from '@livestore/utils/effect'
3
+
4
+ import type { SqliteDb } from '../adapter-types.js'
5
+ import * as EventId from '../schema/EventId.js'
6
+ import * as LiveStoreEvent from '../schema/LiveStoreEvent.js'
7
+ import {
8
+ EVENTLOG_META_TABLE,
9
+ eventlogMetaTable,
10
+ sessionChangesetMetaTable,
11
+ SYNC_STATUS_TABLE,
12
+ syncStatusTable,
13
+ } from '../schema/system-tables.js'
14
+ import { migrateTable } from '../schema-management/migrations.js'
15
+ import { insertRow, updateRows } from '../sql-queries/sql-queries.js'
16
+ import type { PreparedBindValues } from '../util.js'
17
+ import { prepareBindValues, sql } from '../util.js'
18
+ import { execSql } from './connection.js'
19
+ import type { InitialSyncInfo } from './types.js'
20
+ import { LeaderThreadCtx } from './types.js'
21
+
22
+ export const initEventlogDb = (dbEventlog: SqliteDb) =>
23
+ Effect.gen(function* () {
24
+ yield* migrateTable({
25
+ db: dbEventlog,
26
+ behaviour: 'create-if-not-exists',
27
+ tableAst: eventlogMetaTable.sqliteDef.ast,
28
+ skipMetaTable: true,
29
+ })
30
+
31
+ yield* migrateTable({
32
+ db: dbEventlog,
33
+ behaviour: 'create-if-not-exists',
34
+ tableAst: syncStatusTable.sqliteDef.ast,
35
+ skipMetaTable: true,
36
+ })
37
+
38
+ // Create sync status row if it doesn't exist
39
+ yield* execSql(
40
+ dbEventlog,
41
+ sql`INSERT INTO ${SYNC_STATUS_TABLE} (head)
42
+ SELECT ${EventId.ROOT.global}
43
+ WHERE NOT EXISTS (SELECT 1 FROM ${SYNC_STATUS_TABLE})`,
44
+ {},
45
+ )
46
+ })
47
+
48
+ /** Exclusive of the "since event" */
49
+ export const getEventsSince = (
50
+ since: EventId.EventId,
51
+ ): Effect.Effect<ReadonlyArray<LiveStoreEvent.EncodedWithMeta>, never, LeaderThreadCtx> =>
52
+ Effect.gen(function* () {
53
+ const { dbEventlog, dbReadModel } = yield* LeaderThreadCtx
54
+
55
+ const query = eventlogMetaTable.where('idGlobal', '>=', since.global).asSql()
56
+ const pendingEventsRaw = dbEventlog.select(query.query, prepareBindValues(query.bindValues, query.query))
57
+ const pendingEvents = Schema.decodeUnknownSync(eventlogMetaTable.rowSchema.pipe(Schema.Array))(pendingEventsRaw)
58
+
59
+ const sessionChangesetRows = sessionChangesetMetaTable.where('idGlobal', '>=', since.global).asSql()
60
+ const sessionChangesetRowsRaw = dbReadModel.select(
61
+ sessionChangesetRows.query,
62
+ prepareBindValues(sessionChangesetRows.bindValues, sessionChangesetRows.query),
63
+ )
64
+ const sessionChangesetRowsDecoded = Schema.decodeUnknownSync(
65
+ sessionChangesetMetaTable.rowSchema.pipe(Schema.Array),
66
+ )(sessionChangesetRowsRaw)
67
+
68
+ return pendingEvents
69
+ .map((eventlogEvent) => {
70
+ const sessionChangeset = sessionChangesetRowsDecoded.find(
71
+ (readModelEvent) =>
72
+ readModelEvent.idGlobal === eventlogEvent.idGlobal && readModelEvent.idClient === eventlogEvent.idClient,
73
+ )
74
+ return LiveStoreEvent.EncodedWithMeta.make({
75
+ name: eventlogEvent.name,
76
+ args: eventlogEvent.argsJson,
77
+ id: { global: eventlogEvent.idGlobal, client: eventlogEvent.idClient },
78
+ parentId: { global: eventlogEvent.parentIdGlobal, client: eventlogEvent.parentIdClient },
79
+ clientId: eventlogEvent.clientId,
80
+ sessionId: eventlogEvent.sessionId,
81
+ meta: {
82
+ sessionChangeset:
83
+ sessionChangeset && sessionChangeset.changeset !== null
84
+ ? {
85
+ _tag: 'sessionChangeset' as const,
86
+ data: sessionChangeset.changeset,
87
+ debug: sessionChangeset.debug,
88
+ }
89
+ : { _tag: 'unset' as const },
90
+ syncMetadata: eventlogEvent.syncMetadataJson,
91
+ },
92
+ })
93
+ })
94
+ .filter((_) => EventId.compare(_.id, since) > 0)
95
+ .sort((a, b) => EventId.compare(a.id, b.id))
96
+ })
97
+
98
+ export const getClientHeadFromDb = (dbEventlog: SqliteDb): EventId.EventId => {
99
+ const res = dbEventlog.select<{ idGlobal: EventId.GlobalEventId; idClient: EventId.ClientEventId }>(
100
+ sql`select idGlobal, idClient from ${EVENTLOG_META_TABLE} order by idGlobal DESC, idClient DESC limit 1`,
101
+ )[0]
102
+
103
+ return res ? { global: res.idGlobal, client: res.idClient } : EventId.ROOT
104
+ }
105
+
106
+ export const getBackendHeadFromDb = (dbEventlog: SqliteDb): EventId.GlobalEventId =>
107
+ dbEventlog.select<{ head: EventId.GlobalEventId }>(sql`select head from ${SYNC_STATUS_TABLE}`)[0]?.head ??
108
+ EventId.ROOT.global
109
+
110
+ // TODO use prepared statements
111
+ export const updateBackendHead = (dbEventlog: SqliteDb, head: EventId.EventId) =>
112
+ dbEventlog.execute(sql`UPDATE ${SYNC_STATUS_TABLE} SET head = ${head.global}`)
113
+
114
+ export const insertIntoEventlog = (
115
+ eventEncoded: LiveStoreEvent.EncodedWithMeta,
116
+ dbEventlog: SqliteDb,
117
+ eventDefSchemaHash: number,
118
+ clientId: string,
119
+ sessionId: string,
120
+ ) =>
121
+ Effect.gen(function* () {
122
+ // Check history consistency during LS_DEV
123
+ if (LS_DEV && eventEncoded.parentId.global !== EventId.ROOT.global) {
124
+ const parentEventExists =
125
+ dbEventlog.select<{ count: number }>(
126
+ `SELECT COUNT(*) as count FROM ${EVENTLOG_META_TABLE} WHERE idGlobal = ? AND idClient = ?`,
127
+ [eventEncoded.parentId.global, eventEncoded.parentId.client] as any as PreparedBindValues,
128
+ )[0]!.count === 1
129
+
130
+ if (parentEventExists === false) {
131
+ shouldNeverHappen(
132
+ `Parent mutation ${eventEncoded.parentId.global},${eventEncoded.parentId.client} does not exist`,
133
+ )
134
+ }
135
+ }
136
+
137
+ // TODO use prepared statements
138
+ yield* execSql(
139
+ dbEventlog,
140
+ ...insertRow({
141
+ tableName: EVENTLOG_META_TABLE,
142
+ columns: eventlogMetaTable.sqliteDef.columns,
143
+ values: {
144
+ idGlobal: eventEncoded.id.global,
145
+ idClient: eventEncoded.id.client,
146
+ parentIdGlobal: eventEncoded.parentId.global,
147
+ parentIdClient: eventEncoded.parentId.client,
148
+ name: eventEncoded.name,
149
+ argsJson: eventEncoded.args ?? {},
150
+ clientId,
151
+ sessionId,
152
+ schemaHash: eventDefSchemaHash,
153
+ syncMetadataJson: eventEncoded.meta.syncMetadata,
154
+ },
155
+ }),
156
+ )
157
+ })
158
+
159
+ export const updateSyncMetadata = (items: ReadonlyArray<LiveStoreEvent.EncodedWithMeta>) =>
160
+ Effect.gen(function* () {
161
+ const { dbEventlog } = yield* LeaderThreadCtx
162
+
163
+ // TODO try to do this in a single query
164
+ for (let i = 0; i < items.length; i++) {
165
+ const event = items[i]!
166
+
167
+ yield* execSql(
168
+ dbEventlog,
169
+ ...updateRows({
170
+ tableName: EVENTLOG_META_TABLE,
171
+ columns: eventlogMetaTable.sqliteDef.columns,
172
+ where: { idGlobal: event.id.global, idClient: event.id.client },
173
+ updateValues: { syncMetadataJson: event.meta.syncMetadata },
174
+ }),
175
+ )
176
+ }
177
+ })
178
+
179
+ export const getSyncBackendCursorInfo = (remoteHead: EventId.GlobalEventId) =>
180
+ Effect.gen(function* () {
181
+ const { dbEventlog } = yield* LeaderThreadCtx
182
+
183
+ if (remoteHead === EventId.ROOT.global) return Option.none()
184
+
185
+ const EventlogQuerySchema = Schema.Struct({
186
+ syncMetadataJson: Schema.parseJson(Schema.Option(Schema.JsonValue)),
187
+ }).pipe(Schema.pluck('syncMetadataJson'), Schema.Array, Schema.head)
188
+
189
+ const syncMetadataOption = yield* Effect.sync(() =>
190
+ dbEventlog.select<{ syncMetadataJson: string }>(
191
+ sql`SELECT syncMetadataJson FROM ${EVENTLOG_META_TABLE} WHERE idGlobal = ${remoteHead} ORDER BY idClient ASC LIMIT 1`,
192
+ ),
193
+ ).pipe(Effect.andThen(Schema.decode(EventlogQuerySchema)), Effect.map(Option.flatten), Effect.orDie)
194
+
195
+ return Option.some({
196
+ cursor: { global: remoteHead, client: EventId.clientDefault },
197
+ metadata: syncMetadataOption,
198
+ }) satisfies InitialSyncInfo
199
+ }).pipe(Effect.withSpan('@livestore/common:eventlog:getSyncBackendCursorInfo', { attributes: { remoteHead } }))
@@ -2,7 +2,7 @@ import { Effect, FiberMap, Option, Stream, SubscriptionRef } from '@livestore/ut
2
2
  import { nanoid } from '@livestore/utils/nanoid'
3
3
 
4
4
  import { Devtools, IntentionalShutdownCause, liveStoreVersion, UnexpectedError } from '../index.js'
5
- import { MUTATION_LOG_META_TABLE, SCHEMA_META_TABLE, SCHEMA_MUTATIONS_META_TABLE } from '../schema/mod.js'
5
+ import { EVENTLOG_META_TABLE, SCHEMA_EVENT_DEFS_META_TABLE, SCHEMA_META_TABLE } from '../schema/mod.js'
6
6
  import type { DevtoolsOptions, PersistenceInfoPair } from './types.js'
7
7
  import { LeaderThreadCtx } from './types.js'
8
8
 
@@ -33,7 +33,10 @@ export const bootDevtools = (options: DevtoolsOptions) =>
33
33
  Effect.ignoreLogged,
34
34
  )
35
35
 
36
- yield* syncProcessor.pull({ cursor: syncProcessor.getMergeCounter() }).pipe(
36
+ const syncState = yield* syncProcessor.syncState
37
+ const mergeCounter = syncProcessor.getMergeCounter()
38
+
39
+ yield* syncProcessor.pull({ cursor: { mergeCounter, eventId: syncState.localHead } }).pipe(
37
40
  Stream.tap(({ payload }) => sendMessage(Devtools.Leader.SyncPull.make({ payload, liveStoreVersion }))),
38
41
  Stream.runDrain,
39
42
  Effect.forkScoped,
@@ -60,7 +63,7 @@ const listenToDevtools = ({
60
63
  syncBackend,
61
64
  makeSqliteDb,
62
65
  dbReadModel,
63
- dbMutationLog,
66
+ dbEventlog,
64
67
  shutdownStateSubRef,
65
68
  shutdownChannel,
66
69
  syncProcessor,
@@ -140,20 +143,20 @@ const listenToDevtools = ({
140
143
  }
141
144
 
142
145
  try {
143
- if (tableNames.has(MUTATION_LOG_META_TABLE)) {
144
- // Is mutation log
146
+ if (tableNames.has(EVENTLOG_META_TABLE)) {
147
+ // Is eventlog
145
148
  yield* SubscriptionRef.set(shutdownStateSubRef, 'shutting-down')
146
149
 
147
- dbMutationLog.import(data)
150
+ dbEventlog.import(data)
148
151
 
149
152
  dbReadModel.destroy()
150
- } else if (tableNames.has(SCHEMA_META_TABLE) && tableNames.has(SCHEMA_MUTATIONS_META_TABLE)) {
153
+ } else if (tableNames.has(SCHEMA_META_TABLE) && tableNames.has(SCHEMA_EVENT_DEFS_META_TABLE)) {
151
154
  // Is read model
152
155
  yield* SubscriptionRef.set(shutdownStateSubRef, 'shutting-down')
153
156
 
154
157
  dbReadModel.import(data)
155
158
 
156
- dbMutationLog.destroy()
159
+ dbEventlog.destroy()
157
160
  } else {
158
161
  yield* sendMessage(
159
162
  Devtools.Leader.LoadDatabaseFile.Error.make({
@@ -187,7 +190,7 @@ const listenToDevtools = ({
187
190
  dbReadModel.destroy()
188
191
 
189
192
  if (mode === 'all-data') {
190
- dbMutationLog.destroy()
193
+ dbEventlog.destroy()
191
194
  }
192
195
 
193
196
  yield* sendMessage(Devtools.Leader.ResetAllData.Success.make({ ...reqPayload }))
@@ -204,33 +207,33 @@ const listenToDevtools = ({
204
207
 
205
208
  const dbSizeQuery = `SELECT page_count * page_size as size FROM pragma_page_count(), pragma_page_size();`
206
209
  const dbFileSize = dbReadModel.select<{ size: number }>(dbSizeQuery, undefined)[0]!.size
207
- const mutationLogFileSize = dbMutationLog.select<{ size: number }>(dbSizeQuery, undefined)[0]!.size
210
+ const eventlogFileSize = dbEventlog.select<{ size: number }>(dbSizeQuery, undefined)[0]!.size
208
211
 
209
212
  yield* sendMessage(
210
213
  Devtools.Leader.DatabaseFileInfoRes.make({
211
214
  readModel: { fileSize: dbFileSize, persistenceInfo: persistenceInfo.readModel },
212
- mutationLog: { fileSize: mutationLogFileSize, persistenceInfo: persistenceInfo.mutationLog },
215
+ eventlog: { fileSize: eventlogFileSize, persistenceInfo: persistenceInfo.eventlog },
213
216
  ...reqPayload,
214
217
  }),
215
218
  )
216
219
 
217
220
  return
218
221
  }
219
- case 'LSD.Leader.MutationLogReq': {
220
- const mutationLog = dbMutationLog.export()
222
+ case 'LSD.Leader.EventlogReq': {
223
+ const eventlog = dbEventlog.export()
221
224
 
222
- yield* sendMessage(Devtools.Leader.MutationLogRes.make({ mutationLog, ...reqPayload }))
225
+ yield* sendMessage(Devtools.Leader.EventlogRes.make({ eventlog, ...reqPayload }))
223
226
 
224
227
  return
225
228
  }
226
- case 'LSD.Leader.RunMutationReq': {
229
+ case 'LSD.Leader.CommitEventReq': {
227
230
  yield* syncProcessor.pushPartial({
228
- mutationEvent: decodedEvent.mutationEventEncoded,
231
+ event: decodedEvent.eventEncoded,
229
232
  clientId: `devtools-${clientId}`,
230
233
  sessionId: `devtools-${clientId}`,
231
234
  })
232
235
 
233
- yield* sendMessage(Devtools.Leader.RunMutationRes.make({ ...reqPayload }))
236
+ yield* sendMessage(Devtools.Leader.CommitEventRes.make({ ...reqPayload }))
234
237
 
235
238
  return
236
239
  }
@@ -242,10 +245,10 @@ const listenToDevtools = ({
242
245
  yield* syncBackend.pull(Option.none()).pipe(
243
246
  Stream.map((_) => _.batch),
244
247
  Stream.flattenIterables,
245
- Stream.tap(({ mutationEventEncoded, metadata }) =>
248
+ Stream.tap(({ eventEncoded, metadata }) =>
246
249
  sendMessage(
247
250
  Devtools.Leader.SyncHistoryRes.make({
248
- mutationEventEncoded,
251
+ eventEncoded,
249
252
  metadata,
250
253
  subscriptionId,
251
254
  ...reqPayload,