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

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 (328) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/__tests__/fixture.d.ts +21 -21
  3. package/dist/adapter-types.d.ts +97 -53
  4. package/dist/adapter-types.d.ts.map +1 -1
  5. package/dist/adapter-types.js +17 -0
  6. package/dist/adapter-types.js.map +1 -1
  7. package/dist/bounded-collections.d.ts +1 -1
  8. package/dist/bounded-collections.d.ts.map +1 -1
  9. package/dist/debug-info.d.ts +1 -1
  10. package/dist/debug-info.d.ts.map +1 -1
  11. package/dist/derived-mutations.d.ts +5 -5
  12. package/dist/derived-mutations.d.ts.map +1 -1
  13. package/dist/derived-mutations.js +3 -3
  14. package/dist/derived-mutations.js.map +1 -1
  15. package/dist/derived-mutations.test.js.map +1 -1
  16. package/dist/devtools/devtools-messages-client-session.d.ts +389 -0
  17. package/dist/devtools/devtools-messages-client-session.d.ts.map +1 -0
  18. package/dist/devtools/devtools-messages-client-session.js +96 -0
  19. package/dist/devtools/devtools-messages-client-session.js.map +1 -0
  20. package/dist/devtools/devtools-messages-common.d.ts +61 -0
  21. package/dist/devtools/devtools-messages-common.d.ts.map +1 -0
  22. package/dist/devtools/devtools-messages-common.js +54 -0
  23. package/dist/devtools/devtools-messages-common.js.map +1 -0
  24. package/dist/devtools/devtools-messages-leader.d.ts +393 -0
  25. package/dist/devtools/devtools-messages-leader.d.ts.map +1 -0
  26. package/dist/devtools/devtools-messages-leader.js +148 -0
  27. package/dist/devtools/devtools-messages-leader.js.map +1 -0
  28. package/dist/devtools/devtools-messages.d.ts +3 -592
  29. package/dist/devtools/devtools-messages.d.ts.map +1 -1
  30. package/dist/devtools/devtools-messages.js +3 -171
  31. package/dist/devtools/devtools-messages.js.map +1 -1
  32. package/dist/devtools/devtools-sessioninfo.d.ts +28 -0
  33. package/dist/devtools/devtools-sessioninfo.d.ts.map +1 -0
  34. package/dist/devtools/devtools-sessioninfo.js +34 -0
  35. package/dist/devtools/devtools-sessioninfo.js.map +1 -0
  36. package/dist/devtools/mod.d.ts +39 -0
  37. package/dist/devtools/mod.d.ts.map +1 -0
  38. package/dist/devtools/mod.js +27 -0
  39. package/dist/devtools/mod.js.map +1 -0
  40. package/dist/index.d.ts +2 -6
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.js +2 -2
  43. package/dist/index.js.map +1 -1
  44. package/dist/init-singleton-tables.d.ts +2 -2
  45. package/dist/init-singleton-tables.d.ts.map +1 -1
  46. package/dist/init-singleton-tables.js.map +1 -1
  47. package/dist/leader-thread/LeaderSyncProcessor.d.ts +39 -0
  48. package/dist/leader-thread/LeaderSyncProcessor.d.ts.map +1 -0
  49. package/dist/leader-thread/LeaderSyncProcessor.js +527 -0
  50. package/dist/leader-thread/LeaderSyncProcessor.js.map +1 -0
  51. package/dist/leader-thread/apply-mutation.d.ts +5 -2
  52. package/dist/leader-thread/apply-mutation.d.ts.map +1 -1
  53. package/dist/leader-thread/apply-mutation.js +55 -35
  54. package/dist/leader-thread/apply-mutation.js.map +1 -1
  55. package/dist/leader-thread/connection.d.ts +34 -6
  56. package/dist/leader-thread/connection.d.ts.map +1 -1
  57. package/dist/leader-thread/connection.js +22 -7
  58. package/dist/leader-thread/connection.js.map +1 -1
  59. package/dist/leader-thread/leader-worker-devtools.d.ts +1 -1
  60. package/dist/leader-thread/leader-worker-devtools.d.ts.map +1 -1
  61. package/dist/leader-thread/leader-worker-devtools.js +147 -124
  62. package/dist/leader-thread/leader-worker-devtools.js.map +1 -1
  63. package/dist/leader-thread/make-leader-thread-layer.d.ts +12 -11
  64. package/dist/leader-thread/make-leader-thread-layer.d.ts.map +1 -1
  65. package/dist/leader-thread/make-leader-thread-layer.js +55 -18
  66. package/dist/leader-thread/make-leader-thread-layer.js.map +1 -1
  67. package/dist/leader-thread/mutationlog.d.ts +6 -19
  68. package/dist/leader-thread/mutationlog.d.ts.map +1 -1
  69. package/dist/leader-thread/mutationlog.js +12 -9
  70. package/dist/leader-thread/mutationlog.js.map +1 -1
  71. package/dist/leader-thread/pull-queue-set.d.ts +3 -3
  72. package/dist/leader-thread/pull-queue-set.d.ts.map +1 -1
  73. package/dist/leader-thread/pull-queue-set.js +9 -0
  74. package/dist/leader-thread/pull-queue-set.js.map +1 -1
  75. package/dist/leader-thread/recreate-db.d.ts +4 -2
  76. package/dist/leader-thread/recreate-db.d.ts.map +1 -1
  77. package/dist/leader-thread/recreate-db.js +32 -21
  78. package/dist/leader-thread/recreate-db.js.map +1 -1
  79. package/dist/leader-thread/shutdown-channel.d.ts +2 -5
  80. package/dist/leader-thread/shutdown-channel.d.ts.map +1 -1
  81. package/dist/leader-thread/shutdown-channel.js +2 -4
  82. package/dist/leader-thread/shutdown-channel.js.map +1 -1
  83. package/dist/leader-thread/types.d.ts +58 -26
  84. package/dist/leader-thread/types.d.ts.map +1 -1
  85. package/dist/leader-thread/types.js +1 -3
  86. package/dist/leader-thread/types.js.map +1 -1
  87. package/dist/mutation.d.ts +9 -2
  88. package/dist/mutation.d.ts.map +1 -1
  89. package/dist/mutation.js +5 -5
  90. package/dist/mutation.js.map +1 -1
  91. package/dist/otel.d.ts +2 -0
  92. package/dist/otel.d.ts.map +1 -1
  93. package/dist/otel.js +5 -0
  94. package/dist/otel.js.map +1 -1
  95. package/dist/query-builder/api.d.ts +3 -3
  96. package/dist/query-builder/api.d.ts.map +1 -1
  97. package/dist/query-builder/impl.d.ts +4 -4
  98. package/dist/query-builder/impl.d.ts.map +1 -1
  99. package/dist/query-builder/impl.js.map +1 -1
  100. package/dist/query-builder/impl.test.js +16 -1
  101. package/dist/query-builder/impl.test.js.map +1 -1
  102. package/dist/query-info.d.ts +3 -3
  103. package/dist/query-info.d.ts.map +1 -1
  104. package/dist/rehydrate-from-mutationlog.d.ts +5 -5
  105. package/dist/rehydrate-from-mutationlog.d.ts.map +1 -1
  106. package/dist/rehydrate-from-mutationlog.js +23 -27
  107. package/dist/rehydrate-from-mutationlog.js.map +1 -1
  108. package/dist/schema/EventId.d.ts +27 -16
  109. package/dist/schema/EventId.d.ts.map +1 -1
  110. package/dist/schema/EventId.js +36 -11
  111. package/dist/schema/EventId.js.map +1 -1
  112. package/dist/schema/EventId.test.d.ts +2 -0
  113. package/dist/schema/EventId.test.d.ts.map +1 -0
  114. package/dist/schema/EventId.test.js +11 -0
  115. package/dist/schema/EventId.test.js.map +1 -0
  116. package/dist/schema/MutationEvent.d.ts +76 -82
  117. package/dist/schema/MutationEvent.d.ts.map +1 -1
  118. package/dist/schema/MutationEvent.js +53 -20
  119. package/dist/schema/MutationEvent.js.map +1 -1
  120. package/dist/schema/db-schema/ast/sqlite.d.ts +69 -0
  121. package/dist/schema/db-schema/ast/sqlite.d.ts.map +1 -0
  122. package/dist/schema/db-schema/ast/sqlite.js +71 -0
  123. package/dist/schema/db-schema/ast/sqlite.js.map +1 -0
  124. package/dist/schema/db-schema/ast/validate.d.ts +3 -0
  125. package/dist/schema/db-schema/ast/validate.d.ts.map +1 -0
  126. package/dist/schema/db-schema/ast/validate.js +12 -0
  127. package/dist/schema/db-schema/ast/validate.js.map +1 -0
  128. package/dist/schema/db-schema/dsl/field-defs.d.ts +90 -0
  129. package/dist/schema/db-schema/dsl/field-defs.d.ts.map +1 -0
  130. package/dist/schema/db-schema/dsl/field-defs.js +87 -0
  131. package/dist/schema/db-schema/dsl/field-defs.js.map +1 -0
  132. package/dist/schema/db-schema/dsl/field-defs.test.d.ts +2 -0
  133. package/dist/schema/db-schema/dsl/field-defs.test.d.ts.map +1 -0
  134. package/dist/schema/db-schema/dsl/field-defs.test.js +29 -0
  135. package/dist/schema/db-schema/dsl/field-defs.test.js.map +1 -0
  136. package/dist/schema/db-schema/dsl/mod.d.ts +88 -0
  137. package/dist/schema/db-schema/dsl/mod.d.ts.map +1 -0
  138. package/dist/schema/db-schema/dsl/mod.js +35 -0
  139. package/dist/schema/db-schema/dsl/mod.js.map +1 -0
  140. package/dist/schema/db-schema/hash.d.ts +2 -0
  141. package/dist/schema/db-schema/hash.d.ts.map +1 -0
  142. package/dist/schema/db-schema/hash.js +14 -0
  143. package/dist/schema/db-schema/hash.js.map +1 -0
  144. package/dist/schema/db-schema/mod.d.ts +3 -0
  145. package/dist/schema/db-schema/mod.d.ts.map +1 -0
  146. package/dist/schema/db-schema/mod.js +3 -0
  147. package/dist/schema/db-schema/mod.js.map +1 -0
  148. package/dist/schema/mod.d.ts +1 -0
  149. package/dist/schema/mod.d.ts.map +1 -1
  150. package/dist/schema/mod.js +1 -0
  151. package/dist/schema/mod.js.map +1 -1
  152. package/dist/schema/mutations.d.ts +8 -9
  153. package/dist/schema/mutations.d.ts.map +1 -1
  154. package/dist/schema/mutations.js +2 -2
  155. package/dist/schema/mutations.js.map +1 -1
  156. package/dist/schema/schema-helpers.d.ts.map +1 -1
  157. package/dist/schema/schema-helpers.js +1 -1
  158. package/dist/schema/schema-helpers.js.map +1 -1
  159. package/dist/schema/schema.d.ts +5 -2
  160. package/dist/schema/schema.d.ts.map +1 -1
  161. package/dist/schema/schema.js +20 -9
  162. package/dist/schema/schema.js.map +1 -1
  163. package/dist/schema/system-tables.d.ts +65 -47
  164. package/dist/schema/system-tables.d.ts.map +1 -1
  165. package/dist/schema/system-tables.js +24 -13
  166. package/dist/schema/system-tables.js.map +1 -1
  167. package/dist/schema/table-def.d.ts +18 -24
  168. package/dist/schema/table-def.d.ts.map +1 -1
  169. package/dist/schema/table-def.js +3 -4
  170. package/dist/schema/table-def.js.map +1 -1
  171. package/dist/schema-management/common.d.ts +3 -3
  172. package/dist/schema-management/common.d.ts.map +1 -1
  173. package/dist/schema-management/common.js.map +1 -1
  174. package/dist/schema-management/migrations.d.ts +6 -6
  175. package/dist/schema-management/migrations.d.ts.map +1 -1
  176. package/dist/schema-management/migrations.js +13 -8
  177. package/dist/schema-management/migrations.js.map +1 -1
  178. package/dist/schema-management/validate-mutation-defs.d.ts.map +1 -1
  179. package/dist/schema-management/validate-mutation-defs.js +2 -2
  180. package/dist/schema-management/validate-mutation-defs.js.map +1 -1
  181. package/dist/sql-queries/misc.d.ts.map +1 -1
  182. package/dist/sql-queries/sql-queries.d.ts +1 -1
  183. package/dist/sql-queries/sql-queries.d.ts.map +1 -1
  184. package/dist/sql-queries/sql-queries.js.map +1 -1
  185. package/dist/sql-queries/sql-query-builder.d.ts +1 -1
  186. package/dist/sql-queries/sql-query-builder.d.ts.map +1 -1
  187. package/dist/sql-queries/sql-query-builder.js.map +1 -1
  188. package/dist/sql-queries/types.d.ts +2 -1
  189. package/dist/sql-queries/types.d.ts.map +1 -1
  190. package/dist/sql-queries/types.js.map +1 -1
  191. package/dist/sync/{client-session-sync-processor.d.ts → ClientSessionSyncProcessor.d.ts} +25 -14
  192. package/dist/sync/ClientSessionSyncProcessor.d.ts.map +1 -0
  193. package/dist/sync/ClientSessionSyncProcessor.js +199 -0
  194. package/dist/sync/ClientSessionSyncProcessor.js.map +1 -0
  195. package/dist/sync/index.d.ts +1 -1
  196. package/dist/sync/index.d.ts.map +1 -1
  197. package/dist/sync/index.js +1 -1
  198. package/dist/sync/index.js.map +1 -1
  199. package/dist/sync/next/compact-events.d.ts.map +1 -1
  200. package/dist/sync/next/facts.d.ts.map +1 -1
  201. package/dist/sync/next/facts.js +1 -1
  202. package/dist/sync/next/facts.js.map +1 -1
  203. package/dist/sync/next/history-dag-common.d.ts +3 -4
  204. package/dist/sync/next/history-dag-common.d.ts.map +1 -1
  205. package/dist/sync/next/history-dag-common.js +3 -1
  206. package/dist/sync/next/history-dag-common.js.map +1 -1
  207. package/dist/sync/next/history-dag.d.ts.map +1 -1
  208. package/dist/sync/next/history-dag.js +1 -1
  209. package/dist/sync/next/history-dag.js.map +1 -1
  210. package/dist/sync/next/rebase-events.d.ts +6 -4
  211. package/dist/sync/next/rebase-events.d.ts.map +1 -1
  212. package/dist/sync/next/rebase-events.js +6 -3
  213. package/dist/sync/next/rebase-events.js.map +1 -1
  214. package/dist/sync/next/test/compact-events.calculator.test.js +12 -12
  215. package/dist/sync/next/test/compact-events.calculator.test.js.map +1 -1
  216. package/dist/sync/next/test/compact-events.test.js +43 -43
  217. package/dist/sync/next/test/compact-events.test.js.map +1 -1
  218. package/dist/sync/next/test/mutation-fixtures.d.ts +4 -4
  219. package/dist/sync/next/test/mutation-fixtures.d.ts.map +1 -1
  220. package/dist/sync/next/test/mutation-fixtures.js +12 -16
  221. package/dist/sync/next/test/mutation-fixtures.js.map +1 -1
  222. package/dist/sync/sync.d.ts +31 -16
  223. package/dist/sync/sync.d.ts.map +1 -1
  224. package/dist/sync/sync.js +7 -3
  225. package/dist/sync/sync.js.map +1 -1
  226. package/dist/sync/syncstate.d.ts +177 -44
  227. package/dist/sync/syncstate.d.ts.map +1 -1
  228. package/dist/sync/syncstate.js +188 -56
  229. package/dist/sync/syncstate.js.map +1 -1
  230. package/dist/sync/syncstate.test.js +162 -92
  231. package/dist/sync/syncstate.test.js.map +1 -1
  232. package/dist/sync/validate-push-payload.d.ts +2 -2
  233. package/dist/sync/validate-push-payload.d.ts.map +1 -1
  234. package/dist/sync/validate-push-payload.js +2 -2
  235. package/dist/sync/validate-push-payload.js.map +1 -1
  236. package/dist/util.d.ts +2 -2
  237. package/dist/util.d.ts.map +1 -1
  238. package/dist/version.d.ts +1 -1
  239. package/dist/version.d.ts.map +1 -1
  240. package/dist/version.js +1 -1
  241. package/dist/version.js.map +1 -1
  242. package/package.json +6 -6
  243. package/src/adapter-types.ts +80 -56
  244. package/src/derived-mutations.test.ts +1 -1
  245. package/src/derived-mutations.ts +13 -9
  246. package/src/devtools/devtools-messages-client-session.ts +141 -0
  247. package/src/devtools/devtools-messages-common.ts +106 -0
  248. package/src/devtools/devtools-messages-leader.ts +192 -0
  249. package/src/devtools/devtools-messages.ts +3 -243
  250. package/src/devtools/devtools-sessioninfo.ts +99 -0
  251. package/src/devtools/mod.ts +36 -0
  252. package/src/index.ts +2 -8
  253. package/src/init-singleton-tables.ts +2 -2
  254. package/src/leader-thread/LeaderSyncProcessor.ts +833 -0
  255. package/src/leader-thread/apply-mutation.ts +87 -43
  256. package/src/leader-thread/connection.ts +54 -9
  257. package/src/leader-thread/leader-worker-devtools.ts +199 -174
  258. package/src/leader-thread/make-leader-thread-layer.ts +89 -35
  259. package/src/leader-thread/mutationlog.ts +20 -14
  260. package/src/leader-thread/pull-queue-set.ts +10 -1
  261. package/src/leader-thread/recreate-db.ts +38 -25
  262. package/src/leader-thread/shutdown-channel.ts +2 -4
  263. package/src/leader-thread/types.ts +68 -34
  264. package/src/mutation.ts +17 -7
  265. package/src/otel.ts +8 -0
  266. package/src/query-builder/api.ts +4 -4
  267. package/src/query-builder/impl.test.ts +22 -1
  268. package/src/query-builder/impl.ts +2 -2
  269. package/src/query-info.ts +3 -3
  270. package/src/rehydrate-from-mutationlog.ts +28 -34
  271. package/src/schema/EventId.test.ts +12 -0
  272. package/src/schema/EventId.ts +49 -15
  273. package/src/schema/MutationEvent.ts +78 -31
  274. package/src/schema/db-schema/ast/sqlite.ts +142 -0
  275. package/src/schema/db-schema/ast/validate.ts +13 -0
  276. package/src/schema/db-schema/dsl/__snapshots__/field-defs.test.ts.snap +206 -0
  277. package/src/schema/db-schema/dsl/field-defs.test.ts +35 -0
  278. package/src/schema/db-schema/dsl/field-defs.ts +242 -0
  279. package/src/schema/db-schema/dsl/mod.ts +195 -0
  280. package/src/schema/db-schema/hash.ts +14 -0
  281. package/src/schema/db-schema/mod.ts +2 -0
  282. package/src/schema/mod.ts +1 -0
  283. package/src/schema/mutations.ts +10 -20
  284. package/src/schema/schema-helpers.ts +1 -1
  285. package/src/schema/schema.ts +22 -10
  286. package/src/schema/system-tables.ts +24 -13
  287. package/src/schema/table-def.ts +17 -17
  288. package/src/schema-management/common.ts +3 -3
  289. package/src/schema-management/migrations.ts +19 -15
  290. package/src/schema-management/validate-mutation-defs.ts +2 -2
  291. package/src/sql-queries/sql-queries.ts +1 -1
  292. package/src/sql-queries/sql-query-builder.ts +1 -2
  293. package/src/sql-queries/types.ts +3 -1
  294. package/src/sync/ClientSessionSyncProcessor.ts +313 -0
  295. package/src/sync/index.ts +1 -1
  296. package/src/sync/next/facts.ts +1 -1
  297. package/src/sync/next/history-dag-common.ts +5 -1
  298. package/src/sync/next/history-dag.ts +1 -1
  299. package/src/sync/next/rebase-events.ts +13 -7
  300. package/src/sync/next/test/compact-events.calculator.test.ts +12 -12
  301. package/src/sync/next/test/compact-events.test.ts +43 -43
  302. package/src/sync/next/test/mutation-fixtures.ts +16 -19
  303. package/src/sync/sync.ts +26 -10
  304. package/src/sync/syncstate.test.ts +178 -98
  305. package/src/sync/syncstate.ts +170 -83
  306. package/src/sync/validate-push-payload.ts +7 -4
  307. package/src/version.ts +1 -1
  308. package/tmp/pack.tgz +0 -0
  309. package/tsconfig.json +1 -1
  310. package/dist/devtools/devtools-bridge.d.ts +0 -12
  311. package/dist/devtools/devtools-bridge.d.ts.map +0 -1
  312. package/dist/devtools/devtools-bridge.js +0 -2
  313. package/dist/devtools/devtools-bridge.js.map +0 -1
  314. package/dist/devtools/index.d.ts +0 -42
  315. package/dist/devtools/index.d.ts.map +0 -1
  316. package/dist/devtools/index.js +0 -48
  317. package/dist/devtools/index.js.map +0 -1
  318. package/dist/leader-thread/leader-sync-processor.d.ts +0 -47
  319. package/dist/leader-thread/leader-sync-processor.d.ts.map +0 -1
  320. package/dist/leader-thread/leader-sync-processor.js +0 -422
  321. package/dist/leader-thread/leader-sync-processor.js.map +0 -1
  322. package/dist/sync/client-session-sync-processor.d.ts.map +0 -1
  323. package/dist/sync/client-session-sync-processor.js +0 -131
  324. package/dist/sync/client-session-sync-processor.js.map +0 -1
  325. package/src/devtools/devtools-bridge.ts +0 -13
  326. package/src/devtools/index.ts +0 -48
  327. package/src/leader-thread/leader-sync-processor.ts +0 -666
  328. package/src/sync/client-session-sync-processor.ts +0 -207
@@ -1,8 +1,8 @@
1
- import { SqliteAst, SqliteDsl } from '@livestore/db-schema'
2
1
  import { memoizeByStringifyArgs } from '@livestore/utils'
3
2
  import { Effect, Schema as EffectSchema } from '@livestore/utils/effect'
4
3
 
5
- import type { SynchronousDatabase } from '../adapter-types.js'
4
+ import type { MigrationsReport, MigrationsReportEntry, SqliteDb, UnexpectedError } from '../adapter-types.js'
5
+ import { SqliteAst, SqliteDsl } from '../schema/db-schema/mod.js'
6
6
  import type { LiveStoreSchema } from '../schema/mod.js'
7
7
  import type { SchemaMetaRow, SchemaMutationsMetaRow } from '../schema/system-tables.js'
8
8
  import {
@@ -19,7 +19,7 @@ import { validateSchema } from './validate-mutation-defs.js'
19
19
 
20
20
  const getMemoizedTimestamp = memoizeByStringifyArgs(() => new Date().toISOString())
21
21
 
22
- export const makeSchemaManager = (db: SynchronousDatabase): Effect.Effect<SchemaManager> =>
22
+ export const makeSchemaManager = (db: SqliteDb): Effect.Effect<SchemaManager> =>
23
23
  Effect.gen(function* () {
24
24
  yield* migrateTable({
25
25
  db,
@@ -51,10 +51,10 @@ export const migrateDb = ({
51
51
  schema,
52
52
  onProgress,
53
53
  }: {
54
- db: SynchronousDatabase
54
+ db: SqliteDb
55
55
  schema: LiveStoreSchema
56
56
  onProgress?: (opts: { done: number; total: number }) => Effect.Effect<void>
57
- }) =>
57
+ }): Effect.Effect<MigrationsReport, UnexpectedError> =>
58
58
  Effect.gen(function* () {
59
59
  yield* migrateTable({
60
60
  db,
@@ -81,6 +81,7 @@ export const migrateDb = ({
81
81
 
82
82
  const tablesToMigrate = new Set<{ tableAst: SqliteAst.Table; schemaHash: number }>()
83
83
 
84
+ const migrationsReportEntries: MigrationsReportEntry[] = []
84
85
  for (const tableDef of tableDefs) {
85
86
  const tableAst = tableDef.sqliteDef.ast
86
87
  const tableName = tableAst.name
@@ -90,9 +91,10 @@ export const migrateDb = ({
90
91
  if (schemaHash !== dbSchemaHash) {
91
92
  tablesToMigrate.add({ tableAst, schemaHash })
92
93
 
93
- console.log(
94
- `Schema hash mismatch for table '${tableName}' (DB: ${dbSchemaHash}, expected: ${schemaHash}), migrating table...`,
95
- )
94
+ migrationsReportEntries.push({
95
+ tableName,
96
+ hashes: { expected: schemaHash, actual: dbSchemaHash },
97
+ })
96
98
  }
97
99
  }
98
100
 
@@ -107,6 +109,8 @@ export const migrateDb = ({
107
109
  yield* onProgress({ done: processedTables, total: tablesCount })
108
110
  }
109
111
  }
112
+
113
+ return { migrations: migrationsReportEntries }
110
114
  })
111
115
 
112
116
  export const migrateTable = ({
@@ -116,7 +120,7 @@ export const migrateTable = ({
116
120
  behaviour,
117
121
  skipMetaTable = false,
118
122
  }: {
119
- db: SynchronousDatabase
123
+ db: SqliteDb
120
124
  tableAst: SqliteAst.Table
121
125
  schemaHash?: number
122
126
  behaviour: 'drop-and-recreate' | 'create-if-not-exists'
@@ -129,10 +133,10 @@ export const migrateTable = ({
129
133
 
130
134
  if (behaviour === 'drop-and-recreate') {
131
135
  // TODO need to possibly handle cascading deletes due to foreign keys
132
- dbExecute(db, sql`drop table if exists ${tableName}`)
133
- dbExecute(db, sql`create table if not exists ${tableName} (${columnSpec}) strict`)
136
+ dbExecute(db, sql`drop table if exists '${tableName}'`)
137
+ dbExecute(db, sql`create table if not exists '${tableName}' (${columnSpec}) strict`)
134
138
  } else if (behaviour === 'create-if-not-exists') {
135
- dbExecute(db, sql`create table if not exists ${tableName} (${columnSpec}) strict`)
139
+ dbExecute(db, sql`create table if not exists '${tableName}' (${columnSpec}) strict`)
136
140
  }
137
141
 
138
142
  for (const index of tableAst.indexes) {
@@ -162,11 +166,11 @@ export const migrateTable = ({
162
166
 
163
167
  const createIndexFromDefinition = (tableName: string, index: SqliteAst.Index) => {
164
168
  const uniqueStr = index.unique ? 'UNIQUE' : ''
165
- return sql`create ${uniqueStr} index if not exists ${index.name} on ${tableName} (${index.columns.join(', ')})`
169
+ return sql`create ${uniqueStr} index if not exists '${index.name}' on '${tableName}' (${index.columns.join(', ')})`
166
170
  }
167
171
 
168
172
  export const makeColumnSpec = (tableAst: SqliteAst.Table) => {
169
- const primaryKeys = tableAst.columns.filter((_) => _.primaryKey).map((_) => _.name)
173
+ const primaryKeys = tableAst.columns.filter((_) => _.primaryKey).map((_) => `'${_.name}'`)
170
174
  const columnDefStrs = tableAst.columns.map(toSqliteColumnSpec)
171
175
  if (primaryKeys.length > 0) {
172
176
  columnDefStrs.push(`PRIMARY KEY (${primaryKeys.join(', ')})`)
@@ -191,5 +195,5 @@ const toSqliteColumnSpec = (column: SqliteAst.Column) => {
191
195
  return `default ${encodedDefaultValue}`
192
196
  })()
193
197
 
194
- return `${column.name} ${columnTypeStr} ${nullableStr} ${defaultValueStr}`
198
+ return `'${column.name}' ${columnTypeStr} ${nullableStr} ${defaultValueStr}`
195
199
  }
@@ -11,7 +11,7 @@ export const validateSchema = (schema: LiveStoreSchema, schemaManager: SchemaMan
11
11
  const registeredMutationDefInfos = schemaManager.getMutationDefInfos()
12
12
 
13
13
  const missingMutationDefs = registeredMutationDefInfos.filter(
14
- (registeredMutationDefInfo) => !schema.mutations.has(registeredMutationDefInfo.mutationName),
14
+ (registeredMutationDefInfo) => !schema.mutations.map.has(registeredMutationDefInfo.mutationName),
15
15
  )
16
16
 
17
17
  if (missingMutationDefs.length > 0) {
@@ -20,7 +20,7 @@ export const validateSchema = (schema: LiveStoreSchema, schemaManager: SchemaMan
20
20
  })
21
21
  }
22
22
 
23
- for (const [, mutationDef] of schema.mutations) {
23
+ for (const [, mutationDef] of schema.mutations.map) {
24
24
  const registeredMutationDefInfo = registeredMutationDefInfos.find(
25
25
  (info) => info.mutationName === mutationDef.name,
26
26
  )
@@ -1,7 +1,7 @@
1
- import type { SqliteDsl } from '@livestore/db-schema'
2
1
  import { shouldNeverHappen } from '@livestore/utils'
3
2
  import { pipe, ReadonlyArray, Schema, TreeFormatter } from '@livestore/utils/effect'
4
3
 
4
+ import type { SqliteDsl } from '../schema/db-schema/mod.js'
5
5
  import { sql } from '../util.js'
6
6
  import { objectEntries } from './misc.js'
7
7
  import * as ClientTypes from './types.js'
@@ -1,5 +1,4 @@
1
- import type { SqliteDsl } from '@livestore/db-schema'
2
-
1
+ import type { SqliteDsl } from '../schema/db-schema/mod.js'
3
2
  import type { BindValues } from './sql-queries.js'
4
3
  import * as SqlQueries from './sql-queries.js'
5
4
  import type * as ClientTypes from './types.js'
@@ -1,6 +1,8 @@
1
- import type { Prettify, SqliteDsl } from '@livestore/db-schema'
1
+ import type { Prettify } from '@livestore/utils'
2
2
  import type { Schema } from '@livestore/utils/effect'
3
3
 
4
+ import type { SqliteDsl } from '../schema/db-schema/mod.js'
5
+
4
6
  export type DecodedValuesForTableAll<TSchema extends SqliteDsl.DbSchema, TTableName extends keyof TSchema> = {
5
7
  [K in keyof GetColumns<TSchema, TTableName>]: Schema.Schema.Type<GetColumn<TSchema, TTableName, K>['schema']>
6
8
  }
@@ -0,0 +1,313 @@
1
+ import { LS_DEV, shouldNeverHappen, TRACE_VERBOSE } from '@livestore/utils'
2
+ import type { Runtime, Scope } from '@livestore/utils/effect'
3
+ import { BucketQueue, Effect, FiberHandle, Queue, Schema, Stream, Subscribable } from '@livestore/utils/effect'
4
+ import * as otel from '@opentelemetry/api'
5
+
6
+ import type { ClientSession, UnexpectedError } from '../adapter-types.js'
7
+ import * as EventId from '../schema/EventId.js'
8
+ import { getMutationDef, type LiveStoreSchema } from '../schema/mod.js'
9
+ import * as MutationEvent from '../schema/MutationEvent.js'
10
+ import * as SyncState from './syncstate.js'
11
+
12
+ /**
13
+ * Rebase behaviour:
14
+ * - We continously pull mutations from the leader and apply them to the local store.
15
+ * - If there was a race condition (i.e. the leader and client session have both advacned),
16
+ * we'll need to rebase the local pending mutations on top of the leader's head.
17
+ * - The goal is to never block the UI, so we'll interrupt rebasing if a new mutations is pushed by the client session.
18
+ * - We also want to avoid "backwards-jumping" in the UI, so we'll transactionally apply a read model changes during a rebase.
19
+ * - We might need to make the rebase behaviour configurable e.g. to let users manually trigger a rebase
20
+ */
21
+ export const makeClientSessionSyncProcessor = ({
22
+ schema,
23
+ clientSession,
24
+ runtime,
25
+ applyMutation,
26
+ rollback,
27
+ refreshTables,
28
+ span,
29
+ params,
30
+ confirmUnsavedChanges,
31
+ }: {
32
+ schema: LiveStoreSchema
33
+ clientSession: ClientSession
34
+ runtime: Runtime.Runtime<Scope.Scope>
35
+ applyMutation: (
36
+ mutationEventDecoded: MutationEvent.PartialAnyDecoded,
37
+ options: { otelContext: otel.Context; withChangeset: boolean },
38
+ ) => {
39
+ writeTables: Set<string>
40
+ sessionChangeset: Uint8Array | undefined
41
+ }
42
+ rollback: (changeset: Uint8Array) => void
43
+ refreshTables: (tables: Set<string>) => void
44
+ span: otel.Span
45
+ params: {
46
+ leaderPushBatchSize: number
47
+ }
48
+ /**
49
+ * Currently only used in the web adapter:
50
+ * If true, registers a beforeunload event listener to confirm unsaved changes.
51
+ */
52
+ confirmUnsavedChanges: boolean
53
+ }): ClientSessionSyncProcessor => {
54
+ const mutationEventSchema = MutationEvent.makeMutationEventSchemaMemo(schema)
55
+
56
+ const syncStateRef = {
57
+ current: new SyncState.SyncState({
58
+ localHead: clientSession.leaderThread.initialState.leaderHead,
59
+ upstreamHead: clientSession.leaderThread.initialState.leaderHead,
60
+ pending: [],
61
+ // TODO init rollbackTail from leader to be ready for backend rebasing
62
+ rollbackTail: [],
63
+ }),
64
+ }
65
+
66
+ const syncStateUpdateQueue = Queue.unbounded<SyncState.SyncState>().pipe(Effect.runSync)
67
+ const isLocalEvent = (mutationEventEncoded: MutationEvent.EncodedWithMeta) =>
68
+ getMutationDef(schema, mutationEventEncoded.mutation).options.clientOnly
69
+
70
+ /** We're queuing push requests to reduce the number of messages sent to the leader by batching them */
71
+ const leaderPushQueue = BucketQueue.make<MutationEvent.EncodedWithMeta>().pipe(Effect.runSync)
72
+
73
+ const push: ClientSessionSyncProcessor['push'] = (batch, { otelContext }) => {
74
+ // TODO validate batch
75
+
76
+ let baseEventId = syncStateRef.current.localHead
77
+ const encodedMutationEvents = batch.map((mutationEvent) => {
78
+ const mutationDef = getMutationDef(schema, mutationEvent.mutation)
79
+ const nextIdPair = EventId.nextPair(baseEventId, mutationDef.options.clientOnly)
80
+ baseEventId = nextIdPair.id
81
+ return new MutationEvent.EncodedWithMeta(
82
+ Schema.encodeUnknownSync(mutationEventSchema)({
83
+ ...mutationEvent,
84
+ ...nextIdPair,
85
+ clientId: clientSession.clientId,
86
+ sessionId: clientSession.sessionId,
87
+ }),
88
+ )
89
+ })
90
+
91
+ const updateResult = SyncState.updateSyncState({
92
+ syncState: syncStateRef.current,
93
+ payload: { _tag: 'local-push', newEvents: encodedMutationEvents },
94
+ isLocalEvent,
95
+ isEqualEvent: MutationEvent.isEqualEncoded,
96
+ })
97
+
98
+ if (updateResult._tag === 'unexpected-error') {
99
+ return shouldNeverHappen('Unexpected error in client-session-sync-processor', updateResult.cause)
100
+ }
101
+
102
+ span.addEvent('local-push', {
103
+ batchSize: encodedMutationEvents.length,
104
+ updateResult: TRACE_VERBOSE ? JSON.stringify(updateResult) : undefined,
105
+ })
106
+
107
+ if (updateResult._tag !== 'advance') {
108
+ return shouldNeverHappen(`Expected advance, got ${updateResult._tag}`)
109
+ }
110
+
111
+ syncStateRef.current = updateResult.newSyncState
112
+ syncStateUpdateQueue.offer(updateResult.newSyncState).pipe(Effect.runSync)
113
+
114
+ const writeTables = new Set<string>()
115
+ for (const mutationEvent of updateResult.newEvents) {
116
+ // TODO avoid encoding and decoding here again
117
+ const decodedMutationEvent = Schema.decodeSync(mutationEventSchema)(mutationEvent)
118
+ const res = applyMutation(decodedMutationEvent, { otelContext, withChangeset: true })
119
+ for (const table of res.writeTables) {
120
+ writeTables.add(table)
121
+ }
122
+ mutationEvent.meta.sessionChangeset = res.sessionChangeset
123
+ }
124
+
125
+ // console.debug('pushToLeader', encodedMutationEvents.length, ...encodedMutationEvents.map((_) => _.toJSON()))
126
+ BucketQueue.offerAll(leaderPushQueue, encodedMutationEvents).pipe(Effect.runSync)
127
+
128
+ return { writeTables }
129
+ }
130
+
131
+ const debugInfo = {
132
+ rebaseCount: 0,
133
+ advanceCount: 0,
134
+ rejectCount: 0,
135
+ }
136
+
137
+ const otelContext = otel.trace.setSpan(otel.context.active(), span)
138
+
139
+ const boot: ClientSessionSyncProcessor['boot'] = Effect.gen(function* () {
140
+ // eslint-disable-next-line unicorn/prefer-global-this
141
+ if (confirmUnsavedChanges && typeof window !== 'undefined' && typeof window.addEventListener === 'function') {
142
+ const onBeforeUnload = (event: BeforeUnloadEvent) => {
143
+ if (syncStateRef.current.pending.length > 0) {
144
+ // Trigger the default browser dialog
145
+ event.preventDefault()
146
+ }
147
+ }
148
+
149
+ yield* Effect.acquireRelease(
150
+ Effect.sync(() => window.addEventListener('beforeunload', onBeforeUnload)),
151
+ () => Effect.sync(() => window.removeEventListener('beforeunload', onBeforeUnload)),
152
+ )
153
+ }
154
+
155
+ const leaderPushingFiberHandle = yield* FiberHandle.make()
156
+
157
+ const backgroundLeaderPushing = Effect.gen(function* () {
158
+ const batch = yield* BucketQueue.takeBetween(leaderPushQueue, 1, params.leaderPushBatchSize)
159
+ yield* clientSession.leaderThread.mutations.push(batch).pipe(
160
+ Effect.catchTag('LeaderAheadError', () => {
161
+ debugInfo.rejectCount++
162
+ return BucketQueue.clear(leaderPushQueue)
163
+ }),
164
+ )
165
+ }).pipe(Effect.forever, Effect.interruptible, Effect.tapCauseLogPretty)
166
+
167
+ yield* FiberHandle.run(leaderPushingFiberHandle, backgroundLeaderPushing)
168
+
169
+ yield* clientSession.leaderThread.mutations.pull.pipe(
170
+ Stream.tap(({ payload, remaining }) =>
171
+ Effect.gen(function* () {
172
+ // console.log('pulled payload from leader', { payload, remaining })
173
+ if (clientSession.devtools.enabled) {
174
+ yield* clientSession.devtools.pullLatch.await
175
+ }
176
+
177
+ const updateResult = SyncState.updateSyncState({
178
+ syncState: syncStateRef.current,
179
+ payload,
180
+ isLocalEvent,
181
+ isEqualEvent: MutationEvent.isEqualEncoded,
182
+ })
183
+
184
+ if (updateResult._tag === 'unexpected-error') {
185
+ return yield* Effect.fail(updateResult.cause)
186
+ } else if (updateResult._tag === 'reject') {
187
+ return shouldNeverHappen('Unexpected reject in client-session-sync-processor', updateResult)
188
+ }
189
+
190
+ syncStateRef.current = updateResult.newSyncState
191
+ syncStateUpdateQueue.offer(updateResult.newSyncState).pipe(Effect.runSync)
192
+
193
+ if (updateResult._tag === 'rebase') {
194
+ span.addEvent('pull:rebase', {
195
+ payloadTag: payload._tag,
196
+ payload: TRACE_VERBOSE ? JSON.stringify(payload) : undefined,
197
+ newEventsCount: updateResult.newEvents.length,
198
+ rollbackCount: updateResult.eventsToRollback.length,
199
+ res: TRACE_VERBOSE ? JSON.stringify(updateResult) : undefined,
200
+ remaining,
201
+ })
202
+
203
+ debugInfo.rebaseCount++
204
+
205
+ yield* FiberHandle.clear(leaderPushingFiberHandle)
206
+
207
+ // Reset the leader push queue since we're rebasing and will push again
208
+ yield* BucketQueue.clear(leaderPushQueue)
209
+
210
+ yield* FiberHandle.run(leaderPushingFiberHandle, backgroundLeaderPushing)
211
+
212
+ if (LS_DEV) {
213
+ Effect.logDebug(
214
+ 'pull:rebase: rollback',
215
+ updateResult.eventsToRollback.length,
216
+ ...updateResult.eventsToRollback.slice(0, 10).map((_) => _.toJSON()),
217
+ ).pipe(Effect.provide(runtime), Effect.runSync)
218
+ }
219
+
220
+ for (let i = updateResult.eventsToRollback.length - 1; i >= 0; i--) {
221
+ const event = updateResult.eventsToRollback[i]!
222
+ if (event.meta.sessionChangeset) {
223
+ rollback(event.meta.sessionChangeset)
224
+ event.meta.sessionChangeset = undefined
225
+ }
226
+ }
227
+
228
+ yield* BucketQueue.offerAll(leaderPushQueue, updateResult.newSyncState.pending)
229
+ } else {
230
+ span.addEvent('pull:advance', {
231
+ payloadTag: payload._tag,
232
+ payload: TRACE_VERBOSE ? JSON.stringify(payload) : undefined,
233
+ newEventsCount: updateResult.newEvents.length,
234
+ res: TRACE_VERBOSE ? JSON.stringify(updateResult) : undefined,
235
+ remaining,
236
+ })
237
+
238
+ debugInfo.advanceCount++
239
+ }
240
+
241
+ if (updateResult.newEvents.length === 0) return
242
+
243
+ const writeTables = new Set<string>()
244
+ for (const mutationEvent of updateResult.newEvents) {
245
+ const decodedMutationEvent = Schema.decodeSync(mutationEventSchema)(mutationEvent)
246
+ const res = applyMutation(decodedMutationEvent, { otelContext, withChangeset: true })
247
+ for (const table of res.writeTables) {
248
+ writeTables.add(table)
249
+ }
250
+
251
+ mutationEvent.meta.sessionChangeset = res.sessionChangeset
252
+ }
253
+
254
+ refreshTables(writeTables)
255
+ }).pipe(
256
+ Effect.tapCauseLogPretty,
257
+ Effect.catchAllCause((cause) => Effect.sync(() => clientSession.shutdown(cause))),
258
+ ),
259
+ ),
260
+ Stream.runDrain,
261
+ Effect.forever, // NOTE Whenever the leader changes, we need to re-start the stream
262
+ Effect.withSpan('client-session-sync-processor:pull'),
263
+ Effect.tapCauseLogPretty,
264
+ Effect.forkScoped,
265
+ )
266
+ })
267
+
268
+ return {
269
+ push,
270
+ boot,
271
+ syncState: Subscribable.make({
272
+ get: Effect.gen(function* () {
273
+ const syncState = syncStateRef.current
274
+ if (syncStateRef === undefined) return shouldNeverHappen('Not initialized')
275
+ return syncState
276
+ }),
277
+ changes: Stream.fromQueue(syncStateUpdateQueue),
278
+ }),
279
+ debug: {
280
+ print: () =>
281
+ Effect.gen(function* () {
282
+ console.log('debugInfo', debugInfo)
283
+ console.log('syncState', syncStateRef.current)
284
+ const pushQueueSize = yield* BucketQueue.size(leaderPushQueue)
285
+ console.log('pushQueueSize', pushQueueSize)
286
+ const pushQueueItems = yield* BucketQueue.peekAll(leaderPushQueue)
287
+ console.log(
288
+ 'pushQueueItems',
289
+ pushQueueItems.map((_) => _.toJSON()),
290
+ )
291
+ }).pipe(Effect.provide(runtime), Effect.runSync),
292
+ debugInfo: () => debugInfo,
293
+ },
294
+ } satisfies ClientSessionSyncProcessor
295
+ }
296
+
297
+ export interface ClientSessionSyncProcessor {
298
+ push: (
299
+ batch: ReadonlyArray<MutationEvent.PartialAnyDecoded>,
300
+ options: { otelContext: otel.Context },
301
+ ) => {
302
+ writeTables: Set<string>
303
+ }
304
+ boot: Effect.Effect<void, UnexpectedError, Scope.Scope>
305
+ syncState: Subscribable.Subscribable<SyncState.SyncState>
306
+ debug: {
307
+ print: () => void
308
+ debugInfo: () => {
309
+ rebaseCount: number
310
+ advanceCount: number
311
+ }
312
+ }
313
+ }
package/src/sync/index.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  export * from './sync.js'
2
2
  export * from './validate-push-payload.js'
3
- export * from './client-session-sync-processor.js'
3
+ export * from './ClientSessionSyncProcessor.js'
@@ -231,5 +231,5 @@ export const compareEventIds = (a: EventId.EventId, b: EventId.EventId) => {
231
231
  if (a.global !== b.global) {
232
232
  return a.global - b.global
233
233
  }
234
- return a.local - b.local
234
+ return a.client - b.client
235
235
  }
@@ -20,7 +20,7 @@ export const emptyHistoryDag = (): HistoryDag =>
20
20
  })
21
21
 
22
22
  // TODO consider making `ROOT_ID` parent to itself
23
- export const rootParentId = { global: EventId.ROOT.global - 1, local: 0 } satisfies EventId.EventId
23
+ export const rootParentId = EventId.make({ global: EventId.ROOT.global - 1, client: EventId.clientDefault })
24
24
 
25
25
  export type HistoryDagNode = {
26
26
  id: EventId.EventId
@@ -30,6 +30,8 @@ export type HistoryDagNode = {
30
30
  /** Facts are being used for conflict detection and history compaction */
31
31
  factsGroup: MutationEventFactsGroup
32
32
  meta?: any
33
+ clientId: string
34
+ sessionId: string | undefined
33
35
  }
34
36
 
35
37
  export const rootEventNode: HistoryDagNode = {
@@ -39,6 +41,8 @@ export const rootEventNode: HistoryDagNode = {
39
41
  mutation: '__Root__',
40
42
  args: {},
41
43
  factsGroup: { modifySet: new Map(), modifyUnset: new Map(), depRequire: new Map(), depRead: new Map() },
44
+ clientId: 'root',
45
+ sessionId: undefined,
42
46
  }
43
47
 
44
48
  export const EMPTY_FACT_VALUE = Symbol('EMPTY_FACT_VALUE')
@@ -3,7 +3,7 @@ import { factsToString, validateFacts } from './facts.js'
3
3
  import { emptyHistoryDag, type HistoryDagNode, rootParentId } from './history-dag-common.js'
4
4
 
5
5
  export const eventIdToString = (eventId: EventId.EventId) =>
6
- eventId.local === 0 ? eventId.global.toString() : `${eventId.global}.${eventId.local}`
6
+ eventId.client === 0 ? eventId.global.toString() : `${eventId.global}.${eventId.client}`
7
7
 
8
8
  export const historyDagFromNodes = (dagNodes: HistoryDagNode[], options?: { skipFactsCheck: boolean }) => {
9
9
  if (options?.skipFactsCheck !== true) {
@@ -1,4 +1,4 @@
1
- import type * as EventId from '../../schema/EventId.js'
1
+ import * as EventId from '../../schema/EventId.js'
2
2
  import type * as MutationEvent from '../../schema/MutationEvent.js'
3
3
  import type { MutationDef, MutationEventFactsSnapshot } from '../../schema/mutations.js'
4
4
  import {
@@ -19,13 +19,13 @@ export type RebaseInput = {
19
19
  newRemoteEvents: RebaseEventWithConflict[]
20
20
  pendingLocalEvents: RebaseEventWithConflict[]
21
21
  validate: (args: {
22
- rebasedLocalEvents: MutationEvent.PartialAny[]
22
+ rebasedLocalEvents: MutationEvent.PartialAnyDecoded[]
23
23
  mutationDefs: Record<string, MutationDef.Any>
24
24
  }) => FactValidationResult
25
25
  }
26
26
 
27
27
  export type RebaseOutput = {
28
- rebasedLocalEvents: MutationEvent.PartialAny[]
28
+ rebasedLocalEvents: MutationEvent.PartialAnyDecoded[]
29
29
  }
30
30
 
31
31
  export type RebaseFn = (input: RebaseInput) => RebaseOutput
@@ -43,12 +43,16 @@ export const rebaseEvents = ({
43
43
  pendingLocalEvents,
44
44
  newRemoteEvents,
45
45
  currentFactsSnapshot,
46
+ clientId,
47
+ sessionId,
46
48
  }: {
47
49
  pendingLocalEvents: HistoryDagNode[]
48
50
  newRemoteEvents: HistoryDagNode[]
49
51
  rebaseFn: RebaseFn
50
52
  currentFactsSnapshot: MutationEventFactsSnapshot
51
- }): MutationEvent.Any[] => {
53
+ clientId: string
54
+ sessionId: string | undefined
55
+ }): ReadonlyArray<MutationEvent.AnyDecoded> => {
52
56
  const initialSnapshot = new Map(currentFactsSnapshot)
53
57
  applyFactGroups(
54
58
  newRemoteEvents.map((event) => event.factsGroup),
@@ -89,10 +93,12 @@ export const rebaseEvents = ({
89
93
  return rebasedLocalEvents.map(
90
94
  (event, index) =>
91
95
  ({
92
- id: { global: headGlobalId + index + 1, local: 0 } satisfies EventId.EventId,
93
- parentId: { global: headGlobalId + index, local: 0 } satisfies EventId.EventId,
96
+ id: EventId.make({ global: headGlobalId + index + 1, client: EventId.clientDefault }),
97
+ parentId: EventId.make({ global: headGlobalId + index, client: EventId.clientDefault }),
94
98
  mutation: event.mutation,
95
99
  args: event.args,
96
- }) satisfies MutationEvent.Any,
100
+ clientId,
101
+ sessionId,
102
+ }) satisfies MutationEvent.AnyDecoded,
97
103
  )
98
104
  }
@@ -10,7 +10,7 @@ import { toEventNodes } from './mutation-fixtures.js'
10
10
  expect.addSnapshotSerializer(customSerializer)
11
11
 
12
12
  const compact = (events: any[]) => {
13
- const dag = historyDagFromNodes(toEventNodes(events, mutations))
13
+ const dag = historyDagFromNodes(toEventNodes(events, mutations, 'client-id', 'session-id'))
14
14
  const compacted = compactEvents(dag)
15
15
 
16
16
  return Array.from(compacted.dag.nodeEntries())
@@ -50,8 +50,8 @@ describe('compactEvents calculator', () => {
50
50
 
51
51
  expect(expected).toMatchInlineSnapshot(`
52
52
  [
53
- { id: 0, parentId: -1, mutation: "add", args: { value: 1 }, facts: "" }
54
- { id: 1, parentId: 0, mutation: "add", args: { value: 1 }, facts: "" }
53
+ { id: 0, parentId: -1, mutation: "add", args: { value: 1 }, clientId: "client-id", sessionId: "session-id", facts: "" }
54
+ { id: 1, parentId: 0, mutation: "add", args: { value: 1 }, clientId: "client-id", sessionId: "session-id", facts: "" }
55
55
  ]
56
56
  `)
57
57
  })
@@ -64,8 +64,8 @@ describe('compactEvents calculator', () => {
64
64
 
65
65
  expect(expected).toMatchInlineSnapshot(`
66
66
  [
67
- { id: 0, parentId: -1, mutation: "multiply", args: { value: 2 }, facts: "?multiplyByZero -multiplyByZero" }
68
- { id: 1, parentId: 0, mutation: "multiply", args: { value: 2 }, facts: "?multiplyByZero -multiplyByZero" }
67
+ { id: 0, parentId: -1, mutation: "multiply", args: { value: 2 }, clientId: "client-id", sessionId: "session-id", facts: "?multiplyByZero -multiplyByZero" }
68
+ { id: 1, parentId: 0, mutation: "multiply", args: { value: 2 }, clientId: "client-id", sessionId: "session-id", facts: "?multiplyByZero -multiplyByZero" }
69
69
  ]
70
70
  `)
71
71
  })
@@ -79,7 +79,7 @@ describe('compactEvents calculator', () => {
79
79
 
80
80
  expect(expected).toMatchInlineSnapshot(`
81
81
  [
82
- { id: 2, parentId: -1, mutation: "multiply", args: { value: 0 }, facts: "+multiplyByZero" }
82
+ { id: 2, parentId: -1, mutation: "multiply", args: { value: 0 }, clientId: "client-id", sessionId: "session-id", facts: "+multiplyByZero" }
83
83
  ]
84
84
  `)
85
85
  })
@@ -94,8 +94,8 @@ describe('compactEvents calculator', () => {
94
94
 
95
95
  expect(expected).toMatchInlineSnapshot(`
96
96
  [
97
- { id: 2, parentId: -1, mutation: "multiply", args: { value: 0 }, facts: "+multiplyByZero" }
98
- { id: 3, parentId: 2, mutation: "add", args: { value: 1 }, facts: "" }
97
+ { id: 2, parentId: -1, mutation: "multiply", args: { value: 0 }, clientId: "client-id", sessionId: "session-id", facts: "+multiplyByZero" }
98
+ { id: 3, parentId: 2, mutation: "add", args: { value: 1 }, clientId: "client-id", sessionId: "session-id", facts: "" }
99
99
  ]
100
100
  `)
101
101
  })
@@ -111,10 +111,10 @@ describe('compactEvents calculator', () => {
111
111
 
112
112
  expect(expected).toMatchInlineSnapshot(`
113
113
  [
114
- { id: 0, parentId: -1, mutation: "add", args: { value: 1 }, facts: "" }
115
- { id: 2, parentId: 0, mutation: "multiply", args: { value: 0 }, facts: "+multiplyByZero" }
116
- { id: 3, parentId: 2, mutation: "multiply", args: { value: 2 }, facts: "?multiplyByZero +multiplyByZero -multiplyByZero" }
117
- { id: 4, parentId: 3, mutation: "add", args: { value: 1 }, facts: "" }
114
+ { id: 0, parentId: -1, mutation: "add", args: { value: 1 }, clientId: "client-id", sessionId: "session-id", facts: "" }
115
+ { id: 2, parentId: 0, mutation: "multiply", args: { value: 0 }, clientId: "client-id", sessionId: "session-id", facts: "+multiplyByZero" }
116
+ { id: 3, parentId: 2, mutation: "multiply", args: { value: 2 }, clientId: "client-id", sessionId: "session-id", facts: "?multiplyByZero +multiplyByZero -multiplyByZero" }
117
+ { id: 4, parentId: 3, mutation: "add", args: { value: 1 }, clientId: "client-id", sessionId: "session-id", facts: "" }
118
118
  ]
119
119
  `)
120
120
  })