@livestore/livestore 0.4.0-dev.21 → 0.4.0-dev.23

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 (216) hide show
  1. package/README.md +0 -1
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/QueryCache.js +1 -1
  4. package/dist/QueryCache.js.map +1 -1
  5. package/dist/SqliteDbWrapper.d.ts +5 -5
  6. package/dist/SqliteDbWrapper.d.ts.map +1 -1
  7. package/dist/SqliteDbWrapper.js +8 -8
  8. package/dist/SqliteDbWrapper.js.map +1 -1
  9. package/dist/SqliteDbWrapper.test.js +2 -2
  10. package/dist/SqliteDbWrapper.test.js.map +1 -1
  11. package/dist/effect/LiveStore.d.ts +130 -2
  12. package/dist/effect/LiveStore.d.ts.map +1 -1
  13. package/dist/effect/LiveStore.js +185 -6
  14. package/dist/effect/LiveStore.js.map +1 -1
  15. package/dist/effect/LiveStore.test.d.ts +2 -0
  16. package/dist/effect/LiveStore.test.d.ts.map +1 -0
  17. package/dist/effect/LiveStore.test.js +42 -0
  18. package/dist/effect/LiveStore.test.js.map +1 -0
  19. package/dist/effect/mod.d.ts +1 -1
  20. package/dist/effect/mod.d.ts.map +1 -1
  21. package/dist/effect/mod.js +3 -1
  22. package/dist/effect/mod.js.map +1 -1
  23. package/dist/live-queries/base-class.d.ts +3 -3
  24. package/dist/live-queries/base-class.d.ts.map +1 -1
  25. package/dist/live-queries/base-class.js +2 -2
  26. package/dist/live-queries/base-class.js.map +1 -1
  27. package/dist/live-queries/client-document-get-query.d.ts +1 -1
  28. package/dist/live-queries/client-document-get-query.d.ts.map +1 -1
  29. package/dist/live-queries/client-document-get-query.js +1 -1
  30. package/dist/live-queries/client-document-get-query.js.map +1 -1
  31. package/dist/live-queries/computed.d.ts.map +1 -1
  32. package/dist/live-queries/computed.js +2 -2
  33. package/dist/live-queries/computed.js.map +1 -1
  34. package/dist/live-queries/db-query.js +14 -14
  35. package/dist/live-queries/db-query.js.map +1 -1
  36. package/dist/live-queries/db-query.test.js +2 -2
  37. package/dist/live-queries/db-query.test.js.map +1 -1
  38. package/dist/live-queries/signal.test.js +2 -2
  39. package/dist/live-queries/signal.test.js.map +1 -1
  40. package/dist/mod.d.ts +2 -1
  41. package/dist/mod.d.ts.map +1 -1
  42. package/dist/mod.js +1 -0
  43. package/dist/mod.js.map +1 -1
  44. package/dist/reactive.d.ts +9 -9
  45. package/dist/reactive.d.ts.map +1 -1
  46. package/dist/reactive.js +9 -26
  47. package/dist/reactive.js.map +1 -1
  48. package/dist/reactive.test.js +2 -2
  49. package/dist/reactive.test.js.map +1 -1
  50. package/dist/store/StoreRegistry.d.ts +215 -0
  51. package/dist/store/StoreRegistry.d.ts.map +1 -0
  52. package/dist/store/StoreRegistry.js +267 -0
  53. package/dist/store/StoreRegistry.js.map +1 -0
  54. package/dist/store/StoreRegistry.test.d.ts +2 -0
  55. package/dist/store/StoreRegistry.test.d.ts.map +1 -0
  56. package/dist/store/StoreRegistry.test.js +381 -0
  57. package/dist/store/StoreRegistry.test.js.map +1 -0
  58. package/dist/store/create-store.d.ts +56 -6
  59. package/dist/store/create-store.d.ts.map +1 -1
  60. package/dist/store/create-store.js +32 -7
  61. package/dist/store/create-store.js.map +1 -1
  62. package/dist/store/devtools.d.ts +1 -1
  63. package/dist/store/devtools.d.ts.map +1 -1
  64. package/dist/store/devtools.js +16 -3
  65. package/dist/store/devtools.js.map +1 -1
  66. package/dist/store/store-eventstream.test.js +2 -2
  67. package/dist/store/store-eventstream.test.js.map +1 -1
  68. package/dist/store/store-types.d.ts +59 -9
  69. package/dist/store/store-types.d.ts.map +1 -1
  70. package/dist/store/store-types.js.map +1 -1
  71. package/dist/store/store-types.test.js +1 -1
  72. package/dist/store/store-types.test.js.map +1 -1
  73. package/dist/store/store.d.ts +102 -6
  74. package/dist/store/store.d.ts.map +1 -1
  75. package/dist/store/store.js +148 -47
  76. package/dist/store/store.js.map +1 -1
  77. package/dist/utils/dev.js.map +1 -1
  78. package/dist/utils/stack-info.js +2 -2
  79. package/dist/utils/stack-info.js.map +1 -1
  80. package/dist/utils/tests/fixture.d.ts +1 -1
  81. package/dist/utils/tests/fixture.d.ts.map +1 -1
  82. package/dist/utils/tests/fixture.js.map +1 -1
  83. package/dist/utils/tests/otel.d.ts.map +1 -1
  84. package/dist/utils/tests/otel.js +5 -5
  85. package/dist/utils/tests/otel.js.map +1 -1
  86. package/package.json +59 -18
  87. package/src/QueryCache.ts +1 -1
  88. package/src/SqliteDbWrapper.test.ts +4 -2
  89. package/src/SqliteDbWrapper.ts +12 -11
  90. package/src/ambient.d.ts +0 -7
  91. package/src/effect/LiveStore.test.ts +61 -0
  92. package/src/effect/LiveStore.ts +381 -8
  93. package/src/effect/mod.ts +13 -1
  94. package/src/live-queries/__snapshots__/db-query.test.ts.snap +336 -231
  95. package/src/live-queries/base-class.ts +7 -6
  96. package/src/live-queries/client-document-get-query.ts +4 -2
  97. package/src/live-queries/computed.ts +3 -2
  98. package/src/live-queries/db-query.test.ts +3 -2
  99. package/src/live-queries/db-query.ts +15 -15
  100. package/src/live-queries/signal.test.ts +3 -2
  101. package/src/mod.ts +2 -0
  102. package/src/reactive.test.ts +3 -2
  103. package/src/reactive.ts +22 -23
  104. package/src/store/StoreRegistry.test.ts +540 -0
  105. package/src/store/StoreRegistry.ts +418 -0
  106. package/src/store/create-store.ts +76 -15
  107. package/src/store/devtools.ts +20 -6
  108. package/src/store/store-eventstream.test.ts +4 -2
  109. package/src/store/store-types.test.ts +3 -1
  110. package/src/store/store-types.ts +64 -13
  111. package/src/store/store.ts +197 -60
  112. package/src/utils/dev.ts +2 -2
  113. package/src/utils/stack-info.ts +2 -2
  114. package/src/utils/tests/fixture.ts +2 -1
  115. package/src/utils/tests/otel.ts +8 -7
  116. package/docs/api/index.md +0 -3
  117. package/docs/building-with-livestore/complex-ui-state/index.md +0 -5
  118. package/docs/building-with-livestore/crud/index.md +0 -5
  119. package/docs/building-with-livestore/data-modeling/index.md +0 -1
  120. package/docs/building-with-livestore/debugging/index.md +0 -17
  121. package/docs/building-with-livestore/devtools/index.md +0 -79
  122. package/docs/building-with-livestore/events/index.md +0 -355
  123. package/docs/building-with-livestore/examples/ai-agent/index.md +0 -5
  124. package/docs/building-with-livestore/examples/index.md +0 -30
  125. package/docs/building-with-livestore/examples/todo-workspaces/index.md +0 -891
  126. package/docs/building-with-livestore/examples/turnbased-game/index.md +0 -7
  127. package/docs/building-with-livestore/opentelemetry/index.md +0 -208
  128. package/docs/building-with-livestore/production-checklist/index.md +0 -5
  129. package/docs/building-with-livestore/reactivity-system/index.md +0 -202
  130. package/docs/building-with-livestore/rules-for-ai-agents/index.md +0 -9
  131. package/docs/building-with-livestore/state/materializers/index.md +0 -300
  132. package/docs/building-with-livestore/state/sql-queries/index.md +0 -72
  133. package/docs/building-with-livestore/state/sqlite/index.md +0 -45
  134. package/docs/building-with-livestore/state/sqlite-schema/index.md +0 -306
  135. package/docs/building-with-livestore/state/sqlite-schema-effect/index.md +0 -300
  136. package/docs/building-with-livestore/store/index.md +0 -281
  137. package/docs/building-with-livestore/syncing/index.md +0 -136
  138. package/docs/building-with-livestore/tools/cli/index.md +0 -177
  139. package/docs/building-with-livestore/tools/mcp/index.md +0 -187
  140. package/docs/examples/cloudflare-adapter/index.md +0 -44
  141. package/docs/examples/expo-adapter/index.md +0 -44
  142. package/docs/examples/index.md +0 -55
  143. package/docs/examples/node-adapter/index.md +0 -44
  144. package/docs/examples/web-adapter/index.md +0 -52
  145. package/docs/framework-integrations/custom-elements/index.md +0 -142
  146. package/docs/framework-integrations/react-integration/index.md +0 -918
  147. package/docs/framework-integrations/solid-integration/index.md +0 -293
  148. package/docs/framework-integrations/svelte-integration/index.md +0 -42
  149. package/docs/framework-integrations/vue-integration/index.md +0 -294
  150. package/docs/getting-started/expo/index.md +0 -736
  151. package/docs/getting-started/node/index.md +0 -115
  152. package/docs/getting-started/react-web/index.md +0 -573
  153. package/docs/getting-started/solid/index.md +0 -3
  154. package/docs/getting-started/vue/index.md +0 -471
  155. package/docs/index.md +0 -209
  156. package/docs/llms.txt +0 -147
  157. package/docs/misc/CODE_OF_CONDUCT/index.md +0 -133
  158. package/docs/misc/FAQ/index.md +0 -37
  159. package/docs/misc/community/index.md +0 -88
  160. package/docs/misc/credits/index.md +0 -14
  161. package/docs/misc/design-partners/index.md +0 -13
  162. package/docs/misc/package-management/index.md +0 -21
  163. package/docs/misc/performance/index.md +0 -25
  164. package/docs/misc/resources/index.md +0 -46
  165. package/docs/misc/state-of-the-project/index.md +0 -37
  166. package/docs/misc/troubleshooting/index.md +0 -82
  167. package/docs/overview/concepts/index.md +0 -78
  168. package/docs/overview/how-livestore-works/index.md +0 -56
  169. package/docs/overview/introduction/index.md +0 -5
  170. package/docs/overview/technology-comparison/index.md +0 -40
  171. package/docs/overview/when-livestore/index.md +0 -81
  172. package/docs/overview/why-livestore/index.md +0 -5
  173. package/docs/patterns/ai/index.md +0 -15
  174. package/docs/patterns/anonymous-user-transition/index.md +0 -10
  175. package/docs/patterns/app-evolution/index.md +0 -72
  176. package/docs/patterns/auth/index.md +0 -226
  177. package/docs/patterns/effect/index.md +0 -1495
  178. package/docs/patterns/encryption/index.md +0 -6
  179. package/docs/patterns/external-data/index.md +0 -5
  180. package/docs/patterns/file-management/index.md +0 -11
  181. package/docs/patterns/file-structure/index.md +0 -14
  182. package/docs/patterns/list-ordering/index.md +0 -369
  183. package/docs/patterns/offline/index.md +0 -32
  184. package/docs/patterns/orm/index.md +0 -18
  185. package/docs/patterns/presence/index.md +0 -11
  186. package/docs/patterns/rich-text-editing/index.md +0 -11
  187. package/docs/patterns/server-side-clients/index.md +0 -97
  188. package/docs/patterns/side-effects/index.md +0 -11
  189. package/docs/patterns/state-machines/index.md +0 -11
  190. package/docs/patterns/storybook/index.md +0 -192
  191. package/docs/patterns/undo-redo/index.md +0 -9
  192. package/docs/patterns/version-control/index.md +0 -8
  193. package/docs/platform-adapters/cloudflare-durable-object-adapter/index.md +0 -453
  194. package/docs/platform-adapters/electron-adapter/index.md +0 -15
  195. package/docs/platform-adapters/expo-adapter/index.md +0 -245
  196. package/docs/platform-adapters/node-adapter/index.md +0 -160
  197. package/docs/platform-adapters/tauri-adapter/index.md +0 -15
  198. package/docs/platform-adapters/web-adapter/index.md +0 -218
  199. package/docs/sustainable-open-source/contributing/docs/index.md +0 -94
  200. package/docs/sustainable-open-source/contributing/info/index.md +0 -63
  201. package/docs/sustainable-open-source/contributing/monorepo/index.md +0 -195
  202. package/docs/sustainable-open-source/sponsoring/index.md +0 -104
  203. package/docs/sync-providers/cloudflare/index.md +0 -773
  204. package/docs/sync-providers/custom/index.md +0 -65
  205. package/docs/sync-providers/electricsql/index.md +0 -159
  206. package/docs/sync-providers/s2/index.md +0 -230
  207. package/docs/tutorial/0-welcome/index.md +0 -48
  208. package/docs/tutorial/1-setup-starter-project/index.md +0 -105
  209. package/docs/tutorial/2-deploy-to-cloudflare/index.md +0 -195
  210. package/docs/tutorial/3-read-and-write-todos-via-livestore/index.md +0 -511
  211. package/docs/tutorial/4-sync-data-via-cloudflare/index.md +0 -210
  212. package/docs/tutorial/5-expand-business-logic/index.md +0 -174
  213. package/docs/tutorial/6-persist-ui-state/index.md +0 -453
  214. package/docs/tutorial/7-next-steps/index.md +0 -22
  215. package/docs/understanding-livestore/design-decisions/index.md +0 -33
  216. package/docs/understanding-livestore/event-sourcing/index.md +0 -40
@@ -7,8 +7,8 @@ import { nanoid } from '@livestore/utils/nanoid'
7
7
 
8
8
  import { NOT_REFRESHED_YET } from '../reactive.ts'
9
9
  import { emptyDebugInfo as makeEmptyDebugInfo } from '../SqliteDbWrapper.ts'
10
- import type { Store } from './store.ts'
11
10
  import { StoreInternalsSymbol } from './store-types.ts'
11
+ import type { Store } from './store.ts'
12
12
 
13
13
  type Unsub = () => void
14
14
  type RequestId = string
@@ -23,7 +23,7 @@ const requestNextTick: (cb: () => void) => number =
23
23
  const cancelTick: (id: number) => void =
24
24
  globalThis.cancelAnimationFrame === undefined ? (id: number) => clearTimeout(id) : globalThis.cancelAnimationFrame
25
25
 
26
- export const connectDevtoolsToStore = ({
26
+ export const connectDevtoolsToStore = Effect.fn('LSD.devtools.connectStoreToDevtools')(function* ({
27
27
  storeDevtoolsChannel,
28
28
  store,
29
29
  }: {
@@ -32,8 +32,7 @@ export const connectDevtoolsToStore = ({
32
32
  Devtools.ClientSession.MessageFromApp
33
33
  >
34
34
  store: Store
35
- }) =>
36
- Effect.gen(function* () {
35
+ }) {
37
36
  const reactivityGraphSubcriptions: SubMap = new Map()
38
37
  const liveQueriesSubscriptions: SubMap = new Map()
39
38
  const debugInfoHistorySubscriptions: SubMap = new Map()
@@ -88,7 +87,7 @@ export const connectDevtoolsToStore = ({
88
87
  // So far I could only observe this problem with webmesh proxy channels (e.g. for Expo)
89
88
  // Proof: https://share.cleanshot.com/V9G87B0B
90
89
  // Also see `leader-worker-devtools.ts` for same problem
91
- if (handledRequestIds.has(requestId)) {
90
+ if (handledRequestIds.has(requestId) === true) {
92
91
  return
93
92
  }
94
93
 
@@ -235,6 +234,7 @@ export const connectDevtoolsToStore = ({
235
234
  sendToDevtools(
236
235
  Devtools.ClientSession.LiveQueriesRes.make({
237
236
  liveQueries: [...store[StoreInternalsSymbol].activeQueries].map((q) => ({
237
+ /** TODO: include schema metadata for schema-aware rendering in devtools (e.g., schema AST/hash/identifier or table+columns for QueryBuilder-derived queries). */
238
238
  _tag: q._tag,
239
239
  id: q.id,
240
240
  label: q.label,
@@ -316,6 +316,20 @@ export const connectDevtoolsToStore = ({
316
316
  break
317
317
  }
318
318
  case 'LSD.ClientSession.Ping': {
319
+ // Check version mismatch and respond with VersionMismatch if versions don't match
320
+ if (decodedMessage.liveStoreVersion !== liveStoreVersion) {
321
+ sendToDevtools(
322
+ Devtools.ClientSession.VersionMismatch.make({
323
+ requestId,
324
+ clientId,
325
+ sessionId,
326
+ liveStoreVersion,
327
+ appVersion: liveStoreVersion,
328
+ receivedVersion: decodedMessage.liveStoreVersion,
329
+ }),
330
+ )
331
+ break
332
+ }
319
333
  sendToDevtools(Devtools.ClientSession.Pong.make({ requestId, clientId, sessionId, liveStoreVersion }))
320
334
  break
321
335
  }
@@ -332,4 +346,4 @@ export const connectDevtoolsToStore = ({
332
346
  Stream.runDrain,
333
347
  Effect.withSpan('LSD.devtools.onMessage'),
334
348
  )
335
- }).pipe(UnknownError.mapToUnknownError, Effect.withSpan('LSD.devtools.connectStoreToDevtools'))
349
+ }, UnknownError.mapToUnknownError)
@@ -1,3 +1,5 @@
1
+ import { expect } from 'vitest'
2
+
1
3
  import { makeInMemoryAdapter } from '@livestore/adapter-web'
2
4
  import type { MockSyncBackend } from '@livestore/common'
3
5
  import { type ClientSessionLeaderThreadProxy, makeMockSyncBackend, type UnknownError } from '@livestore/common'
@@ -6,12 +8,12 @@ import { EventFactory } from '@livestore/common/testing'
6
8
  import type { ShutdownDeferred, Store } from '@livestore/livestore'
7
9
  import { createStore, makeShutdownDeferred } from '@livestore/livestore'
8
10
  import { omitUndefineds } from '@livestore/utils'
11
+ import { Vitest } from '@livestore/utils-dev/node-vitest'
9
12
  import type { OtelTracer, Scope } from '@livestore/utils/effect'
10
13
  import { Context, Effect, FetchHttpClient, Layer, Logger, LogLevel, Queue, Stream } from '@livestore/utils/effect'
11
14
  import { nanoid } from '@livestore/utils/nanoid'
12
15
  import { PlatformNode } from '@livestore/utils/node'
13
- import { Vitest } from '@livestore/utils-dev/node-vitest'
14
- import { expect } from 'vitest'
16
+
15
17
  import { events, schema } from '../utils/tests/fixture.ts'
16
18
 
17
19
  const withTestCtx = Vitest.makeWithTestCtx({
@@ -1,7 +1,9 @@
1
+ import { describe, expect, it } from 'vitest'
2
+
1
3
  import type { QueryBuilder } from '@livestore/common'
2
4
  import { QueryBuilderTypeId } from '@livestore/common'
3
5
  import { Schema } from '@livestore/utils/effect'
4
- import { describe, expect, it } from 'vitest'
6
+
5
7
  import { TypeId } from '../live-queries/base-class.ts'
6
8
  import { queryDb, signal } from '../live-queries/mod.ts'
7
9
  import { isQueryable } from './store-types.ts'
@@ -1,22 +1,22 @@
1
+ import type * as otel from '@opentelemetry/api'
2
+
1
3
  import {
2
4
  type ClientSession,
3
5
  type ClientSessionSyncProcessor,
4
6
  type ClientSessionSyncProcessorSimulationParams,
5
7
  type IntentionalShutdownCause,
6
- type InvalidPullError,
7
- type IsOfflineError,
8
8
  isQueryBuilder,
9
9
  type MaterializeError,
10
10
  type QueryBuilder,
11
11
  type StoreInterrupted,
12
- type SyncError,
12
+ type BackendIdMismatchError,
13
13
  type UnknownError,
14
14
  } from '@livestore/common'
15
15
  import type { StreamEventsOptions } from '@livestore/common/leader-thread'
16
16
  import type { LiveStoreEvent, LiveStoreSchema } from '@livestore/common/schema'
17
17
  import type { Effect, Runtime, Schema, Scope } from '@livestore/utils/effect'
18
18
  import { Deferred, Predicate } from '@livestore/utils/effect'
19
- import type * as otel from '@opentelemetry/api'
19
+
20
20
  import type {
21
21
  LiveQuery,
22
22
  LiveQueryDef,
@@ -38,25 +38,27 @@ import type { Store } from './store.ts'
38
38
  * - `running`: Store is active and ready for queries/commits
39
39
  * - `error`: Store failed during boot or operation
40
40
  * - `shutdown`: Store was intentionally shut down or interrupted
41
+ *
42
+ * @typeParam TSchema - The LiveStore schema type. Defaults to `LiveStoreSchema.Any`.
41
43
  */
42
- export type LiveStoreContext =
43
- | LiveStoreContextRunning
44
+ export type LiveStoreContext<TSchema extends LiveStoreSchema = LiveStoreSchema.Any> =
45
+ | LiveStoreContextRunning<TSchema>
44
46
  | {
45
47
  stage: 'error'
46
- error: UnknownError | unknown
48
+ error: unknown
47
49
  }
48
50
  | {
49
51
  stage: 'shutdown'
50
- cause: IntentionalShutdownCause | StoreInterrupted | SyncError
52
+ cause: IntentionalShutdownCause | StoreInterrupted | UnknownError
51
53
  }
52
54
 
53
55
  export type ShutdownDeferred = Deferred.Deferred<
54
56
  IntentionalShutdownCause,
55
- UnknownError | SyncError | StoreInterrupted | MaterializeError | InvalidPullError | IsOfflineError
57
+ UnknownError | StoreInterrupted | MaterializeError | BackendIdMismatchError
56
58
  >
57
59
  export const makeShutdownDeferred: Effect.Effect<ShutdownDeferred> = Deferred.make<
58
60
  IntentionalShutdownCause,
59
- UnknownError | SyncError | StoreInterrupted | MaterializeError | InvalidPullError | IsOfflineError
61
+ UnknownError | StoreInterrupted | MaterializeError | BackendIdMismatchError
60
62
  >()
61
63
 
62
64
  /**
@@ -64,10 +66,14 @@ export const makeShutdownDeferred: Effect.Effect<ShutdownDeferred> = Deferred.ma
64
66
  *
65
67
  * This is the normal operating state where you can query data, commit events,
66
68
  * and subscribe to changes.
69
+ *
70
+ * @typeParam TSchema - The LiveStore schema type. Defaults to `LiveStoreSchema.Any`
71
+ * for backwards compatibility, but prefer providing the concrete schema type
72
+ * for full type safety.
67
73
  */
68
- export type LiveStoreContextRunning = {
74
+ export type LiveStoreContextRunning<TSchema extends LiveStoreSchema = LiveStoreSchema.Any> = {
69
75
  stage: 'running'
70
- store: Store
76
+ store: Store<TSchema>
71
77
  }
72
78
 
73
79
  export type OtelOptions = {
@@ -170,7 +176,13 @@ export type StoreInternals = {
170
176
  isShutdown: boolean
171
177
  }
172
178
 
173
- export type StoreOptions<TSchema extends LiveStoreSchema = LiveStoreSchema.Any, TContext = {}> = {
179
+ /**
180
+ * Parameters for constructing a Store instance.
181
+ *
182
+ * @internal This type is used by the Store constructor and is not part of the public API.
183
+ * For creating stores, use `createStore()` or `StoreRegistry` instead.
184
+ */
185
+ export type StoreConstructorParams<TSchema extends LiveStoreSchema = LiveStoreSchema.Any, TContext = {}> = {
174
186
  clientSession: ClientSession
175
187
  schema: TSchema
176
188
  storeId: string
@@ -404,3 +416,42 @@ export const isLiveQueryInstance = (value: unknown): value is LiveQuery<any> =>
404
416
  */
405
417
  export const isQueryable = (value: unknown): value is Queryable<unknown> =>
406
418
  isQueryBuilder(value) || isLiveQueryInstance(value) || isLiveQueryDef(value)
419
+
420
+ /**
421
+ * Represents the current synchronization status of the store.
422
+ *
423
+ * This provides visibility into the sync state between the client session
424
+ * and the leader thread, allowing applications to show sync indicators
425
+ * or determine backend health.
426
+ *
427
+ * @example
428
+ * ```ts
429
+ * const status = store.syncStatus()
430
+ * if (status.isSynced) {
431
+ * console.log('All changes synced')
432
+ * } else {
433
+ * console.log(`${status.pendingCount} events pending sync`)
434
+ * }
435
+ * ```
436
+ */
437
+ export type SyncStatus = {
438
+ /**
439
+ * The local head sequence number (most recent event in the client session).
440
+ * Represented as a string in the format "e{global}.{client}" (e.g., "e5.2").
441
+ */
442
+ localHead: string
443
+ /**
444
+ * The upstream head sequence number (what the leader thread has confirmed).
445
+ * Represented as a string in the format "e{global}" (e.g., "e3").
446
+ */
447
+ upstreamHead: string
448
+ /**
449
+ * Number of events pending synchronization to the leader thread.
450
+ */
451
+ pendingCount: number
452
+ /**
453
+ * Whether the client session is fully synced with the leader thread.
454
+ * True when there are no pending events (pendingCount === 0).
455
+ */
456
+ isSynced: boolean
457
+ }