@livestore/common 0.3.0-dev.1 → 0.3.0-dev.11

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 (181) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/adapter-types.d.ts +47 -35
  3. package/dist/adapter-types.d.ts.map +1 -1
  4. package/dist/adapter-types.js.map +1 -1
  5. package/dist/derived-mutations.d.ts +4 -4
  6. package/dist/derived-mutations.d.ts.map +1 -1
  7. package/dist/derived-mutations.test.js.map +1 -1
  8. package/dist/devtools/devtool-message-leader.d.ts +2 -0
  9. package/dist/devtools/devtool-message-leader.d.ts.map +1 -0
  10. package/dist/devtools/devtool-message-leader.js +2 -0
  11. package/dist/devtools/devtool-message-leader.js.map +1 -0
  12. package/dist/devtools/devtools-bridge.d.ts +2 -1
  13. package/dist/devtools/devtools-bridge.d.ts.map +1 -1
  14. package/dist/devtools/devtools-messages-client-session.d.ts +297 -0
  15. package/dist/devtools/devtools-messages-client-session.d.ts.map +1 -0
  16. package/dist/devtools/devtools-messages-client-session.js +61 -0
  17. package/dist/devtools/devtools-messages-client-session.js.map +1 -0
  18. package/dist/devtools/devtools-messages-common.d.ts +65 -0
  19. package/dist/devtools/devtools-messages-common.d.ts.map +1 -0
  20. package/dist/devtools/devtools-messages-common.js +35 -0
  21. package/dist/devtools/devtools-messages-common.js.map +1 -0
  22. package/dist/devtools/devtools-messages-leader.d.ts +261 -0
  23. package/dist/devtools/devtools-messages-leader.d.ts.map +1 -0
  24. package/dist/devtools/devtools-messages-leader.js +85 -0
  25. package/dist/devtools/devtools-messages-leader.js.map +1 -0
  26. package/dist/devtools/devtools-messages.d.ts +3 -592
  27. package/dist/devtools/devtools-messages.d.ts.map +1 -1
  28. package/dist/devtools/devtools-messages.js +3 -171
  29. package/dist/devtools/devtools-messages.js.map +1 -1
  30. package/dist/index.d.ts +0 -4
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/init-singleton-tables.d.ts +2 -2
  33. package/dist/init-singleton-tables.d.ts.map +1 -1
  34. package/dist/init-singleton-tables.js.map +1 -1
  35. package/dist/leader-thread/LeaderSyncProcessor.d.ts +37 -0
  36. package/dist/leader-thread/LeaderSyncProcessor.d.ts.map +1 -0
  37. package/dist/leader-thread/LeaderSyncProcessor.js +432 -0
  38. package/dist/leader-thread/LeaderSyncProcessor.js.map +1 -0
  39. package/dist/leader-thread/apply-mutation.d.ts +5 -2
  40. package/dist/leader-thread/apply-mutation.d.ts.map +1 -1
  41. package/dist/leader-thread/apply-mutation.js +41 -29
  42. package/dist/leader-thread/apply-mutation.js.map +1 -1
  43. package/dist/leader-thread/connection.d.ts +4 -4
  44. package/dist/leader-thread/connection.d.ts.map +1 -1
  45. package/dist/leader-thread/connection.js +5 -5
  46. package/dist/leader-thread/connection.js.map +1 -1
  47. package/dist/leader-thread/leader-sync-processor.d.ts +2 -2
  48. package/dist/leader-thread/leader-sync-processor.d.ts.map +1 -1
  49. package/dist/leader-thread/leader-sync-processor.js +20 -12
  50. package/dist/leader-thread/leader-sync-processor.js.map +1 -1
  51. package/dist/leader-thread/leader-worker-devtools.d.ts +1 -1
  52. package/dist/leader-thread/leader-worker-devtools.d.ts.map +1 -1
  53. package/dist/leader-thread/leader-worker-devtools.js +37 -81
  54. package/dist/leader-thread/leader-worker-devtools.js.map +1 -1
  55. package/dist/leader-thread/make-leader-thread-layer.d.ts +12 -11
  56. package/dist/leader-thread/make-leader-thread-layer.d.ts.map +1 -1
  57. package/dist/leader-thread/make-leader-thread-layer.js +33 -14
  58. package/dist/leader-thread/make-leader-thread-layer.js.map +1 -1
  59. package/dist/leader-thread/mutationlog.d.ts +6 -19
  60. package/dist/leader-thread/mutationlog.d.ts.map +1 -1
  61. package/dist/leader-thread/mutationlog.js +7 -6
  62. package/dist/leader-thread/mutationlog.js.map +1 -1
  63. package/dist/leader-thread/pull-queue-set.d.ts.map +1 -1
  64. package/dist/leader-thread/recreate-db.d.ts.map +1 -1
  65. package/dist/leader-thread/recreate-db.js +24 -18
  66. package/dist/leader-thread/recreate-db.js.map +1 -1
  67. package/dist/leader-thread/types.d.ts +36 -16
  68. package/dist/leader-thread/types.d.ts.map +1 -1
  69. package/dist/leader-thread/types.js.map +1 -1
  70. package/dist/mutation.d.ts +9 -2
  71. package/dist/mutation.d.ts.map +1 -1
  72. package/dist/mutation.js +5 -5
  73. package/dist/mutation.js.map +1 -1
  74. package/dist/query-builder/impl.d.ts +1 -1
  75. package/dist/rehydrate-from-mutationlog.d.ts +5 -5
  76. package/dist/rehydrate-from-mutationlog.d.ts.map +1 -1
  77. package/dist/rehydrate-from-mutationlog.js +13 -19
  78. package/dist/rehydrate-from-mutationlog.js.map +1 -1
  79. package/dist/schema/EventId.d.ts +16 -14
  80. package/dist/schema/EventId.d.ts.map +1 -1
  81. package/dist/schema/EventId.js +15 -7
  82. package/dist/schema/EventId.js.map +1 -1
  83. package/dist/schema/EventId.test.d.ts +2 -0
  84. package/dist/schema/EventId.test.d.ts.map +1 -0
  85. package/dist/schema/EventId.test.js +11 -0
  86. package/dist/schema/EventId.test.js.map +1 -0
  87. package/dist/schema/MutationEvent.d.ts +49 -80
  88. package/dist/schema/MutationEvent.d.ts.map +1 -1
  89. package/dist/schema/MutationEvent.js +32 -15
  90. package/dist/schema/MutationEvent.js.map +1 -1
  91. package/dist/schema/MutationEvent.test.d.ts +2 -0
  92. package/dist/schema/MutationEvent.test.d.ts.map +1 -0
  93. package/dist/schema/MutationEvent.test.js +2 -0
  94. package/dist/schema/MutationEvent.test.js.map +1 -0
  95. package/dist/schema/system-tables.d.ts +26 -26
  96. package/dist/schema/system-tables.d.ts.map +1 -1
  97. package/dist/schema/system-tables.js +19 -11
  98. package/dist/schema/system-tables.js.map +1 -1
  99. package/dist/schema-management/common.d.ts +3 -3
  100. package/dist/schema-management/common.d.ts.map +1 -1
  101. package/dist/schema-management/common.js.map +1 -1
  102. package/dist/schema-management/migrations.d.ts +4 -4
  103. package/dist/schema-management/migrations.d.ts.map +1 -1
  104. package/dist/schema-management/migrations.js +6 -6
  105. package/dist/schema-management/migrations.js.map +1 -1
  106. package/dist/sync/ClientSessionSyncProcessor.d.ts +43 -0
  107. package/dist/sync/ClientSessionSyncProcessor.d.ts.map +1 -0
  108. package/dist/sync/ClientSessionSyncProcessor.js +141 -0
  109. package/dist/sync/ClientSessionSyncProcessor.js.map +1 -0
  110. package/dist/sync/client-session-sync-processor.d.ts +4 -4
  111. package/dist/sync/client-session-sync-processor.d.ts.map +1 -1
  112. package/dist/sync/index.d.ts +1 -1
  113. package/dist/sync/index.d.ts.map +1 -1
  114. package/dist/sync/index.js +1 -1
  115. package/dist/sync/index.js.map +1 -1
  116. package/dist/sync/next/history-dag-common.d.ts +1 -4
  117. package/dist/sync/next/history-dag-common.d.ts.map +1 -1
  118. package/dist/sync/next/history-dag-common.js +1 -1
  119. package/dist/sync/next/history-dag-common.js.map +1 -1
  120. package/dist/sync/next/rebase-events.d.ts +3 -3
  121. package/dist/sync/next/rebase-events.d.ts.map +1 -1
  122. package/dist/sync/next/rebase-events.js +3 -2
  123. package/dist/sync/next/rebase-events.js.map +1 -1
  124. package/dist/sync/next/test/mutation-fixtures.d.ts +7 -7
  125. package/dist/sync/next/test/mutation-fixtures.d.ts.map +1 -1
  126. package/dist/sync/next/test/mutation-fixtures.js +3 -9
  127. package/dist/sync/next/test/mutation-fixtures.js.map +1 -1
  128. package/dist/sync/sync.d.ts +21 -11
  129. package/dist/sync/sync.d.ts.map +1 -1
  130. package/dist/sync/sync.js.map +1 -1
  131. package/dist/sync/syncstate.d.ts +45 -23
  132. package/dist/sync/syncstate.d.ts.map +1 -1
  133. package/dist/sync/syncstate.js +56 -12
  134. package/dist/sync/syncstate.js.map +1 -1
  135. package/dist/sync/syncstate.test.js +125 -69
  136. package/dist/sync/syncstate.test.js.map +1 -1
  137. package/dist/sync/validate-push-payload.d.ts +2 -2
  138. package/dist/sync/validate-push-payload.d.ts.map +1 -1
  139. package/dist/sync/validate-push-payload.js +2 -2
  140. package/dist/sync/validate-push-payload.js.map +1 -1
  141. package/dist/version.d.ts +1 -1
  142. package/dist/version.d.ts.map +1 -1
  143. package/dist/version.js +1 -1
  144. package/dist/version.js.map +1 -1
  145. package/package.json +6 -5
  146. package/src/adapter-types.ts +39 -40
  147. package/src/derived-mutations.test.ts +1 -1
  148. package/src/derived-mutations.ts +9 -5
  149. package/src/devtools/devtools-bridge.ts +2 -1
  150. package/src/devtools/devtools-messages-client-session.ts +109 -0
  151. package/src/devtools/devtools-messages-common.ts +52 -0
  152. package/src/devtools/devtools-messages-leader.ts +115 -0
  153. package/src/devtools/devtools-messages.ts +3 -243
  154. package/src/index.ts +0 -6
  155. package/src/init-singleton-tables.ts +2 -2
  156. package/src/leader-thread/{leader-sync-processor.ts → LeaderSyncProcessor.ts} +306 -268
  157. package/src/leader-thread/apply-mutation.ts +53 -35
  158. package/src/leader-thread/connection.ts +7 -7
  159. package/src/leader-thread/leader-worker-devtools.ts +52 -124
  160. package/src/leader-thread/make-leader-thread-layer.ts +62 -30
  161. package/src/leader-thread/mutationlog.ts +14 -10
  162. package/src/leader-thread/recreate-db.ts +24 -20
  163. package/src/leader-thread/types.ts +41 -20
  164. package/src/mutation.ts +17 -7
  165. package/src/rehydrate-from-mutationlog.ts +18 -26
  166. package/src/schema/EventId.test.ts +12 -0
  167. package/src/schema/EventId.ts +23 -9
  168. package/src/schema/MutationEvent.ts +46 -24
  169. package/src/schema/system-tables.ts +19 -11
  170. package/src/schema-management/common.ts +3 -3
  171. package/src/schema-management/migrations.ts +10 -10
  172. package/src/sync/{client-session-sync-processor.ts → ClientSessionSyncProcessor.ts} +26 -19
  173. package/src/sync/index.ts +1 -1
  174. package/src/sync/next/history-dag-common.ts +1 -1
  175. package/src/sync/next/rebase-events.ts +7 -7
  176. package/src/sync/next/test/mutation-fixtures.ts +3 -10
  177. package/src/sync/sync.ts +19 -6
  178. package/src/sync/syncstate.test.ts +127 -67
  179. package/src/sync/syncstate.ts +21 -19
  180. package/src/sync/validate-push-payload.ts +7 -4
  181. package/src/version.ts +1 -1
@@ -1,4 +1,4 @@
1
- import type { SynchronousDatabase } from '../adapter-types.js'
1
+ import type { SqliteDb } from '../adapter-types.js'
2
2
  import type { ParamsObject } from '../util.js'
3
3
  import { prepareBindValues } from '../util.js'
4
4
 
@@ -6,7 +6,7 @@ import { prepareBindValues } from '../util.js'
6
6
  // will require proper scope-aware cleanup etc (for testing and apps with multiple LiveStore instances)
7
7
  // const cachedStmts = new Map<string, PreparedStatement>()
8
8
 
9
- export const dbExecute = (db: SynchronousDatabase, queryStr: string, bindValues?: ParamsObject) => {
9
+ export const dbExecute = (db: SqliteDb, queryStr: string, bindValues?: ParamsObject) => {
10
10
  // let stmt = cachedStmts.get(queryStr)
11
11
  // if (!stmt) {
12
12
  const stmt = db.prepare(queryStr)
@@ -20,7 +20,7 @@ export const dbExecute = (db: SynchronousDatabase, queryStr: string, bindValues?
20
20
  stmt.finalize()
21
21
  }
22
22
 
23
- export const dbSelect = <T>(db: SynchronousDatabase, queryStr: string, bindValues?: ParamsObject) => {
23
+ export const dbSelect = <T>(db: SqliteDb, queryStr: string, bindValues?: ParamsObject) => {
24
24
  // let stmt = cachedStmts.get(queryStr)
25
25
  // if (!stmt) {
26
26
  const stmt = db.prepare(queryStr)
@@ -2,7 +2,7 @@ import { SqliteAst, SqliteDsl } from '@livestore/db-schema'
2
2
  import { memoizeByStringifyArgs } from '@livestore/utils'
3
3
  import { Effect, Schema as EffectSchema } from '@livestore/utils/effect'
4
4
 
5
- import type { SynchronousDatabase } from '../adapter-types.js'
5
+ import type { SqliteDb } from '../adapter-types.js'
6
6
  import type { LiveStoreSchema } from '../schema/mod.js'
7
7
  import type { SchemaMetaRow, SchemaMutationsMetaRow } from '../schema/system-tables.js'
8
8
  import {
@@ -19,7 +19,7 @@ import { validateSchema } from './validate-mutation-defs.js'
19
19
 
20
20
  const getMemoizedTimestamp = memoizeByStringifyArgs(() => new Date().toISOString())
21
21
 
22
- export const makeSchemaManager = (db: 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,7 +51,7 @@ 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
  }) =>
@@ -116,7 +116,7 @@ export const migrateTable = ({
116
116
  behaviour,
117
117
  skipMetaTable = false,
118
118
  }: {
119
- db: SynchronousDatabase
119
+ db: SqliteDb
120
120
  tableAst: SqliteAst.Table
121
121
  schemaHash?: number
122
122
  behaviour: 'drop-and-recreate' | 'create-if-not-exists'
@@ -129,10 +129,10 @@ export const migrateTable = ({
129
129
 
130
130
  if (behaviour === 'drop-and-recreate') {
131
131
  // TODO need to possibly handle cascading deletes due to foreign keys
132
- dbExecute(db, sql`drop table if exists ${tableName}`)
133
- dbExecute(db, sql`create table if not exists ${tableName} (${columnSpec}) strict`)
132
+ dbExecute(db, sql`drop table if exists '${tableName}'`)
133
+ dbExecute(db, sql`create table if not exists '${tableName}' (${columnSpec}) strict`)
134
134
  } else if (behaviour === 'create-if-not-exists') {
135
- dbExecute(db, sql`create table if not exists ${tableName} (${columnSpec}) strict`)
135
+ dbExecute(db, sql`create table if not exists '${tableName}' (${columnSpec}) strict`)
136
136
  }
137
137
 
138
138
  for (const index of tableAst.indexes) {
@@ -162,11 +162,11 @@ export const migrateTable = ({
162
162
 
163
163
  const createIndexFromDefinition = (tableName: string, index: SqliteAst.Index) => {
164
164
  const uniqueStr = index.unique ? 'UNIQUE' : ''
165
- return sql`create ${uniqueStr} index if not exists ${index.name} on ${tableName} (${index.columns.join(', ')})`
165
+ return sql`create ${uniqueStr} index if not exists '${index.name}' on '${tableName}' (${index.columns.join(', ')})`
166
166
  }
167
167
 
168
168
  export const makeColumnSpec = (tableAst: SqliteAst.Table) => {
169
- const primaryKeys = tableAst.columns.filter((_) => _.primaryKey).map((_) => _.name)
169
+ const primaryKeys = tableAst.columns.filter((_) => _.primaryKey).map((_) => `'${_.name}'`)
170
170
  const columnDefStrs = tableAst.columns.map(toSqliteColumnSpec)
171
171
  if (primaryKeys.length > 0) {
172
172
  columnDefStrs.push(`PRIMARY KEY (${primaryKeys.join(', ')})`)
@@ -191,5 +191,5 @@ const toSqliteColumnSpec = (column: SqliteAst.Column) => {
191
191
  return `default ${encodedDefaultValue}`
192
192
  })()
193
193
 
194
- return `${column.name} ${columnTypeStr} ${nullableStr} ${defaultValueStr}`
194
+ return `'${column.name}' ${columnTypeStr} ${nullableStr} ${defaultValueStr}`
195
195
  }
@@ -1,14 +1,13 @@
1
1
  import { LS_DEV, shouldNeverHappen, TRACE_VERBOSE } from '@livestore/utils'
2
- import type { Scope } from '@livestore/utils/effect'
2
+ import type { Runtime, Scope } from '@livestore/utils/effect'
3
3
  import { Effect, Schema, Stream } from '@livestore/utils/effect'
4
4
  import * as otel from '@opentelemetry/api'
5
5
 
6
- import type { Coordinator, UnexpectedError } from '../adapter-types.js'
6
+ import type { ClientSession, UnexpectedError } from '../adapter-types.js'
7
7
  import * as EventId from '../schema/EventId.js'
8
8
  import { type LiveStoreSchema } from '../schema/mod.js'
9
9
  import * as MutationEvent from '../schema/MutationEvent.js'
10
- import type { SyncState } from './syncstate.js'
11
- import { updateSyncState } from './syncstate.js'
10
+ import { SyncState, updateSyncState } from './syncstate.js'
12
11
 
13
12
  /**
14
13
  * Rebase behaviour:
@@ -21,20 +20,18 @@ import { updateSyncState } from './syncstate.js'
21
20
  */
22
21
  export const makeClientSessionSyncProcessor = ({
23
22
  schema,
24
- initialLeaderHead,
25
- pushToLeader,
26
- pullFromLeader,
23
+ clientSession,
24
+ runtime,
27
25
  applyMutation,
28
26
  rollback,
29
27
  refreshTables,
30
28
  span,
31
29
  }: {
32
30
  schema: LiveStoreSchema
33
- initialLeaderHead: EventId.EventId
34
- pushToLeader: (batch: ReadonlyArray<MutationEvent.AnyEncoded>) => void
35
- pullFromLeader: Coordinator['mutations']['pull']
31
+ clientSession: ClientSession
32
+ runtime: Runtime.Runtime<Scope.Scope>
36
33
  applyMutation: (
37
- mutationEventDecoded: MutationEvent.PartialAny,
34
+ mutationEventDecoded: MutationEvent.PartialAnyDecoded,
38
35
  options: { otelContext: otel.Context; withChangeset: boolean },
39
36
  ) => {
40
37
  writeTables: Set<string>
@@ -42,19 +39,18 @@ export const makeClientSessionSyncProcessor = ({
42
39
  }
43
40
  rollback: (changeset: Uint8Array) => void
44
41
  refreshTables: (tables: Set<string>) => void
45
- // rebaseBehaviour: 'auto-rebase' | 'manual-rebase'
46
42
  span: otel.Span
47
43
  }): ClientSessionSyncProcessor => {
48
44
  const mutationEventSchema = MutationEvent.makeMutationEventSchemaMemo(schema)
49
45
 
50
46
  const syncStateRef = {
51
- current: {
52
- localHead: initialLeaderHead,
53
- upstreamHead: initialLeaderHead,
47
+ current: new SyncState({
48
+ localHead: clientSession.leaderThread.mutations.initialMutationEventId,
49
+ upstreamHead: clientSession.leaderThread.mutations.initialMutationEventId,
54
50
  pending: [],
55
51
  // TODO init rollbackTail from leader to be ready for backend rebasing
56
52
  rollbackTail: [],
57
- } as SyncState,
53
+ }),
58
54
  }
59
55
 
60
56
  const isLocalEvent = (mutationEventEncoded: MutationEvent.EncodedWithMeta) => {
@@ -104,7 +100,10 @@ export const makeClientSessionSyncProcessor = ({
104
100
  mutationEvent.meta.sessionChangeset = res.sessionChangeset
105
101
  }
106
102
 
107
- pushToLeader(encodedMutationEvents)
103
+ // console.debug('pushToLeader', encodedMutationEvents.length, ...encodedMutationEvents.map((_) => _.toJSON()))
104
+ clientSession.leaderThread.mutations
105
+ .push(encodedMutationEvents)
106
+ .pipe(Effect.tapCauseLogPretty, Effect.provide(runtime), Effect.runFork)
108
107
 
109
108
  return { writeTables }
110
109
  }
@@ -112,10 +111,13 @@ export const makeClientSessionSyncProcessor = ({
112
111
  const otelContext = otel.trace.setSpan(otel.context.active(), span)
113
112
 
114
113
  const boot: ClientSessionSyncProcessor['boot'] = Effect.gen(function* () {
115
- yield* pullFromLeader.pipe(
114
+ yield* clientSession.leaderThread.mutations.pull.pipe(
116
115
  Stream.tap(({ payload, remaining }) =>
117
116
  Effect.gen(function* () {
118
117
  // console.log('pulled payload from leader', { payload, remaining })
118
+ if (clientSession.devtools.enabled) {
119
+ yield* clientSession.devtools.pullLatch.await
120
+ }
119
121
 
120
122
  const updateResult = updateSyncState({
121
123
  syncState: syncStateRef.current,
@@ -155,6 +157,10 @@ export const makeClientSessionSyncProcessor = ({
155
157
  event.meta.sessionChangeset = undefined
156
158
  }
157
159
  }
160
+
161
+ clientSession.leaderThread.mutations
162
+ .push(updateResult.newSyncState.pending)
163
+ .pipe(Effect.tapCauseLogPretty, Effect.provide(runtime), Effect.runFork)
158
164
  } else {
159
165
  span.addEvent('pull:advance', {
160
166
  payloadTag: payload._tag,
@@ -182,6 +188,7 @@ export const makeClientSessionSyncProcessor = ({
182
188
  }),
183
189
  ),
184
190
  Stream.runDrain,
191
+ Effect.forever, // NOTE Whenever the leader changes, we need to re-start the stream
185
192
  Effect.tapCauseLogPretty,
186
193
  Effect.forkScoped,
187
194
  )
@@ -196,7 +203,7 @@ export const makeClientSessionSyncProcessor = ({
196
203
 
197
204
  export interface ClientSessionSyncProcessor {
198
205
  push: (
199
- batch: ReadonlyArray<MutationEvent.PartialAny>,
206
+ batch: ReadonlyArray<MutationEvent.PartialAnyDecoded>,
200
207
  options: { otelContext: otel.Context },
201
208
  ) => {
202
209
  writeTables: Set<string>
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'
@@ -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, local: EventId.localDefault })
24
24
 
25
25
  export type HistoryDagNode = {
26
26
  id: EventId.EventId
@@ -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
@@ -48,7 +48,7 @@ export const rebaseEvents = ({
48
48
  newRemoteEvents: HistoryDagNode[]
49
49
  rebaseFn: RebaseFn
50
50
  currentFactsSnapshot: MutationEventFactsSnapshot
51
- }): MutationEvent.Any[] => {
51
+ }): ReadonlyArray<MutationEvent.AnyDecoded> => {
52
52
  const initialSnapshot = new Map(currentFactsSnapshot)
53
53
  applyFactGroups(
54
54
  newRemoteEvents.map((event) => event.factsGroup),
@@ -89,10 +89,10 @@ export const rebaseEvents = ({
89
89
  return rebasedLocalEvents.map(
90
90
  (event, index) =>
91
91
  ({
92
- id: { global: headGlobalId + index + 1, local: 0 } satisfies EventId.EventId,
93
- parentId: { global: headGlobalId + index, local: 0 } satisfies EventId.EventId,
92
+ id: EventId.make({ global: headGlobalId + index + 1, local: EventId.localDefault }),
93
+ parentId: EventId.make({ global: headGlobalId + index, local: EventId.localDefault }),
94
94
  mutation: event.mutation,
95
95
  args: event.args,
96
- }) satisfies MutationEvent.Any,
96
+ }) satisfies MutationEvent.AnyDecoded,
97
97
  )
98
98
  }
@@ -140,16 +140,9 @@ export const toEventNodes = (
140
140
 
141
141
  let currentEventId: EventId.EventId = EventId.ROOT
142
142
 
143
- const getNextEventId = (mutationDef: MutationDef.Any): EventId.EventId => {
144
- if (mutationDef.options.localOnly) {
145
- return { global: currentEventId.global, local: currentEventId.local + 1 }
146
- }
147
- return { global: currentEventId.global + 1, local: 0 }
148
- }
149
-
150
143
  const eventNodes = partialEvents.map((partialEvent) => {
151
144
  const mutationDef = mutationDefs[partialEvent.mutation]!
152
- const eventId = getNextEventId(mutationDef)
145
+ const eventId = EventId.nextPair(currentEventId, mutationDef.options.localOnly).id
153
146
  currentEventId = eventId
154
147
 
155
148
  const factsSnapshot = factsSnapshotForDag(historyDagFromNodes(nodesAcc, { skipFactsCheck: true }), undefined)
@@ -224,8 +217,8 @@ const getParentId = (eventId: EventId.EventId): EventId.EventId => {
224
217
  const localParentId = eventId.local - 1
225
218
 
226
219
  if (localParentId < 0) {
227
- return { global: globalParentId - 1, local: 0 }
220
+ return EventId.make({ global: globalParentId - 1, local: EventId.localDefault })
228
221
  }
229
222
 
230
- return { global: globalParentId, local: localParentId }
223
+ return EventId.make({ global: globalParentId, local: localParentId })
231
224
  }
package/src/sync/sync.ts CHANGED
@@ -1,12 +1,23 @@
1
- import type { Effect, HttpClient, Option, Stream, SubscriptionRef } from '@livestore/utils/effect'
1
+ import type { Effect, HttpClient, Option, Scope, Stream, SubscriptionRef } from '@livestore/utils/effect'
2
2
  import { Schema } from '@livestore/utils/effect'
3
3
 
4
+ import type { UnexpectedError } from '../adapter-types.js'
5
+ import type { InitialSyncOptions } from '../leader-thread/types.js'
4
6
  import * as EventId from '../schema/EventId.js'
5
7
  import type * as MutationEvent from '../schema/MutationEvent.js'
6
8
 
7
- export interface SyncBackendOptionsBase {
8
- type: string
9
- [key: string]: Schema.JsonValue
9
+ /**
10
+ * Those arguments can be used to implement multi-tenancy etc and are passed in from the store.
11
+ */
12
+ export type MakeBackendArgs = {
13
+ storeId: string
14
+ clientId: string
15
+ }
16
+
17
+ export type SyncOptions = {
18
+ makeBackend: (args: MakeBackendArgs) => Effect.Effect<SyncBackend<any>, UnexpectedError, Scope.Scope>
19
+ /** @default { _tag: 'Skip' } */
20
+ initialSyncOptions?: InitialSyncOptions
10
21
  }
11
22
 
12
23
  export type SyncBackend<TSyncMetadata = Schema.JsonValue> = {
@@ -18,7 +29,7 @@ export type SyncBackend<TSyncMetadata = Schema.JsonValue> = {
18
29
  ) => Stream.Stream<
19
30
  {
20
31
  batch: ReadonlyArray<{
21
- mutationEventEncoded: MutationEvent.AnyEncoded
32
+ mutationEventEncoded: MutationEvent.AnyEncodedGlobal
22
33
  metadata: Option.Option<TSyncMetadata>
23
34
  }>
24
35
  remaining: number
@@ -33,7 +44,7 @@ export type SyncBackend<TSyncMetadata = Schema.JsonValue> = {
33
44
  * - Number of events: 1-100
34
45
  * - event ids must be in ascending order
35
46
  * */
36
- batch: ReadonlyArray<MutationEvent.AnyEncoded>,
47
+ batch: ReadonlyArray<MutationEvent.AnyEncodedGlobal>,
37
48
  ) => Effect.Effect<
38
49
  {
39
50
  /** Indexes are relative to `batch` */
@@ -46,6 +57,7 @@ export type SyncBackend<TSyncMetadata = Schema.JsonValue> = {
46
57
  }
47
58
 
48
59
  export class IsOfflineError extends Schema.TaggedError<IsOfflineError>()('IsOfflineError', {}) {}
60
+
49
61
  export class InvalidPushError extends Schema.TaggedError<InvalidPushError>()('InvalidPushError', {
50
62
  reason: Schema.Union(
51
63
  Schema.TaggedStruct('Unexpected', {
@@ -61,6 +73,7 @@ export class InvalidPushError extends Schema.TaggedError<InvalidPushError>()('In
61
73
  }),
62
74
  ),
63
75
  }) {}
76
+
64
77
  export class InvalidPullError extends Schema.TaggedError<InvalidPullError>()('InvalidPullError', {
65
78
  message: Schema.String,
66
79
  }) {}