@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
@@ -1,88 +1,85 @@
1
1
  import { memoizeByRef } from '@livestore/utils'
2
2
  import { Chunk, Effect, Option, Schema, Stream } from '@livestore/utils/effect'
3
3
 
4
- import { type MigrationOptionsFromMutationLog, type SqliteDb, UnexpectedError } from './adapter-types.js'
5
- import type { ApplyMutation } from './leader-thread/mod.js'
6
- import type { LiveStoreSchema, MutationDef, MutationLogMetaRow } from './schema/mod.js'
7
- import { EventId, getMutationDef, MUTATION_LOG_META_TABLE, MutationEvent } from './schema/mod.js'
4
+ import { type MigrationOptionsFromEventlog, type SqliteDb, UnexpectedError } from './adapter-types.js'
5
+ import type { ApplyEvent } from './leader-thread/mod.js'
6
+ import type { EventDef, EventlogMetaRow, LiveStoreSchema } from './schema/mod.js'
7
+ import { EventId, EVENTLOG_META_TABLE, getEventDef, LiveStoreEvent } from './schema/mod.js'
8
8
  import type { PreparedBindValues } from './util.js'
9
9
  import { sql } from './util.js'
10
10
 
11
- export const rehydrateFromMutationLog = ({
12
- dbMutationLog,
11
+ export const rehydrateFromEventlog = ({
12
+ dbEventlog,
13
13
  // TODO re-use this db when bringing back the boot in-memory db implementation
14
14
  // db,
15
15
  schema,
16
16
  migrationOptions,
17
17
  onProgress,
18
- applyMutation,
18
+ applyEvent,
19
19
  }: {
20
- dbMutationLog: SqliteDb
20
+ dbEventlog: SqliteDb
21
21
  // db: SqliteDb
22
22
  schema: LiveStoreSchema
23
- migrationOptions: MigrationOptionsFromMutationLog
23
+ migrationOptions: MigrationOptionsFromEventlog
24
24
  onProgress: (_: { done: number; total: number }) => Effect.Effect<void>
25
- applyMutation: ApplyMutation
25
+ applyEvent: ApplyEvent
26
26
  }) =>
27
27
  Effect.gen(function* () {
28
- const mutationsCount = dbMutationLog.select<{ count: number }>(
29
- `SELECT COUNT(*) AS count FROM ${MUTATION_LOG_META_TABLE}`,
30
- )[0]!.count
28
+ const eventsCount = dbEventlog.select<{ count: number }>(`SELECT COUNT(*) AS count FROM ${EVENTLOG_META_TABLE}`)[0]!
29
+ .count
31
30
 
32
- const hashMutation = memoizeByRef((mutation: MutationDef.Any) => Schema.hash(mutation.schema))
31
+ const hashEvent = memoizeByRef((event: EventDef.AnyWithoutFn) => Schema.hash(event.schema))
33
32
 
34
- const processMutation = (row: MutationLogMetaRow) =>
33
+ const processEvent = (row: EventlogMetaRow) =>
35
34
  Effect.gen(function* () {
36
- const mutationDef = getMutationDef(schema, row.mutation)
35
+ const eventDef = getEventDef(schema, row.name)
37
36
 
38
- if (migrationOptions.excludeMutations?.has(row.mutation) === true) return
37
+ if (migrationOptions.excludeEvents?.has(row.name) === true) return
39
38
 
40
- if (hashMutation(mutationDef) !== row.schemaHash) {
41
- yield* Effect.logWarning(
42
- `Schema hash mismatch for mutation ${row.mutation}. Trying to apply mutation anyway.`,
43
- )
39
+ if (hashEvent(eventDef.eventDef) !== row.schemaHash) {
40
+ yield* Effect.logWarning(`Schema hash mismatch for mutation ${row.name}. Trying to apply mutation anyway.`)
44
41
  }
45
42
 
46
43
  const args = JSON.parse(row.argsJson)
47
44
 
48
45
  // Checking whether the schema has changed in an incompatible way
49
- yield* Schema.decodeUnknown(mutationDef.schema)(args).pipe(
46
+ yield* Schema.decodeUnknown(eventDef.eventDef.schema)(args).pipe(
50
47
  Effect.mapError((cause) =>
51
48
  UnexpectedError.make({
52
49
  cause,
53
50
  note: `\
54
- There was an error during rehydrating from the mutation log while decoding
55
- the persisted mutation event args for mutation "${row.mutation}".
51
+ There was an error during rehydrating from the eventlog while decoding
52
+ the persisted mutation event args for mutation "${row.name}".
56
53
  This likely means the schema has changed in an incompatible way.
57
54
  `,
58
55
  }),
59
56
  ),
60
57
  )
61
58
 
62
- const mutationEventEncoded = MutationEvent.EncodedWithMeta.make({
59
+ const eventEncoded = LiveStoreEvent.EncodedWithMeta.make({
63
60
  id: { global: row.idGlobal, client: row.idClient },
64
61
  parentId: { global: row.parentIdGlobal, client: row.parentIdClient },
65
- mutation: row.mutation,
62
+ name: row.name,
66
63
  args,
67
64
  clientId: row.clientId,
68
65
  sessionId: row.sessionId,
69
66
  })
70
67
 
71
- yield* applyMutation(mutationEventEncoded, { skipMutationLog: true })
72
- }).pipe(Effect.withSpan(`@livestore/common:rehydrateFromMutationLog:processMutation`))
68
+ yield* applyEvent(eventEncoded, { skipEventlog: true })
69
+ }).pipe(Effect.withSpan(`@livestore/common:rehydrateFromEventlog:processEvent`))
73
70
 
74
71
  const CHUNK_SIZE = 100
75
72
 
76
- const stmt = dbMutationLog.prepare(sql`\
77
- SELECT * FROM ${MUTATION_LOG_META_TABLE}
73
+ const stmt = dbEventlog.prepare(sql`\
74
+ SELECT * FROM ${EVENTLOG_META_TABLE}
78
75
  WHERE idGlobal > $idGlobal OR (idGlobal = $idGlobal AND idClient > $idClient)
79
76
  ORDER BY idGlobal ASC, idClient ASC
80
77
  LIMIT ${CHUNK_SIZE}
81
78
  `)
82
79
 
83
- let processedMutations = 0
80
+ let processedEvents = 0
84
81
 
85
- yield* Stream.unfoldChunk<Chunk.Chunk<MutationLogMetaRow> | { _tag: 'Initial ' }, MutationLogMetaRow>(
82
+ yield* Stream.unfoldChunk<Chunk.Chunk<EventlogMetaRow> | { _tag: 'Initial ' }, EventlogMetaRow>(
86
83
  { _tag: 'Initial ' },
87
84
  (item) => {
88
85
  // End stream if no more rows
@@ -95,7 +92,7 @@ LIMIT ${CHUNK_SIZE}
95
92
  )
96
93
  : EventId.ROOT
97
94
  const nextItem = Chunk.fromIterable(
98
- stmt.select<MutationLogMetaRow>({
95
+ stmt.select<EventlogMetaRow>({
99
96
  $idGlobal: lastId?.global,
100
97
  $idClient: lastId?.client,
101
98
  } as any as PreparedBindValues),
@@ -107,15 +104,15 @@ LIMIT ${CHUNK_SIZE}
107
104
  Stream.bufferChunks({ capacity: 2 }),
108
105
  Stream.tap((row) =>
109
106
  Effect.gen(function* () {
110
- yield* processMutation(row)
107
+ yield* processEvent(row)
111
108
 
112
- processedMutations++
113
- yield* onProgress({ done: processedMutations, total: mutationsCount })
109
+ processedEvents++
110
+ yield* onProgress({ done: processedEvents, total: eventsCount })
114
111
  }),
115
112
  ),
116
113
  Stream.runDrain,
117
114
  )
118
115
  }).pipe(
119
- Effect.withPerformanceMeasure('@livestore/common:rehydrateFromMutationLog'),
120
- Effect.withSpan('@livestore/common:rehydrateFromMutationLog'),
116
+ Effect.withPerformanceMeasure('@livestore/common:rehydrateFromEventlog'),
117
+ Effect.withSpan('@livestore/common:rehydrateFromEventlog'),
121
118
  )
@@ -0,0 +1,216 @@
1
+ import type { SingleOrReadonlyArray } from '@livestore/utils'
2
+ import { shouldNeverHappen } from '@livestore/utils'
3
+ import { Schema } from '@livestore/utils/effect'
4
+
5
+ import type { QueryBuilder } from '../query-builder/mod.js'
6
+ import type { BindValues } from '../sql-queries/sql-queries.js'
7
+
8
+ export type EventDefMap = {
9
+ map: Map<string | 'livestore.RawSql', EventDef.Any>
10
+ }
11
+ export type EventDefRecord = {
12
+ 'livestore.RawSql': RawSqlEvent
13
+ [name: string]: EventDef.Any
14
+ }
15
+
16
+ export type EventDef<TName extends string, TType, TEncoded = TType, TDerived extends boolean = false> = {
17
+ name: TName
18
+ schema: Schema.Schema<TType, TEncoded>
19
+ options: {
20
+ /**
21
+ * When set to true, the mutation won't be synced across clients but
22
+ */
23
+ clientOnly: boolean
24
+ /** Warning: This feature is not fully implemented yet */
25
+ facts: FactsCallback<TType> | undefined
26
+ derived: TDerived
27
+ }
28
+
29
+ /** Helper function to construct a partial mutation event */
30
+ (args: TType): {
31
+ name: TName
32
+ args: TType
33
+ }
34
+
35
+ readonly Event: {
36
+ name: TName
37
+ args: TType
38
+ }
39
+ }
40
+
41
+ export type FactsCallback<TTo> = (
42
+ args: TTo,
43
+ currentFacts: EventDefFacts,
44
+ ) => {
45
+ modify: {
46
+ set: Iterable<EventDefFactInput>
47
+ unset: Iterable<EventDefFactInput>
48
+ }
49
+ require: Iterable<EventDefFactInput>
50
+ }
51
+
52
+ export namespace EventDef {
53
+ export type Any = EventDef<string, any, any, boolean>
54
+
55
+ export type AnyWithoutFn = Pick<Any, 'name' | 'schema' | 'options'>
56
+ }
57
+
58
+ export type EventDefKey = string
59
+ export type EventDefFact = string
60
+ export type EventDefFacts = ReadonlyMap<string, any>
61
+
62
+ export type EventDefFactsGroup = {
63
+ modifySet: EventDefFacts
64
+ modifyUnset: EventDefFacts
65
+
66
+ /**
67
+ * Events on independent "dependency" branches are commutative which can facilitate more prioritized syncing
68
+ */
69
+ depRequire: EventDefFacts
70
+ depRead: EventDefFacts
71
+ }
72
+
73
+ export type EventDefFactsSnapshot = Map<string, any>
74
+
75
+ export type EventDefFactInput = string | readonly [string, any]
76
+
77
+ export const defineFacts = <
78
+ TRecord extends Record<string, EventDefFactInput | ((...args: any[]) => EventDefFactInput)>,
79
+ >(
80
+ record: TRecord,
81
+ ): TRecord => record
82
+
83
+ export type DefineEventOptions<TTo, TDerived extends boolean = false> = {
84
+ // TODO actually implement this
85
+ // onError?: (error: any) => void
86
+ /** Warning: This feature is not fully implemented yet */
87
+ facts?: (
88
+ args: TTo,
89
+ currentFacts: EventDefFacts,
90
+ ) => {
91
+ modify?: {
92
+ set?: Iterable<EventDefFactInput>
93
+ unset?: Iterable<EventDefFactInput>
94
+ }
95
+ /**
96
+ * Two purposes: constrain history and constrain compaction
97
+ */
98
+ require?: Iterable<EventDefFactInput>
99
+ }
100
+ /**
101
+ * When set to true, the event won't be synced over the network
102
+ */
103
+ clientOnly?: boolean
104
+ derived?: TDerived
105
+ }
106
+
107
+ export const defineEvent = <TName extends string, TType, TEncoded = TType, TDerived extends boolean = false>(
108
+ args: {
109
+ name: TName
110
+ schema: Schema.Schema<TType, TEncoded>
111
+ } & DefineEventOptions<TType, TDerived>,
112
+ ): EventDef<TName, TType, TEncoded, TDerived> => {
113
+ const { name, schema, ...options } = args
114
+
115
+ const makePartialEvent = (args: TType) => {
116
+ const res = Schema.validateEither(schema)(args)
117
+ if (res._tag === 'Left') {
118
+ shouldNeverHappen(`Invalid event args for event '${name}':`, res.left.message, '\n')
119
+ }
120
+ return { name: name, args }
121
+ }
122
+
123
+ Object.defineProperty(makePartialEvent, 'name', { value: name })
124
+ Object.defineProperty(makePartialEvent, 'schema', { value: schema })
125
+ Object.defineProperty(makePartialEvent, 'options', {
126
+ value: {
127
+ clientOnly: options?.clientOnly ?? false,
128
+ facts: options?.facts
129
+ ? (args, currentFacts) => {
130
+ const res = options.facts!(args, currentFacts)
131
+ return {
132
+ modify: {
133
+ set: res.modify?.set ? new Set(res.modify.set) : new Set(),
134
+ unset: res.modify?.unset ? new Set(res.modify.unset) : new Set(),
135
+ },
136
+ require: res.require ? new Set(res.require) : new Set(),
137
+ }
138
+ }
139
+ : undefined,
140
+ derived: options?.derived ?? false,
141
+ } satisfies EventDef.Any['options'],
142
+ })
143
+
144
+ return makePartialEvent as EventDef<TName, TType, TEncoded, TDerived>
145
+ }
146
+
147
+ export const synced = <TName extends string, TType, TEncoded = TType>(
148
+ args: {
149
+ name: TName
150
+ schema: Schema.Schema<TType, TEncoded>
151
+ } & Omit<DefineEventOptions<TType, false>, 'derived' | 'clientOnly'>,
152
+ ): EventDef<TName, TType, TEncoded> => defineEvent({ ...args, clientOnly: false })
153
+
154
+ export const clientOnly = <TName extends string, TType, TEncoded = TType>(
155
+ args: {
156
+ name: TName
157
+ schema: Schema.Schema<TType, TEncoded>
158
+ } & Omit<DefineEventOptions<TType, false>, 'derived' | 'clientOnly'>,
159
+ ): EventDef<TName, TType, TEncoded> => defineEvent({ ...args, clientOnly: true })
160
+
161
+ export type MaterializerResult =
162
+ | {
163
+ sql: string
164
+ bindValues: BindValues
165
+ writeTables?: ReadonlySet<string>
166
+ }
167
+ | QueryBuilder.Any
168
+ | string
169
+
170
+ export type Materializer<TEventDef extends EventDef.AnyWithoutFn = EventDef.AnyWithoutFn> = (
171
+ event: TEventDef['schema']['Type'],
172
+ context: { currentFacts: EventDefFacts; clientOnly: boolean },
173
+ ) => SingleOrReadonlyArray<MaterializerResult>
174
+
175
+ export const defineMaterializer = <TEventDef extends EventDef.AnyWithoutFn>(
176
+ eventDef: TEventDef,
177
+ materializer: Materializer<TEventDef>,
178
+ ): Materializer<TEventDef> => {
179
+ return materializer
180
+ }
181
+
182
+ export const materializers = <TInputRecord extends Record<string, EventDef.AnyWithoutFn>>(
183
+ eventDefRecord: TInputRecord,
184
+ handlers: {
185
+ [TEventName in TInputRecord[keyof TInputRecord]['name'] as Extract<
186
+ TInputRecord[keyof TInputRecord],
187
+ { name: TEventName }
188
+ >['options']['derived'] extends true
189
+ ? never
190
+ : TEventName]: Materializer<Extract<TInputRecord[keyof TInputRecord], { name: TEventName }>>
191
+ // [K in TInputRecord[keyof TInputRecord]['name']]: Materializer<
192
+ // Extract<TInputRecord[keyof TInputRecord], { name: K }>
193
+ // >
194
+ },
195
+ ) => {
196
+ return handlers
197
+ }
198
+
199
+ export const rawSqlEvent = defineEvent({
200
+ name: 'livestore.RawSql',
201
+ schema: Schema.Struct({
202
+ sql: Schema.String,
203
+ bindValues: Schema.optional(Schema.Record({ key: Schema.String, value: Schema.Any })),
204
+ writeTables: Schema.optional(Schema.ReadonlySet(Schema.String)),
205
+ }),
206
+ clientOnly: true,
207
+ derived: true,
208
+ })
209
+
210
+ export const rawSqlMaterializer = defineMaterializer(rawSqlEvent, ({ sql, bindValues, writeTables }) => ({
211
+ sql,
212
+ bindValues: bindValues ?? {},
213
+ writeTables,
214
+ }))
215
+
216
+ export type RawSqlEvent = typeof rawSqlEvent
@@ -14,20 +14,28 @@ export const clientDefault = 0 as any as ClientEventId
14
14
  * LiveStore event id value consisting of a globally unique event sequence number
15
15
  * and a client sequence number.
16
16
  *
17
- * The client sequence number is only used for clientOnly mutations and starts from 0 for each global sequence number.
17
+ * The client sequence number is only used for clientOnly events and starts from 0 for each global sequence number.
18
18
  */
19
19
  export type EventId = { global: GlobalEventId; client: ClientEventId }
20
20
 
21
21
  // export const EventSequenceNumber = Schema.Struct({})
22
22
  // export const EventNumber = Schema.Struct({})
23
+ // export const ClientEventNumber = Schema.Struct({})
24
+ // export const GlobalEventNumber = Schema.Struct({})
23
25
 
24
26
  /**
25
27
  * NOTE: Client mutation events with a non-0 client id, won't be synced to the sync backend.
26
28
  */
27
29
  export const EventId = Schema.Struct({
28
30
  global: GlobalEventId,
29
- /** Only increments for clientOnly mutations */
31
+ /** Only increments for clientOnly events */
30
32
  client: ClientEventId,
33
+
34
+ // TODO also provide a way to see "confirmation level" of event (e.g. confirmed by leader/sync backend)
35
+
36
+ // TODO: actually add this field
37
+ // Client only
38
+ // generation: Schema.Number.pipe(Schema.optional),
31
39
  }).annotations({ title: 'LiveStore.EventId' })
32
40
 
33
41
  /**
@@ -60,7 +68,7 @@ export const isEqual = (a: EventId, b: EventId) => a.global === b.global && a.cl
60
68
 
61
69
  export type EventIdPair = { id: EventId; parentId: EventId }
62
70
 
63
- export const ROOT = { global: -1 as any as GlobalEventId, client: clientDefault } satisfies EventId
71
+ export const ROOT = { global: 0 as any as GlobalEventId, client: clientDefault } satisfies EventId
64
72
 
65
73
  export const isGreaterThan = (a: EventId, b: EventId) => {
66
74
  return a.global > b.global || (a.global === b.global && a.client > b.client)
@@ -70,6 +78,17 @@ export const isGreaterThanOrEqual = (a: EventId, b: EventId) => {
70
78
  return a.global > b.global || (a.global === b.global && a.client >= b.client)
71
79
  }
72
80
 
81
+ export const max = (a: EventId, b: EventId) => {
82
+ return a.global > b.global || (a.global === b.global && a.client > b.client) ? a : b
83
+ }
84
+
85
+ export const diff = (a: EventId, b: EventId) => {
86
+ return {
87
+ global: a.global - b.global,
88
+ client: a.client - b.client,
89
+ }
90
+ }
91
+
73
92
  export const make = (id: EventId | typeof EventId.Encoded): EventId => {
74
93
  return Schema.is(EventId)(id) ? id : Schema.decodeSync(EventId)(id)
75
94
  }
@@ -81,7 +100,7 @@ export const nextPair = (id: EventId, isLocal: boolean): EventIdPair => {
81
100
 
82
101
  return {
83
102
  id: { global: (id.global + 1) as any as GlobalEventId, client: clientDefault },
84
- // NOTE we always point to `client: 0` for non-clientOnly mutations
103
+ // NOTE we always point to `client: 0` for non-clientOnly events
85
104
  parentId: { global: id.global, client: clientDefault },
86
105
  }
87
106
  }