@livestore/livestore 0.3.0-dev.11 → 0.3.0-dev.13

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 (65) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/SqliteDbWrapper.js +0 -1
  3. package/dist/SqliteDbWrapper.js.map +1 -1
  4. package/dist/index.d.ts +1 -1
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +1 -1
  7. package/dist/index.js.map +1 -1
  8. package/dist/live-queries/base-class.d.ts +2 -9
  9. package/dist/live-queries/base-class.d.ts.map +1 -1
  10. package/dist/live-queries/base-class.js +3 -5
  11. package/dist/live-queries/base-class.js.map +1 -1
  12. package/dist/live-queries/computed.d.ts.map +1 -1
  13. package/dist/live-queries/computed.js +1 -2
  14. package/dist/live-queries/computed.js.map +1 -1
  15. package/dist/live-queries/db-query.d.ts.map +1 -1
  16. package/dist/live-queries/db-query.js +1 -2
  17. package/dist/live-queries/db-query.js.map +1 -1
  18. package/dist/live-queries/db-query.test.js +46 -56
  19. package/dist/live-queries/db-query.test.js.map +1 -1
  20. package/dist/live-queries/graphql.d.ts.map +1 -1
  21. package/dist/live-queries/graphql.js +1 -2
  22. package/dist/live-queries/graphql.js.map +1 -1
  23. package/dist/reactive.d.ts +8 -4
  24. package/dist/reactive.d.ts.map +1 -1
  25. package/dist/reactive.js +9 -11
  26. package/dist/reactive.js.map +1 -1
  27. package/dist/reactive.test.js +1 -1
  28. package/dist/reactive.test.js.map +1 -1
  29. package/dist/row-query-utils.d.ts +2 -2
  30. package/dist/row-query-utils.d.ts.map +1 -1
  31. package/dist/row-query-utils.js +3 -3
  32. package/dist/row-query-utils.js.map +1 -1
  33. package/dist/store/create-store.d.ts +5 -2
  34. package/dist/store/create-store.d.ts.map +1 -1
  35. package/dist/store/create-store.js +15 -1
  36. package/dist/store/create-store.js.map +1 -1
  37. package/dist/store/devtools.d.ts +3 -2
  38. package/dist/store/devtools.d.ts.map +1 -1
  39. package/dist/store/devtools.js +30 -8
  40. package/dist/store/devtools.js.map +1 -1
  41. package/dist/store/store.d.ts +3 -2
  42. package/dist/store/store.d.ts.map +1 -1
  43. package/dist/store/store.js +8 -3
  44. package/dist/store/store.js.map +1 -1
  45. package/dist/utils/tests/fixture.d.ts +15 -15
  46. package/dist/utils/tests/fixture.d.ts.map +1 -1
  47. package/dist/utils/tests/fixture.js +1 -1
  48. package/dist/utils/tests/fixture.js.map +1 -1
  49. package/package.json +5 -6
  50. package/src/SqliteDbWrapper.ts +0 -1
  51. package/src/index.ts +1 -2
  52. package/src/live-queries/__snapshots__/db-query.test.ts.snap +0 -3
  53. package/src/live-queries/base-class.ts +5 -14
  54. package/src/live-queries/computed.ts +1 -2
  55. package/src/live-queries/db-query.test.ts +28 -26
  56. package/src/live-queries/db-query.ts +1 -2
  57. package/src/live-queries/graphql.ts +1 -2
  58. package/src/reactive.test.ts +1 -1
  59. package/src/reactive.ts +14 -16
  60. package/src/row-query-utils.ts +5 -5
  61. package/src/store/create-store.ts +35 -4
  62. package/src/store/devtools.ts +57 -12
  63. package/src/store/store.ts +11 -4
  64. package/src/utils/tests/fixture.ts +1 -1
  65. package/tsconfig.json +1 -2
package/src/reactive.ts CHANGED
@@ -24,8 +24,8 @@
24
24
  /* eslint-disable prefer-arrow/prefer-arrow-functions */
25
25
 
26
26
  import { BoundArray } from '@livestore/common'
27
- import type { PrettifyFlat } from '@livestore/utils'
28
27
  import { deepEqual, shouldNeverHappen } from '@livestore/utils'
28
+ import type { Types } from '@livestore/utils/effect'
29
29
  import type * as otel from '@opentelemetry/api'
30
30
  // import { getDurationMsFromSpan } from './otel.js'
31
31
 
@@ -144,7 +144,7 @@ const encodedOptionNone = <A>(): EncodedOption<A> => ({ _tag: 'None' })
144
144
  export type SerializedAtom = SerializedRef | SerializedThunk
145
145
 
146
146
  export type SerializedRef = Readonly<
147
- PrettifyFlat<
147
+ Types.Simplify<
148
148
  Pick<Ref<unknown, unknown, any>, '_tag' | 'id' | 'label' | 'meta' | 'isDirty' | 'isDestroyed' | 'refreshes'> & {
149
149
  /** Is `None` if `getSnapshot` was called with `includeResults: false` which is the default */
150
150
  previousResult: EncodedOption<string>
@@ -155,7 +155,7 @@ export type SerializedRef = Readonly<
155
155
  >
156
156
 
157
157
  export type SerializedThunk = Readonly<
158
- PrettifyFlat<
158
+ Types.Simplify<
159
159
  Pick<
160
160
  Thunk<unknown, unknown, any>,
161
161
  '_tag' | 'id' | 'label' | 'meta' | 'isDirty' | 'isDestroyed' | 'recomputations'
@@ -169,7 +169,7 @@ export type SerializedThunk = Readonly<
169
169
  >
170
170
 
171
171
  export type SerializedEffect = Readonly<
172
- PrettifyFlat<
172
+ Types.Simplify<
173
173
  Pick<Effect<any>, '_tag' | 'id' | 'label' | 'invocations' | 'isDestroyed'> & {
174
174
  sub: ReadonlyArray<string>
175
175
  }
@@ -183,18 +183,11 @@ export type ReactiveGraphSnapshot = {
183
183
  readonly deferredEffects: ReadonlyArray<string>
184
184
  }
185
185
 
186
- let nodeIdCounter = 0
187
- const uniqueNodeId = () => `node-${++nodeIdCounter}`
188
- let refreshInfoIdCounter = 0
189
- const uniqueRefreshInfoId = () => `refresh-info-${++refreshInfoIdCounter}`
190
-
191
186
  let globalGraphIdCounter = 0
192
187
  const uniqueGraphId = () => `graph-${++globalGraphIdCounter}`
193
188
 
194
189
  /** Used for testing */
195
190
  export const __resetIds = () => {
196
- nodeIdCounter = 0
197
- refreshInfoIdCounter = 0
198
191
  globalGraphIdCounter = 0
199
192
  }
200
193
 
@@ -220,13 +213,18 @@ export class ReactiveGraph<
220
213
 
221
214
  private refreshCallbacks: Set<() => void> = new Set()
222
215
 
216
+ private nodeIdCounter = 0
217
+ private uniqueNodeId = () => `node-${++this.nodeIdCounter}`
218
+ private refreshInfoIdCounter = 0
219
+ private uniqueRefreshInfoId = () => `refresh-info-${++this.refreshInfoIdCounter}`
220
+
223
221
  makeRef<T>(
224
222
  val: T,
225
223
  options?: { label?: string; meta?: unknown; equal?: (a: T, b: T) => boolean },
226
224
  ): Ref<T, TContext, TDebugRefreshReason> {
227
225
  const ref: Ref<T, TContext, TDebugRefreshReason> = {
228
226
  _tag: 'ref',
229
- id: uniqueNodeId(),
227
+ id: this.uniqueNodeId(),
230
228
  isDirty: false,
231
229
  isDestroyed: false,
232
230
  previousResult: val,
@@ -262,7 +260,7 @@ export class ReactiveGraph<
262
260
  ): Thunk<T, TContext, TDebugRefreshReason> {
263
261
  const thunk: Thunk<T, TContext, TDebugRefreshReason> = {
264
262
  _tag: 'thunk',
265
- id: uniqueNodeId(),
263
+ id: this.uniqueNodeId(),
266
264
  previousResult: NOT_REFRESHED_YET,
267
265
  isDirty: true,
268
266
  isDestroyed: false,
@@ -314,7 +312,7 @@ export class ReactiveGraph<
314
312
  this.currentDebugRefresh = undefined
315
313
 
316
314
  this.debugRefreshInfos.push({
317
- id: uniqueRefreshInfoId(),
315
+ id: this.uniqueRefreshInfoId(),
318
316
  reason: debugRefreshReason ?? ({ _tag: 'makeThunk', label: options?.label } as TDebugRefreshReason),
319
317
  skippedRefresh: false,
320
318
  refreshedAtoms,
@@ -387,7 +385,7 @@ export class ReactiveGraph<
387
385
  ): Effect<TDebugRefreshReason> {
388
386
  const effect: Effect<TDebugRefreshReason> = {
389
387
  _tag: 'effect',
390
- id: uniqueNodeId(),
388
+ id: this.uniqueNodeId(),
391
389
  isDestroyed: false,
392
390
  doEffect: (otelContext, debugRefreshReason) => {
393
391
  effect.invocations++
@@ -488,7 +486,7 @@ export class ReactiveGraph<
488
486
  this.currentDebugRefresh = undefined
489
487
 
490
488
  const refreshDebugInfo: RefreshDebugInfo<TDebugRefreshReason, TDebugThunkInfo> = {
491
- id: uniqueRefreshInfoId(),
489
+ id: this.uniqueRefreshInfoId(),
492
490
  reason: options.debugRefreshReason,
493
491
  skippedRefresh: false,
494
492
  refreshedAtoms,
@@ -7,7 +7,7 @@ import type * as otel from '@opentelemetry/api'
7
7
  import type { GetResult, LiveQueryDef, ReactivityGraphContext } from './live-queries/base-class.js'
8
8
  import { computed } from './live-queries/computed.js'
9
9
 
10
- export const rowQueryLabel = (table: DbSchema.TableDefBase, id: string | SessionIdSymbol | undefined) =>
10
+ export const rowQueryLabel = (table: DbSchema.TableDefBase, id: string | SessionIdSymbol | number | undefined) =>
11
11
  `row:${table.sqliteDef.name}${id === undefined ? '' : id === SessionIdSymbol ? `:sessionId` : `:${id}`}`
12
12
 
13
13
  export const deriveColQuery: {
@@ -41,7 +41,7 @@ export const makeExecBeforeFirstRun =
41
41
  table,
42
42
  otelContext: otelContext_,
43
43
  }: {
44
- id?: string | SessionIdSymbol
44
+ id?: string | SessionIdSymbol | number
45
45
  insertValues?: any
46
46
  table: DbSchema.TableDefBase
47
47
  otelContext: otel.Context | undefined
@@ -50,11 +50,11 @@ export const makeExecBeforeFirstRun =
50
50
  const otelContext = otelContext_ ?? store.otel.queriesSpanContext
51
51
 
52
52
  if (table.options.isSingleton === false) {
53
- const idStr = id === SessionIdSymbol ? store.sessionId : id!
53
+ const idVal = id === SessionIdSymbol ? store.sessionId : id!
54
54
  const rowExists =
55
55
  store.sqliteDbWrapper.select(
56
56
  `SELECT 1 FROM '${table.sqliteDef.name}' WHERE id = ?`,
57
- [idStr] as any as PreparedBindValues,
57
+ [idVal] as any as PreparedBindValues,
58
58
  { otelContext },
59
59
  ).length === 1
60
60
 
@@ -69,7 +69,7 @@ export const makeExecBeforeFirstRun =
69
69
  // It's important that we only mutate and don't refresh here, as this function might be called during a render
70
70
  // and otherwise we might end up in a "reactive loop"
71
71
  store.mutate(
72
- { otelContext, skipRefresh: true, label: `rowQuery:${table.sqliteDef.name}:${idStr}` },
72
+ { otelContext, skipRefresh: true, label: `rowQuery:${table.sqliteDef.name}:${idVal}` },
73
73
  table.insert({ id, ...insertValues }),
74
74
  )
75
75
  }
@@ -2,8 +2,9 @@ import type {
2
2
  Adapter,
3
3
  BootStatus,
4
4
  ClientSession,
5
+ ClientSessionDevtoolsChannel,
5
6
  IntentionalShutdownCause,
6
- StoreDevtoolsChannel,
7
+ MigrationsReport,
7
8
  } from '@livestore/common'
8
9
  import { provideOtel, UnexpectedError } from '@livestore/common'
9
10
  import type { EventId, LiveStoreSchema, MutationEvent } from '@livestore/common/schema'
@@ -39,7 +40,10 @@ export interface CreateStoreOptions<TGraphQLContext extends BaseGraphQLContext,
39
40
  graphQLOptions?: GraphQLOptions<TGraphQLContext>
40
41
  boot?: (
41
42
  store: Store<TGraphQLContext, TSchema>,
42
- parentSpan: otel.Span,
43
+ ctx: {
44
+ migrationsReport: MigrationsReport
45
+ parentSpan: otel.Span
46
+ },
43
47
  ) => void | Promise<void> | Effect.Effect<void, unknown, OtelTracer.OtelTracer | LiveStoreContextRunning>
44
48
  batchUpdates?: (run: () => void) => void
45
49
  disableDevtools?: boolean
@@ -107,6 +111,8 @@ export const createStore = <
107
111
  Effect.gen(function* () {
108
112
  const lifetimeScope = yield* Scope.make()
109
113
 
114
+ yield* validateStoreId(storeId)
115
+
110
116
  yield* Effect.addFinalizer((_) => Scope.close(lifetimeScope, _))
111
117
 
112
118
  const debugInstanceId = debug?.instanceId ?? nanoid(10)
@@ -128,7 +134,7 @@ export const createStore = <
128
134
 
129
135
  const storeDeferred = yield* Deferred.make<Store>()
130
136
 
131
- const connectDevtoolsToStore_ = (storeDevtoolsChannel: StoreDevtoolsChannel) =>
137
+ const connectDevtoolsToStore_ = (storeDevtoolsChannel: ClientSessionDevtoolsChannel) =>
132
138
  Effect.gen(function* () {
133
139
  const store = yield* storeDeferred
134
140
  yield* connectDevtoolsToStore({ storeDevtoolsChannel, store })
@@ -158,6 +164,16 @@ export const createStore = <
158
164
  debugInstanceId,
159
165
  }).pipe(Effect.withPerformanceMeasure('livestore:makeAdapter'), Effect.withSpan('createStore:makeAdapter'))
160
166
 
167
+ if (LS_DEV && clientSession.leaderThread.initialState.migrationsReport.migrations.length > 0) {
168
+ yield* Effect.logDebug(
169
+ '[@livestore/livestore:createStore] migrationsReport',
170
+ ...clientSession.leaderThread.initialState.migrationsReport.migrations.map(
171
+ (m) =>
172
+ `Schema hash mismatch for table '${m.tableName}' (DB: ${m.hashes.actual}, expected: ${m.hashes.expected}), migrating table...`,
173
+ ),
174
+ )
175
+ }
176
+
161
177
  // TODO fill up with unsynced mutation events from the client session
162
178
  const unsyncedMutationEvents = MutableHashMap.empty<EventId.EventId, MutationEvent.ForSchema<TSchema>>()
163
179
 
@@ -176,11 +192,14 @@ export const createStore = <
176
192
  storeId,
177
193
  })
178
194
 
195
+ // Starts background fibers (syncing, mutation processing, etc) for store
179
196
  yield* store.boot
180
197
 
181
198
  if (boot !== undefined) {
182
199
  // TODO also incorporate `boot` function progress into `bootStatusQueue`
183
- yield* Effect.tryAll(() => boot(store, span)).pipe(
200
+ yield* Effect.tryAll(() =>
201
+ boot(store, { migrationsReport: clientSession.leaderThread.initialState.migrationsReport, parentSpan: span }),
202
+ ).pipe(
184
203
  UnexpectedError.mapToUnexpectedError,
185
204
  Effect.provide(Layer.succeed(LiveStoreContextRunning, { stage: 'running', store: store as any as Store })),
186
205
  Effect.withSpan('createStore:boot'),
@@ -205,3 +224,15 @@ export const createStore = <
205
224
  Scope.extend(lifetimeScope),
206
225
  )
207
226
  })
227
+
228
+ const validateStoreId = (storeId: string) =>
229
+ Effect.gen(function* () {
230
+ const validChars = /^[a-zA-Z0-9_-]+$/
231
+
232
+ if (!validChars.test(storeId)) {
233
+ return yield* UnexpectedError.make({
234
+ cause: `Invalid storeId: ${storeId}. Only alphanumeric characters, underscores, and hyphens are allowed.`,
235
+ payload: { storeId },
236
+ })
237
+ }
238
+ })
@@ -1,4 +1,4 @@
1
- import type { ClientSession, DebugInfo } from '@livestore/common'
1
+ import type { ClientSession, ClientSessionSyncProcessor, DebugInfo, SyncState } from '@livestore/common'
2
2
  import { Devtools, liveStoreVersion, UnexpectedError } from '@livestore/common'
3
3
  import { throttle } from '@livestore/utils'
4
4
  import type { WebChannel } from '@livestore/utils/effect'
@@ -15,6 +15,7 @@ type IStore = {
15
15
  reactivityGraph: ReactivityGraph
16
16
  sqliteDbWrapper: SqliteDbWrapper
17
17
  activeQueries: ReferenceCountedSet<LiveQuery<any>>
18
+ syncProcessor: ClientSessionSyncProcessor
18
19
  }
19
20
 
20
21
  type Unsub = () => void
@@ -34,13 +35,17 @@ export const connectDevtoolsToStore = ({
34
35
  storeDevtoolsChannel,
35
36
  store,
36
37
  }: {
37
- storeDevtoolsChannel: WebChannel.WebChannel<Devtools.MessageToAppClientSession, Devtools.MessageFromAppClientSession>
38
+ storeDevtoolsChannel: WebChannel.WebChannel<
39
+ Devtools.ClientSession.MessageToApp,
40
+ Devtools.ClientSession.MessageFromApp
41
+ >
38
42
  store: IStore
39
43
  }) =>
40
44
  Effect.gen(function* () {
41
45
  const reactivityGraphSubcriptions: SubMap = new Map()
42
46
  const liveQueriesSubscriptions: SubMap = new Map()
43
47
  const debugInfoHistorySubscriptions: SubMap = new Map()
48
+ const syncHeadClientSessionSubscriptions: SubMap = new Map()
44
49
 
45
50
  const { clientId, sessionId } = store.clientSession
46
51
 
@@ -49,13 +54,14 @@ export const connectDevtoolsToStore = ({
49
54
  reactivityGraphSubcriptions.forEach((unsub) => unsub())
50
55
  liveQueriesSubscriptions.forEach((unsub) => unsub())
51
56
  debugInfoHistorySubscriptions.forEach((unsub) => unsub())
57
+ syncHeadClientSessionSubscriptions.forEach((unsub) => unsub())
52
58
  }),
53
59
  )
54
60
 
55
- const sendToDevtools = (message: Devtools.MessageFromAppClientSession) =>
61
+ const sendToDevtools = (message: Devtools.ClientSession.MessageFromApp) =>
56
62
  storeDevtoolsChannel.send(message).pipe(Effect.tapCauseLogPretty, Effect.runFork)
57
63
 
58
- const onMessage = (decodedMessage: typeof Devtools.MessageToAppClientSession.Type) => {
64
+ const onMessage = (decodedMessage: typeof Devtools.ClientSession.MessageToApp.Type) => {
59
65
  // console.debug('@livestore/livestore:store:devtools:onMessage', decodedMessage)
60
66
 
61
67
  if (decodedMessage.clientId !== clientId || decodedMessage.sessionId !== sessionId) {
@@ -63,7 +69,7 @@ export const connectDevtoolsToStore = ({
63
69
  return
64
70
  }
65
71
 
66
- if (decodedMessage._tag === 'LSD.Disconnect') {
72
+ if (decodedMessage._tag === 'LSD.ClientSession.Disconnect') {
67
73
  // console.error('TODO handle disconnect properly in store')
68
74
  return
69
75
  }
@@ -82,7 +88,7 @@ export const connectDevtoolsToStore = ({
82
88
  requestIdleCallback(
83
89
  () =>
84
90
  sendToDevtools(
85
- Devtools.ReactivityGraphRes.make({
91
+ Devtools.ClientSession.ReactivityGraphRes.make({
86
92
  reactivityGraph: store.reactivityGraph.getSnapshot({ includeResults }),
87
93
  requestId,
88
94
  clientId,
@@ -106,7 +112,7 @@ export const connectDevtoolsToStore = ({
106
112
  }
107
113
  case 'LSD.ClientSession.DebugInfoReq': {
108
114
  sendToDevtools(
109
- Devtools.DebugInfoRes.make({
115
+ Devtools.ClientSession.DebugInfoRes.make({
110
116
  debugInfo: store.sqliteDbWrapper.debugInfo,
111
117
  requestId,
112
118
  clientId,
@@ -132,7 +138,7 @@ export const connectDevtoolsToStore = ({
132
138
 
133
139
  if (buffer.length > 10) {
134
140
  sendToDevtools(
135
- Devtools.DebugInfoHistoryRes.make({
141
+ Devtools.ClientSession.DebugInfoHistoryRes.make({
136
142
  debugInfoHistory: buffer,
137
143
  requestId,
138
144
  clientId,
@@ -171,13 +177,17 @@ export const connectDevtoolsToStore = ({
171
177
  }
172
178
  case 'LSD.ClientSession.DebugInfoResetReq': {
173
179
  store.sqliteDbWrapper.debugInfo.slowQueries.clear()
174
- sendToDevtools(Devtools.DebugInfoResetRes.make({ requestId, clientId, sessionId, liveStoreVersion }))
180
+ sendToDevtools(
181
+ Devtools.ClientSession.DebugInfoResetRes.make({ requestId, clientId, sessionId, liveStoreVersion }),
182
+ )
175
183
  break
176
184
  }
177
185
  case 'LSD.ClientSession.DebugInfoRerunQueryReq': {
178
186
  const { queryStr, bindValues, queriedTables } = decodedMessage
179
187
  store.sqliteDbWrapper.select(queryStr, bindValues, { queriedTables, skipCache: true })
180
- sendToDevtools(Devtools.DebugInfoRerunQueryRes.make({ requestId, clientId, sessionId, liveStoreVersion }))
188
+ sendToDevtools(
189
+ Devtools.ClientSession.DebugInfoRerunQueryRes.make({ requestId, clientId, sessionId, liveStoreVersion }),
190
+ )
181
191
  break
182
192
  }
183
193
  case 'LSD.ClientSession.ReactivityGraphUnsubscribe': {
@@ -191,7 +201,7 @@ export const connectDevtoolsToStore = ({
191
201
  requestIdleCallback(
192
202
  () =>
193
203
  sendToDevtools(
194
- Devtools.LiveQueriesRes.make({
204
+ Devtools.ClientSession.LiveQueriesRes.make({
195
205
  liveQueries: [...store.activeQueries].map((q) => ({
196
206
  _tag: q._tag,
197
207
  id: q.id,
@@ -229,7 +239,42 @@ export const connectDevtoolsToStore = ({
229
239
  liveQueriesSubscriptions.delete(requestId)
230
240
  break
231
241
  }
232
- // No default
242
+ case 'LSD.ClientSession.SyncHeadSubscribe': {
243
+ const send = (syncState: SyncState.SyncState) =>
244
+ sendToDevtools(
245
+ Devtools.ClientSession.SyncHeadRes.make({
246
+ local: syncState.localHead,
247
+ upstream: syncState.upstreamHead,
248
+ requestId,
249
+ clientId,
250
+ sessionId,
251
+ liveStoreVersion,
252
+ }),
253
+ )
254
+
255
+ send(store.syncProcessor.syncState.pipe(Effect.runSync))
256
+
257
+ syncHeadClientSessionSubscriptions.set(
258
+ requestId,
259
+ store.syncProcessor.syncState.changes.pipe(
260
+ Stream.tap((syncState) => send(syncState)),
261
+ Stream.runDrain,
262
+ Effect.interruptible,
263
+ Effect.tapCauseLogPretty,
264
+ Effect.runCallback,
265
+ ),
266
+ )
267
+
268
+ break
269
+ }
270
+ case 'LSD.ClientSession.SyncHeadUnsubscribe': {
271
+ syncHeadClientSessionSubscriptions.get(requestId)?.()
272
+ syncHeadClientSessionSubscriptions.delete(requestId)
273
+ break
274
+ }
275
+ default: {
276
+ console.warn(`[LSD.ClientSession] Unknown message`, decodedMessage)
277
+ }
233
278
  }
234
279
  }
235
280
 
@@ -96,7 +96,7 @@ export class Store<
96
96
  // NOTE this is currently exposed for the Devtools databrowser to emit mutation events
97
97
  readonly __mutationEventSchema
98
98
  private unsyncedMutationEvents
99
- private syncProcessor: ClientSessionSyncProcessor
99
+ readonly syncProcessor: ClientSessionSyncProcessor
100
100
  readonly lifetimeScope: Scope.Scope
101
101
 
102
102
  readonly boot: Effect.Effect<void, UnexpectedError, Scope.Scope>
@@ -195,7 +195,7 @@ export class Store<
195
195
  this.reactivityGraph = reactivityGraph
196
196
  this.reactivityGraph.context = {
197
197
  store: this as unknown as Store<BaseGraphQLContext, LiveStoreSchema>,
198
- liveQueryRCMap: new Map(),
198
+ defRcMap: new Map(),
199
199
  reactivityGraph: new WeakRef(reactivityGraph),
200
200
  otelTracer: otelOptions.tracer,
201
201
  rootOtelContext: otelQueriesSpanContext,
@@ -262,6 +262,10 @@ export class Store<
262
262
  return this.clientSession.sessionId
263
263
  }
264
264
 
265
+ get clientId(): string {
266
+ return this.clientSession.clientId
267
+ }
268
+
265
269
  /**
266
270
  * Subscribe to the results of a query
267
271
  * Returns a function to cancel the subscription.
@@ -594,15 +598,16 @@ export class Store<
594
598
 
595
599
  hardReset: (mode: 'all-data' | 'only-app-db' = 'all-data') => {
596
600
  Effect.gen(this, function* () {
601
+ const clientId = this.clientSession.clientId
597
602
  yield* this.clientSession.leaderThread.sendDevtoolsMessage(
598
- Devtools.ResetAllDataReq.make({ liveStoreVersion, mode, requestId: nanoid() }),
603
+ Devtools.Leader.ResetAllData.Request.make({ liveStoreVersion, mode, requestId: nanoid(), clientId }),
599
604
  )
600
605
  }).pipe(this.runEffectFork)
601
606
  },
602
607
 
603
608
  syncStates: () => {
604
609
  Effect.gen(this, function* () {
605
- const session = this.syncProcessor.syncStateRef.current
610
+ const session = yield* this.syncProcessor.syncState
606
611
  console.log('Session sync state:', session.toJSON())
607
612
  const leader = yield* this.clientSession.leaderThread.getSyncState
608
613
  console.log('Leader sync state:', leader.toJSON())
@@ -614,6 +619,8 @@ export class Store<
614
619
  .shutdown(cause ?? Cause.fail(IntentionalShutdownCause.make({ reason: 'manual' })))
615
620
  .pipe(Effect.tapCauseLogPretty, Effect.provide(this.runtime), Effect.runFork)
616
621
  },
622
+
623
+ version: liveStoreVersion,
617
624
  }
618
625
 
619
626
  // NOTE This is needed because when booting a Store via Effect it seems to call `toJSON` in the error path
@@ -1,9 +1,9 @@
1
+ import { makeInMemoryAdapter } from '@livestore/adapter-web'
1
2
  import { provideOtel } from '@livestore/common'
2
3
  import type { FromInputSchema } from '@livestore/common/schema'
3
4
  import type { Store } from '@livestore/livestore'
4
5
  import { createStore, DbSchema, makeSchema } from '@livestore/livestore'
5
6
  import { Effect } from '@livestore/utils/effect'
6
- import { makeInMemoryAdapter } from '@livestore/web'
7
7
  import type * as otel from '@opentelemetry/api'
8
8
 
9
9
  export type Todo = {
package/tsconfig.json CHANGED
@@ -10,9 +10,8 @@
10
10
  },
11
11
  "include": ["./src"],
12
12
  "references": [
13
- { "path": "../db-schema" },
14
13
  { "path": "../common" },
15
- { "path": "../web" },
14
+ { "path": "../adapter-web" },
16
15
  { "path": "../utils" }
17
16
  ]
18
17
  }