@livestore/livestore 0.0.0-snapshot-2b8a9de3ec1a701aca891ebc2c98eb328274ae9e → 0.0.0-snapshot-2c861249e50661661613204300b1fc0d902c2e46
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.
- package/dist/.tsbuildinfo +1 -1
- package/dist/SqliteDbWrapper.d.ts +7 -1
- package/dist/SqliteDbWrapper.d.ts.map +1 -1
- package/dist/SqliteDbWrapper.js +8 -2
- package/dist/SqliteDbWrapper.js.map +1 -1
- package/dist/live-queries/base-class.d.ts +8 -12
- package/dist/live-queries/base-class.d.ts.map +1 -1
- package/dist/live-queries/base-class.js.map +1 -1
- package/dist/live-queries/computed.d.ts +4 -8
- package/dist/live-queries/computed.d.ts.map +1 -1
- package/dist/live-queries/computed.js +1 -6
- package/dist/live-queries/computed.js.map +1 -1
- package/dist/live-queries/db-query.d.ts +13 -18
- package/dist/live-queries/db-query.d.ts.map +1 -1
- package/dist/live-queries/db-query.js +31 -30
- package/dist/live-queries/db-query.js.map +1 -1
- package/dist/live-queries/db-query.test.js +7 -7
- package/dist/live-queries/db-query.test.js.map +1 -1
- package/dist/live-queries/make-ref.d.ts.map +1 -1
- package/dist/live-queries/make-ref.js +1 -0
- package/dist/live-queries/make-ref.js.map +1 -1
- package/dist/live-queries/row-query-utils.d.ts +12 -0
- package/dist/live-queries/row-query-utils.d.ts.map +1 -0
- package/dist/live-queries/row-query-utils.js +18 -0
- package/dist/live-queries/row-query-utils.js.map +1 -0
- package/dist/mod.d.ts +0 -1
- package/dist/mod.d.ts.map +1 -1
- package/dist/mod.js +0 -1
- package/dist/mod.js.map +1 -1
- package/dist/reactive.d.ts.map +1 -1
- package/dist/reactive.js +1 -1
- package/dist/reactive.js.map +1 -1
- package/dist/store/create-store.d.ts +12 -2
- package/dist/store/create-store.d.ts.map +1 -1
- package/dist/store/create-store.js +18 -11
- package/dist/store/create-store.js.map +1 -1
- package/dist/store/store-types.d.ts +11 -10
- package/dist/store/store-types.d.ts.map +1 -1
- package/dist/store/store.d.ts +29 -30
- package/dist/store/store.d.ts.map +1 -1
- package/dist/store/store.js +84 -85
- package/dist/store/store.js.map +1 -1
- package/dist/utils/stack-info.test.js +6 -6
- package/dist/utils/tests/fixture.d.ts +54 -207
- package/dist/utils/tests/fixture.d.ts.map +1 -1
- package/dist/utils/tests/fixture.js +20 -13
- package/dist/utils/tests/fixture.js.map +1 -1
- package/package.json +4 -4
- package/src/SqliteDbWrapper.ts +12 -3
- package/src/live-queries/__snapshots__/db-query.test.ts.snap +9 -9
- package/src/live-queries/base-class.ts +8 -25
- package/src/live-queries/computed.ts +4 -18
- package/src/live-queries/db-query.test.ts +7 -7
- package/src/live-queries/db-query.ts +57 -63
- package/src/live-queries/make-ref.ts +2 -0
- package/src/live-queries/row-query-utils.ts +50 -0
- package/src/mod.ts +0 -2
- package/src/reactive.ts +1 -1
- package/src/store/create-store.ts +33 -15
- package/src/store/store-types.ts +11 -11
- package/src/store/store.ts +120 -122
- package/src/utils/stack-info.test.ts +6 -6
- package/src/utils/tests/fixture.ts +21 -25
- package/dist/row-query-utils.d.ts +0 -17
- package/dist/row-query-utils.d.ts.map +0 -1
- package/dist/row-query-utils.js +0 -34
- package/dist/row-query-utils.js.map +0 -1
- package/src/row-query-utils.ts +0 -76
package/src/store/store.ts
CHANGED
|
@@ -9,7 +9,7 @@ import type {
|
|
|
9
9
|
import {
|
|
10
10
|
Devtools,
|
|
11
11
|
getDurationMsFromSpan,
|
|
12
|
-
|
|
12
|
+
getExecArgsFromEvent,
|
|
13
13
|
getResultSchema,
|
|
14
14
|
IntentionalShutdownCause,
|
|
15
15
|
isQueryBuilder,
|
|
@@ -21,25 +21,16 @@ import {
|
|
|
21
21
|
} from '@livestore/common'
|
|
22
22
|
import type { LiveStoreSchema } from '@livestore/common/schema'
|
|
23
23
|
import {
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
getEventDef,
|
|
25
|
+
LEADER_MERGE_COUNTER_TABLE,
|
|
26
|
+
LiveStoreEvent,
|
|
27
|
+
SCHEMA_EVENT_DEFS_META_TABLE,
|
|
26
28
|
SCHEMA_META_TABLE,
|
|
27
|
-
SCHEMA_MUTATIONS_META_TABLE,
|
|
28
29
|
SESSION_CHANGESET_META_TABLE,
|
|
29
30
|
} from '@livestore/common/schema'
|
|
30
31
|
import { assertNever, isDevEnv } from '@livestore/utils'
|
|
31
32
|
import type { Scope } from '@livestore/utils/effect'
|
|
32
|
-
import {
|
|
33
|
-
Cause,
|
|
34
|
-
Data,
|
|
35
|
-
Effect,
|
|
36
|
-
Inspectable,
|
|
37
|
-
MutableHashMap,
|
|
38
|
-
OtelTracer,
|
|
39
|
-
Runtime,
|
|
40
|
-
Schema,
|
|
41
|
-
Stream,
|
|
42
|
-
} from '@livestore/utils/effect'
|
|
33
|
+
import { Cause, Effect, Inspectable, OtelTracer, Runtime, Schema, Stream } from '@livestore/utils/effect'
|
|
43
34
|
import { nanoid } from '@livestore/utils/nanoid'
|
|
44
35
|
import * as otel from '@opentelemetry/api'
|
|
45
36
|
|
|
@@ -51,13 +42,13 @@ import type {
|
|
|
51
42
|
ReactivityGraphContext,
|
|
52
43
|
} from '../live-queries/base-class.js'
|
|
53
44
|
import { makeReactivityGraph } from '../live-queries/base-class.js'
|
|
45
|
+
import { makeExecBeforeFirstRun } from '../live-queries/row-query-utils.js'
|
|
54
46
|
import type { Ref } from '../reactive.js'
|
|
55
|
-
import { makeExecBeforeFirstRun } from '../row-query-utils.js'
|
|
56
47
|
import { SqliteDbWrapper } from '../SqliteDbWrapper.js'
|
|
57
48
|
import { ReferenceCountedSet } from '../utils/data-structures.js'
|
|
58
49
|
import { downloadBlob, exposeDebugUtils } from '../utils/dev.js'
|
|
59
50
|
import type { StackInfo } from '../utils/stack-info.js'
|
|
60
|
-
import type { RefreshReason,
|
|
51
|
+
import type { RefreshReason, StoreCommitOptions, StoreOptions, StoreOtel, Unsubscribe } from './store-types.js'
|
|
61
52
|
|
|
62
53
|
if (isDevEnv()) {
|
|
63
54
|
exposeDebugUtils()
|
|
@@ -77,16 +68,17 @@ export class Store<TSchema extends LiveStoreSchema = LiveStoreSchema, TContext =
|
|
|
77
68
|
*/
|
|
78
69
|
tableRefs: { [key: string]: Ref<null, ReactivityGraphContext, RefreshReason> }
|
|
79
70
|
|
|
80
|
-
private
|
|
71
|
+
private effectContext: {
|
|
72
|
+
runtime: Runtime.Runtime<Scope.Scope>
|
|
73
|
+
lifetimeScope: Scope.Scope
|
|
74
|
+
}
|
|
81
75
|
|
|
82
76
|
/** RC-based set to see which queries are currently subscribed to */
|
|
83
77
|
activeQueries: ReferenceCountedSet<LiveQuery<any>>
|
|
84
78
|
|
|
85
|
-
// NOTE this is currently exposed for the Devtools databrowser to
|
|
86
|
-
readonly
|
|
87
|
-
private unsyncedMutationEvents
|
|
79
|
+
// NOTE this is currently exposed for the Devtools databrowser to commit events
|
|
80
|
+
readonly __eventSchema
|
|
88
81
|
readonly syncProcessor: ClientSessionSyncProcessor
|
|
89
|
-
readonly lifetimeScope: Scope.Scope
|
|
90
82
|
|
|
91
83
|
readonly boot: Effect.Effect<void, UnexpectedError, Scope.Scope>
|
|
92
84
|
|
|
@@ -96,27 +88,23 @@ export class Store<TSchema extends LiveStoreSchema = LiveStoreSchema, TContext =
|
|
|
96
88
|
schema,
|
|
97
89
|
otelOptions,
|
|
98
90
|
context,
|
|
99
|
-
disableDevtools,
|
|
100
91
|
batchUpdates,
|
|
101
|
-
unsyncedMutationEvents,
|
|
102
92
|
storeId,
|
|
103
|
-
|
|
104
|
-
runtime,
|
|
93
|
+
effectContext,
|
|
105
94
|
params,
|
|
106
95
|
confirmUnsavedChanges,
|
|
96
|
+
__runningInDevtools,
|
|
107
97
|
}: StoreOptions<TSchema, TContext>) {
|
|
108
98
|
super()
|
|
109
99
|
|
|
110
100
|
this.storeId = storeId
|
|
111
|
-
this.unsyncedMutationEvents = unsyncedMutationEvents
|
|
112
101
|
|
|
113
102
|
this.sqliteDbWrapper = new SqliteDbWrapper({ otel: otelOptions, db: clientSession.sqliteDb })
|
|
114
103
|
this.clientSession = clientSession
|
|
115
104
|
this.schema = schema
|
|
116
105
|
this.context = context
|
|
117
106
|
|
|
118
|
-
this.
|
|
119
|
-
this.runtime = runtime
|
|
107
|
+
this.effectContext = effectContext
|
|
120
108
|
|
|
121
109
|
const reactivityGraph = makeReactivityGraph()
|
|
122
110
|
|
|
@@ -125,13 +113,13 @@ export class Store<TSchema extends LiveStoreSchema = LiveStoreSchema, TContext =
|
|
|
125
113
|
this.syncProcessor = makeClientSessionSyncProcessor({
|
|
126
114
|
schema,
|
|
127
115
|
clientSession,
|
|
128
|
-
runtime,
|
|
129
|
-
|
|
130
|
-
const
|
|
116
|
+
runtime: effectContext.runtime,
|
|
117
|
+
applyEvent: (eventDecoded, { otelContext, withChangeset }) => {
|
|
118
|
+
const eventDef = getEventDef(schema, eventDecoded.name)
|
|
131
119
|
|
|
132
|
-
const execArgsArr =
|
|
133
|
-
|
|
134
|
-
|
|
120
|
+
const execArgsArr = getExecArgsFromEvent({
|
|
121
|
+
eventDef,
|
|
122
|
+
event: { decoded: eventDecoded, encoded: undefined },
|
|
135
123
|
})
|
|
136
124
|
|
|
137
125
|
const writeTablesForEvent = new Set<string>()
|
|
@@ -149,7 +137,10 @@ export class Store<TSchema extends LiveStoreSchema = LiveStoreSchema, TContext =
|
|
|
149
137
|
}
|
|
150
138
|
}
|
|
151
139
|
|
|
152
|
-
let sessionChangeset:
|
|
140
|
+
let sessionChangeset:
|
|
141
|
+
| { _tag: 'sessionChangeset'; data: Uint8Array; debug: any }
|
|
142
|
+
| { _tag: 'no-op' }
|
|
143
|
+
| { _tag: 'unset' } = { _tag: 'unset' }
|
|
153
144
|
if (withChangeset === true) {
|
|
154
145
|
sessionChangeset = this.sqliteDbWrapper.withChangeset(exec).changeset
|
|
155
146
|
} else {
|
|
@@ -177,14 +168,14 @@ export class Store<TSchema extends LiveStoreSchema = LiveStoreSchema, TContext =
|
|
|
177
168
|
confirmUnsavedChanges,
|
|
178
169
|
})
|
|
179
170
|
|
|
180
|
-
this.
|
|
171
|
+
this.__eventSchema = LiveStoreEvent.makeEventDefSchemaMemo(schema)
|
|
181
172
|
|
|
182
173
|
// TODO generalize the `tableRefs` concept to allow finer-grained refs
|
|
183
174
|
this.tableRefs = {}
|
|
184
175
|
this.activeQueries = new ReferenceCountedSet()
|
|
185
176
|
|
|
186
|
-
const
|
|
187
|
-
const otelMuationsSpanContext = otel.trace.setSpan(otel.context.active(),
|
|
177
|
+
const commitsSpan = otelOptions.tracer.startSpan('LiveStore:commits', {}, otelOptions.rootSpanContext)
|
|
178
|
+
const otelMuationsSpanContext = otel.trace.setSpan(otel.context.active(), commitsSpan)
|
|
188
179
|
|
|
189
180
|
const queriesSpan = otelOptions.tracer.startSpan('LiveStore:queries', {}, otelOptions.rootSpanContext)
|
|
190
181
|
const otelQueriesSpanContext = otel.trace.setSpan(otel.context.active(), queriesSpan)
|
|
@@ -201,22 +192,22 @@ export class Store<TSchema extends LiveStoreSchema = LiveStoreSchema, TContext =
|
|
|
201
192
|
|
|
202
193
|
this.otel = {
|
|
203
194
|
tracer: otelOptions.tracer,
|
|
204
|
-
|
|
195
|
+
commitsSpanContext: otelMuationsSpanContext,
|
|
205
196
|
queriesSpanContext: otelQueriesSpanContext,
|
|
206
197
|
}
|
|
207
198
|
|
|
208
|
-
// TODO find a better way to detect if we're running LiveStore in the LiveStore devtools
|
|
209
|
-
// But for now this is a good enough approximation with little downsides
|
|
210
|
-
const isRunningInDevtools = disableDevtools === true
|
|
211
|
-
|
|
212
199
|
// Need a set here since `schema.tables` might contain duplicates and some componentStateTables
|
|
213
200
|
const allTableNames = new Set(
|
|
214
|
-
// NOTE we're excluding the LiveStore schema and
|
|
201
|
+
// NOTE we're excluding the LiveStore schema and events tables as they are not user-facing
|
|
215
202
|
// unless LiveStore is running in the devtools
|
|
216
|
-
|
|
203
|
+
__runningInDevtools
|
|
217
204
|
? this.schema.tables.keys()
|
|
218
205
|
: Array.from(this.schema.tables.keys()).filter(
|
|
219
|
-
(_) =>
|
|
206
|
+
(_) =>
|
|
207
|
+
_ !== SCHEMA_META_TABLE &&
|
|
208
|
+
_ !== SCHEMA_EVENT_DEFS_META_TABLE &&
|
|
209
|
+
_ !== SESSION_CHANGESET_META_TABLE &&
|
|
210
|
+
_ !== LEADER_MERGE_COUNTER_TABLE,
|
|
220
211
|
),
|
|
221
212
|
)
|
|
222
213
|
const existingTableRefs = new Map(
|
|
@@ -240,7 +231,7 @@ export class Store<TSchema extends LiveStoreSchema = LiveStoreSchema, TContext =
|
|
|
240
231
|
|
|
241
232
|
// End the otel spans
|
|
242
233
|
syncSpan.end()
|
|
243
|
-
|
|
234
|
+
commitsSpan.end()
|
|
244
235
|
queriesSpan.end()
|
|
245
236
|
}),
|
|
246
237
|
)
|
|
@@ -268,11 +259,11 @@ export class Store<TSchema extends LiveStoreSchema = LiveStoreSchema, TContext =
|
|
|
268
259
|
* ```
|
|
269
260
|
*/
|
|
270
261
|
subscribe = <TResult>(
|
|
271
|
-
query: LiveQueryDef<TResult
|
|
262
|
+
query: LiveQueryDef<TResult> | LiveQuery<TResult>,
|
|
272
263
|
options: {
|
|
273
264
|
/** Called when the query result has changed */
|
|
274
265
|
onUpdate: (value: TResult) => void
|
|
275
|
-
onSubscribe?: (query$: LiveQuery<TResult
|
|
266
|
+
onSubscribe?: (query$: LiveQuery<TResult>) => void
|
|
276
267
|
/** Gets called after the query subscription has been removed */
|
|
277
268
|
onUnsubsubscribe?: () => void
|
|
278
269
|
label?: string
|
|
@@ -346,7 +337,7 @@ export class Store<TSchema extends LiveStoreSchema = LiveStoreSchema, TContext =
|
|
|
346
337
|
)
|
|
347
338
|
|
|
348
339
|
subscribeStream = <TResult>(
|
|
349
|
-
query$: LiveQueryDef<TResult
|
|
340
|
+
query$: LiveQueryDef<TResult>,
|
|
350
341
|
options?: { label?: string; skipInitialRun?: boolean } | undefined,
|
|
351
342
|
): Stream.Stream<TResult> =>
|
|
352
343
|
Stream.asyncPush<TResult>((emit) =>
|
|
@@ -386,8 +377,8 @@ export class Store<TSchema extends LiveStoreSchema = LiveStoreSchema, TContext =
|
|
|
386
377
|
query = <TResult>(
|
|
387
378
|
query:
|
|
388
379
|
| QueryBuilder<TResult, any, any>
|
|
389
|
-
| LiveQuery<TResult
|
|
390
|
-
| LiveQueryDef<TResult
|
|
380
|
+
| LiveQuery<TResult>
|
|
381
|
+
| LiveQueryDef<TResult>
|
|
391
382
|
| { query: string; bindValues: ParamsObject },
|
|
392
383
|
options?: { otelContext?: otel.Context; debugRefreshReason?: RefreshReason },
|
|
393
384
|
): TResult => {
|
|
@@ -401,7 +392,7 @@ export class Store<TSchema extends LiveStoreSchema = LiveStoreSchema, TContext =
|
|
|
401
392
|
makeExecBeforeFirstRun({
|
|
402
393
|
table: ast.tableDef,
|
|
403
394
|
id: ast.id,
|
|
404
|
-
|
|
395
|
+
explicitDefaultValues: ast.explicitDefaultValues,
|
|
405
396
|
otelContext: options?.otelContext,
|
|
406
397
|
})(this.reactivityGraph.context!)
|
|
407
398
|
}
|
|
@@ -424,6 +415,8 @@ export class Store<TSchema extends LiveStoreSchema = LiveStoreSchema, TContext =
|
|
|
424
415
|
}
|
|
425
416
|
}
|
|
426
417
|
|
|
418
|
+
atom = (): TODO => {}
|
|
419
|
+
|
|
427
420
|
// makeLive: {
|
|
428
421
|
// <T>(def: LiveQueryDef<T, any>): LiveQuery<T, any>
|
|
429
422
|
// <T>(def: ILiveQueryRefDef<T>): ILiveQueryRef<T>
|
|
@@ -443,42 +436,42 @@ export class Store<TSchema extends LiveStoreSchema = LiveStoreSchema, TContext =
|
|
|
443
436
|
|
|
444
437
|
// #region commit
|
|
445
438
|
/**
|
|
446
|
-
* Commit a list of
|
|
447
|
-
* and sync the
|
|
439
|
+
* Commit a list of events to the store which will immediately update the local database
|
|
440
|
+
* and sync the events across other clients (similar to a `git commit`).
|
|
448
441
|
*
|
|
449
442
|
* @example
|
|
450
443
|
* ```ts
|
|
451
|
-
* store.commit(
|
|
444
|
+
* store.commit(events.todoCreated({ id: nanoid(), text: 'Make coffee' }))
|
|
452
445
|
* ```
|
|
453
446
|
*
|
|
454
|
-
* You can call `commit` with multiple
|
|
447
|
+
* You can call `commit` with multiple events to apply them in a single database transaction.
|
|
455
448
|
*
|
|
456
449
|
* @example
|
|
457
450
|
* ```ts
|
|
458
451
|
* const todoId = nanoid()
|
|
459
452
|
* store.commit(
|
|
460
|
-
*
|
|
461
|
-
*
|
|
453
|
+
* events.todoCreated({ id: todoId, text: 'Make coffee' }),
|
|
454
|
+
* events.todoCompleted({ id: todoId }))
|
|
462
455
|
* ```
|
|
463
456
|
*
|
|
464
457
|
* For more advanced transaction scenarios, you can pass a synchronous function to `commit` which will receive a callback
|
|
465
|
-
* to which you can pass multiple
|
|
466
|
-
* Under the hood this will simply collect all
|
|
458
|
+
* to which you can pass multiple events to be committed in the same database transaction.
|
|
459
|
+
* Under the hood this will simply collect all events and apply them in a single database transaction.
|
|
467
460
|
*
|
|
468
461
|
* @example
|
|
469
462
|
* ```ts
|
|
470
463
|
* store.commit((commit) => {
|
|
471
464
|
* const todoId = nanoid()
|
|
472
465
|
* if (Math.random() > 0.5) {
|
|
473
|
-
* commit(
|
|
466
|
+
* commit(events.todoCreated({ id: todoId, text: 'Make coffee' }))
|
|
474
467
|
* } else {
|
|
475
|
-
* commit(
|
|
468
|
+
* commit(events.todoCompleted({ id: todoId }))
|
|
476
469
|
* }
|
|
477
470
|
* })
|
|
478
471
|
* ```
|
|
479
472
|
*
|
|
480
|
-
* When committing a large batch of
|
|
481
|
-
* and call `store.manualRefresh()` after all
|
|
473
|
+
* When committing a large batch of events, you can also skip the database refresh to improve performance
|
|
474
|
+
* and call `store.manualRefresh()` after all events have been committed.
|
|
482
475
|
*
|
|
483
476
|
* @example
|
|
484
477
|
* ```ts
|
|
@@ -488,44 +481,44 @@ export class Store<TSchema extends LiveStoreSchema = LiveStoreSchema, TContext =
|
|
|
488
481
|
* // ... 1000 more todos
|
|
489
482
|
* ]
|
|
490
483
|
* for (const todo of todos) {
|
|
491
|
-
* store.commit({ skipRefresh: true },
|
|
484
|
+
* store.commit({ skipRefresh: true }, events.todoCreated({ id: todo.id, text: todo.text }))
|
|
492
485
|
* }
|
|
493
486
|
* store.manualRefresh()
|
|
494
487
|
* ```
|
|
495
488
|
*/
|
|
496
489
|
commit: {
|
|
497
|
-
<const
|
|
490
|
+
<const TCommitArg extends ReadonlyArray<LiveStoreEvent.PartialForSchema<TSchema>>>(...list: TCommitArg): void
|
|
498
491
|
(
|
|
499
|
-
txn: <const
|
|
500
|
-
...list:
|
|
492
|
+
txn: <const TCommitArg extends ReadonlyArray<LiveStoreEvent.PartialForSchema<TSchema>>>(
|
|
493
|
+
...list: TCommitArg
|
|
501
494
|
) => void,
|
|
502
495
|
): void
|
|
503
|
-
<const
|
|
504
|
-
options:
|
|
505
|
-
...list:
|
|
496
|
+
<const TCommitArg extends ReadonlyArray<LiveStoreEvent.PartialForSchema<TSchema>>>(
|
|
497
|
+
options: StoreCommitOptions,
|
|
498
|
+
...list: TCommitArg
|
|
506
499
|
): void
|
|
507
500
|
(
|
|
508
|
-
options:
|
|
509
|
-
txn: <const
|
|
510
|
-
...list:
|
|
501
|
+
options: StoreCommitOptions,
|
|
502
|
+
txn: <const TCommitArg extends ReadonlyArray<LiveStoreEvent.PartialForSchema<TSchema>>>(
|
|
503
|
+
...list: TCommitArg
|
|
511
504
|
) => void,
|
|
512
505
|
): void
|
|
513
|
-
} = (
|
|
514
|
-
const {
|
|
506
|
+
} = (firstEventOrTxnFnOrOptions: any, ...restEvents: any[]) => {
|
|
507
|
+
const { events, options } = this.getCommitArgs(firstEventOrTxnFnOrOptions, restEvents)
|
|
515
508
|
|
|
516
|
-
for (const
|
|
517
|
-
replaceSessionIdSymbol(
|
|
509
|
+
for (const event of events) {
|
|
510
|
+
replaceSessionIdSymbol(event.args, this.clientSession.sessionId)
|
|
518
511
|
}
|
|
519
512
|
|
|
520
|
-
if (
|
|
513
|
+
if (events.length === 0) return
|
|
521
514
|
|
|
522
515
|
const skipRefresh = options?.skipRefresh ?? false
|
|
523
516
|
|
|
524
|
-
const
|
|
525
|
-
|
|
517
|
+
const commitsSpan = otel.trace.getSpan(this.otel.commitsSpanContext)!
|
|
518
|
+
commitsSpan.addEvent('commit')
|
|
526
519
|
|
|
527
520
|
// console.group('LiveStore.commit', { skipRefresh, wasSyncMessage, label })
|
|
528
|
-
//
|
|
521
|
+
// events.forEach((_) => console.debug(_.name, _.id, _.args))
|
|
529
522
|
// console.groupEnd()
|
|
530
523
|
|
|
531
524
|
let durationMs: number
|
|
@@ -534,26 +527,26 @@ export class Store<TSchema extends LiveStoreSchema = LiveStoreSchema, TContext =
|
|
|
534
527
|
'LiveStore:commit',
|
|
535
528
|
{
|
|
536
529
|
attributes: {
|
|
537
|
-
'livestore.
|
|
538
|
-
'livestore.
|
|
530
|
+
'livestore.eventsCount': events.length,
|
|
531
|
+
'livestore.eventTags': events.map((_) => _.name),
|
|
539
532
|
'livestore.commitLabel': options?.label,
|
|
540
533
|
},
|
|
541
534
|
links: options?.spanLinks,
|
|
542
535
|
},
|
|
543
|
-
options?.otelContext ?? this.otel.
|
|
536
|
+
options?.otelContext ?? this.otel.commitsSpanContext,
|
|
544
537
|
(span) => {
|
|
545
538
|
const otelContext = otel.trace.setSpan(otel.context.active(), span)
|
|
546
539
|
|
|
547
540
|
try {
|
|
548
541
|
const { writeTables } = (() => {
|
|
549
542
|
try {
|
|
550
|
-
const
|
|
543
|
+
const applyEvents = () => this.syncProcessor.push(events, { otelContext })
|
|
551
544
|
|
|
552
|
-
if (
|
|
545
|
+
if (events.length > 1) {
|
|
553
546
|
// TODO: what to do about leader transaction here?
|
|
554
|
-
return this.sqliteDbWrapper.txn(
|
|
547
|
+
return this.sqliteDbWrapper.txn(applyEvents)
|
|
555
548
|
} else {
|
|
556
|
-
return
|
|
549
|
+
return applyEvents()
|
|
557
550
|
}
|
|
558
551
|
} catch (e: any) {
|
|
559
552
|
console.error(e)
|
|
@@ -573,7 +566,7 @@ export class Store<TSchema extends LiveStoreSchema = LiveStoreSchema, TContext =
|
|
|
573
566
|
|
|
574
567
|
const debugRefreshReason = {
|
|
575
568
|
_tag: 'commit' as const,
|
|
576
|
-
|
|
569
|
+
events,
|
|
577
570
|
writeTables: Array.from(writeTables),
|
|
578
571
|
}
|
|
579
572
|
|
|
@@ -596,7 +589,7 @@ export class Store<TSchema extends LiveStoreSchema = LiveStoreSchema, TContext =
|
|
|
596
589
|
// #endregion commit
|
|
597
590
|
|
|
598
591
|
/**
|
|
599
|
-
* This can be used in combination with `skipRefresh` when
|
|
592
|
+
* This can be used in combination with `skipRefresh` when committing events.
|
|
600
593
|
* We might need a better solution for this. Let's see.
|
|
601
594
|
*/
|
|
602
595
|
manualRefresh = (options?: { label?: string }) => {
|
|
@@ -604,7 +597,7 @@ export class Store<TSchema extends LiveStoreSchema = LiveStoreSchema, TContext =
|
|
|
604
597
|
this.otel.tracer.startActiveSpan(
|
|
605
598
|
'LiveStore:manualRefresh',
|
|
606
599
|
{ attributes: { 'livestore.manualRefreshLabel': label } },
|
|
607
|
-
this.otel.
|
|
600
|
+
this.otel.commitsSpanContext,
|
|
608
601
|
(span) => {
|
|
609
602
|
const otelContext = otel.trace.setSpan(otel.context.active(), span)
|
|
610
603
|
this.reactivityGraph.runDeferredEffects({ otelContext })
|
|
@@ -633,10 +626,10 @@ export class Store<TSchema extends LiveStoreSchema = LiveStoreSchema, TContext =
|
|
|
633
626
|
}).pipe(this.runEffectFork)
|
|
634
627
|
},
|
|
635
628
|
|
|
636
|
-
|
|
629
|
+
downloadEventlogDb: () => {
|
|
637
630
|
Effect.gen(this, function* () {
|
|
638
|
-
const data = yield* this.clientSession.leaderThread.
|
|
639
|
-
downloadBlob(data, `livestore-
|
|
631
|
+
const data = yield* this.clientSession.leaderThread.getEventlogData
|
|
632
|
+
downloadBlob(data, `livestore-eventlog-${Date.now()}.db`)
|
|
640
633
|
}).pipe(this.runEffectFork)
|
|
641
634
|
},
|
|
642
635
|
|
|
@@ -671,41 +664,46 @@ export class Store<TSchema extends LiveStoreSchema = LiveStoreSchema, TContext =
|
|
|
671
664
|
})
|
|
672
665
|
|
|
673
666
|
private runEffectFork = <A, E>(effect: Effect.Effect<A, E, Scope.Scope>) =>
|
|
674
|
-
effect.pipe(
|
|
667
|
+
effect.pipe(
|
|
668
|
+
Effect.forkIn(this.effectContext.lifetimeScope),
|
|
669
|
+
Effect.tapCauseLogPretty,
|
|
670
|
+
Runtime.runFork(this.effectContext.runtime),
|
|
671
|
+
)
|
|
675
672
|
|
|
676
|
-
private
|
|
677
|
-
|
|
678
|
-
|
|
673
|
+
private getCommitArgs = (
|
|
674
|
+
firstEventOrTxnFnOrOptions: any,
|
|
675
|
+
restEvents: any[],
|
|
679
676
|
): {
|
|
680
|
-
|
|
681
|
-
options:
|
|
677
|
+
events: LiveStoreEvent.PartialForSchema<TSchema>[]
|
|
678
|
+
options: StoreCommitOptions | undefined
|
|
682
679
|
} => {
|
|
683
|
-
let
|
|
684
|
-
let options:
|
|
680
|
+
let events: LiveStoreEvent.PartialForSchema<TSchema>[]
|
|
681
|
+
let options: StoreCommitOptions | undefined
|
|
685
682
|
|
|
686
|
-
if (typeof
|
|
683
|
+
if (typeof firstEventOrTxnFnOrOptions === 'function') {
|
|
687
684
|
// TODO ensure that function is synchronous and isn't called in a async way (also write tests for this)
|
|
688
|
-
|
|
685
|
+
events = firstEventOrTxnFnOrOptions((arg: any) => events.push(arg))
|
|
689
686
|
} else if (
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
687
|
+
firstEventOrTxnFnOrOptions?.label !== undefined ||
|
|
688
|
+
firstEventOrTxnFnOrOptions?.skipRefresh !== undefined ||
|
|
689
|
+
firstEventOrTxnFnOrOptions?.otelContext !== undefined ||
|
|
690
|
+
firstEventOrTxnFnOrOptions?.spanLinks !== undefined
|
|
694
691
|
) {
|
|
695
|
-
options =
|
|
696
|
-
|
|
697
|
-
} else if (
|
|
698
|
-
// When `commit` is called with no arguments (which sometimes happens when dynamically filtering
|
|
699
|
-
|
|
692
|
+
options = firstEventOrTxnFnOrOptions
|
|
693
|
+
events = restEvents
|
|
694
|
+
} else if (firstEventOrTxnFnOrOptions === undefined) {
|
|
695
|
+
// When `commit` is called with no arguments (which sometimes happens when dynamically filtering events)
|
|
696
|
+
events = []
|
|
700
697
|
} else {
|
|
701
|
-
|
|
698
|
+
events = [firstEventOrTxnFnOrOptions, ...restEvents]
|
|
702
699
|
}
|
|
703
700
|
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
701
|
+
// for (const event of events) {
|
|
702
|
+
// if (event.args.id === SessionIdSymbol) {
|
|
703
|
+
// event.args.id = this.clientSession.sessionId
|
|
704
|
+
// }
|
|
705
|
+
// }
|
|
708
706
|
|
|
709
|
-
return {
|
|
707
|
+
return { events, options }
|
|
710
708
|
}
|
|
711
709
|
}
|
|
@@ -86,7 +86,7 @@ Error:
|
|
|
86
86
|
at Object.useMemo (/Users/schickling/Code/overtone/node_modules/.pnpm/react-dom@19.0.0_react@19.0.0/node_modules/react-dom/cjs/react-dom-client.development.js:22757:18)
|
|
87
87
|
at Object.process.env.NODE_ENV.exports.useMemo (/Users/schickling/Code/overtone/node_modules/.pnpm/react@19.0.0/node_modules/react/cjs/react.development.js:1488:34)
|
|
88
88
|
at Module.useQueryRef (/Users/schickling/Code/overtone/submodules/livestore/packages/@livestore/react/src/useQuery.ts:54:27)
|
|
89
|
-
at Module.
|
|
89
|
+
at Module.useClientDocument (/Users/schickling/Code/overtone/submodules/livestore/packages/@livestore/react/src/useClientDocument.ts:111:20)
|
|
90
90
|
at TestComponent (/Users/schickling/Code/overtone/node_modules/.pnpm/@testing-library+react@16.1.0_@testing-library+dom@10.4.0_@types+react-dom@19.0.3_@types+reac_2jaiibiag2sxou3wtzbuqx3r5a/node_modules/@testing-library/react/dist/pure.js:309:27)
|
|
91
91
|
at Object.react-stack-bottom-frame (/Users/schickling/Code/overtone/node_modules/.pnpm/react-dom@19.0.0_react@19.0.0/node_modules/react-dom/cjs/react-dom-client.development.js:22428:20)
|
|
92
92
|
at renderWithHooks (/Users/schickling/Code/overtone/node_modules/.pnpm/react-dom@19.0.0_react@19.0.0/node_modules/react-dom/cjs/react-dom-client.development.js:5757:22)
|
|
@@ -101,8 +101,8 @@ Error:
|
|
|
101
101
|
"name": "TestComponent",
|
|
102
102
|
},
|
|
103
103
|
{
|
|
104
|
-
"filePath": "/Users/schickling/Code/overtone/submodules/livestore/packages/@livestore/react/src/
|
|
105
|
-
"name": "
|
|
104
|
+
"filePath": "/Users/schickling/Code/overtone/submodules/livestore/packages/@livestore/react/src/useClientDocument.ts:111:20",
|
|
105
|
+
"name": "useClientDocument",
|
|
106
106
|
},
|
|
107
107
|
],
|
|
108
108
|
}
|
|
@@ -117,7 +117,7 @@ Error:
|
|
|
117
117
|
at Object.useMemo (/Users/schickling/Code/overtone/node_modules/.pnpm/react-dom@19.0.0_react@19.0.0/node_modules/react-dom/cjs/react-dom-client.development.js:22757:18)
|
|
118
118
|
at Object.process.env.NODE_ENV.exports.useMemo (/Users/schickling/Code/overtone/node_modules/.pnpm/react@19.0.0/node_modules/react/cjs/react.development.js:1488:34)
|
|
119
119
|
at Module.useQueryRef (/Users/schickling/Code/overtone/submodules/livestore/packages/@livestore/react/src/useQuery.ts:54:27)
|
|
120
|
-
at Module.
|
|
120
|
+
at Module.useClientDocument (/Users/schickling/Code/overtone/submodules/livestore/packages/@livestore/react/src/useClientDocument.ts:111:20)
|
|
121
121
|
at Object.react-stack-bottom-frame (/Users/schickling/Code/overtone/node_modules/.pnpm/react-dom@19.0.0_react@19.0.0/node_modules/react-dom/cjs/react-dom-client.development.js:22428:20)
|
|
122
122
|
at renderWithHooks (/Users/schickling/Code/overtone/node_modules/.pnpm/react-dom@19.0.0_react@19.0.0/node_modules/react-dom/cjs/react-dom-client.development.js:5757:22)
|
|
123
123
|
`
|
|
@@ -127,8 +127,8 @@ Error:
|
|
|
127
127
|
{
|
|
128
128
|
"frames": [
|
|
129
129
|
{
|
|
130
|
-
"filePath": "/Users/schickling/Code/overtone/submodules/livestore/packages/@livestore/react/src/
|
|
131
|
-
"name": "
|
|
130
|
+
"filePath": "/Users/schickling/Code/overtone/submodules/livestore/packages/@livestore/react/src/useClientDocument.ts:111:20",
|
|
131
|
+
"name": "useClientDocument",
|
|
132
132
|
},
|
|
133
133
|
],
|
|
134
134
|
}
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { makeInMemoryAdapter } from '@livestore/adapter-web'
|
|
2
2
|
import { provideOtel } from '@livestore/common'
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import { createStore, DbSchema, makeSchema } from '@livestore/livestore'
|
|
6
|
-
import { Effect } from '@livestore/utils/effect'
|
|
3
|
+
import { createStore, makeSchema, State } from '@livestore/livestore'
|
|
4
|
+
import { Effect, Schema } from '@livestore/utils/effect'
|
|
7
5
|
import type * as otel from '@opentelemetry/api'
|
|
8
6
|
|
|
9
7
|
export type Todo = {
|
|
@@ -19,30 +17,28 @@ export type AppState = {
|
|
|
19
17
|
filter: Filter
|
|
20
18
|
}
|
|
21
19
|
|
|
22
|
-
export const todos =
|
|
23
|
-
'todos',
|
|
24
|
-
{
|
|
25
|
-
id:
|
|
26
|
-
text:
|
|
27
|
-
completed:
|
|
20
|
+
export const todos = State.SQLite.table({
|
|
21
|
+
name: 'todos',
|
|
22
|
+
columns: {
|
|
23
|
+
id: State.SQLite.text({ primaryKey: true }),
|
|
24
|
+
text: State.SQLite.text({ default: '', nullable: false }),
|
|
25
|
+
completed: State.SQLite.boolean({ default: false, nullable: false }),
|
|
28
26
|
},
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
{ isSingleton: true },
|
|
40
|
-
)
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
export const app = State.SQLite.clientDocument({
|
|
30
|
+
name: 'app',
|
|
31
|
+
schema: Schema.Struct({
|
|
32
|
+
newTodoText: Schema.String,
|
|
33
|
+
filter: Schema.String,
|
|
34
|
+
}),
|
|
35
|
+
default: { value: { newTodoText: '', filter: 'all' } },
|
|
36
|
+
})
|
|
41
37
|
|
|
42
38
|
export const tables = { todos, app }
|
|
43
|
-
export const schema = makeSchema({ tables })
|
|
44
39
|
|
|
45
|
-
export
|
|
40
|
+
export const state = State.SQLite.makeState({ tables, materializers: {} })
|
|
41
|
+
export const schema = makeSchema({ state, events: {} })
|
|
46
42
|
|
|
47
43
|
export const makeTodoMvc = ({
|
|
48
44
|
otelTracer,
|
|
@@ -52,7 +48,7 @@ export const makeTodoMvc = ({
|
|
|
52
48
|
otelContext?: otel.Context
|
|
53
49
|
} = {}) =>
|
|
54
50
|
Effect.gen(function* () {
|
|
55
|
-
const store
|
|
51
|
+
const store = yield* createStore({
|
|
56
52
|
schema,
|
|
57
53
|
storeId: 'default',
|
|
58
54
|
adapter: makeInMemoryAdapter(),
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import type { QueryInfo } from '@livestore/common';
|
|
2
|
-
import { SessionIdSymbol } from '@livestore/common';
|
|
3
|
-
import { DbSchema } from '@livestore/common/schema';
|
|
4
|
-
import type * as otel from '@opentelemetry/api';
|
|
5
|
-
import type { GetResult, LiveQueryDef, ReactivityGraphContext } from './live-queries/base-class.js';
|
|
6
|
-
export declare const rowQueryLabel: (table: DbSchema.TableDefBase, id: string | SessionIdSymbol | number | undefined) => string;
|
|
7
|
-
export declare const deriveColQuery: {
|
|
8
|
-
<TQueryDef extends LiveQueryDef<any, QueryInfo.None>, TCol extends keyof GetResult<TQueryDef> & string>(queryDef: TQueryDef, colName: TCol): LiveQueryDef<GetResult<TQueryDef>[TCol], QueryInfo.None>;
|
|
9
|
-
<TQueryDef extends LiveQueryDef<any, QueryInfo.Row>, TCol extends keyof GetResult<TQueryDef> & string>(queryDef: TQueryDef, colName: TCol): LiveQueryDef<GetResult<TQueryDef>[TCol], QueryInfo.Col>;
|
|
10
|
-
};
|
|
11
|
-
export declare const makeExecBeforeFirstRun: ({ id, insertValues, table, otelContext: otelContext_, }: {
|
|
12
|
-
id?: string | SessionIdSymbol | number;
|
|
13
|
-
insertValues?: any;
|
|
14
|
-
table: DbSchema.TableDefBase;
|
|
15
|
-
otelContext: otel.Context | undefined;
|
|
16
|
-
}) => ({ store }: ReactivityGraphContext) => undefined;
|
|
17
|
-
//# sourceMappingURL=row-query-utils.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"row-query-utils.d.ts","sourceRoot":"","sources":["../src/row-query-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAsB,SAAS,EAAE,MAAM,mBAAmB,CAAA;AACtE,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AAEnD,OAAO,KAAK,KAAK,IAAI,MAAM,oBAAoB,CAAA;AAE/C,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAA;AAGnG,eAAO,MAAM,aAAa,GAAI,OAAO,QAAQ,CAAC,YAAY,EAAE,IAAI,MAAM,GAAG,eAAe,GAAG,MAAM,GAAG,SAAS,WACH,CAAA;AAE1G,eAAO,MAAM,cAAc,EAAE;IAC3B,CAAC,SAAS,SAAS,YAAY,CAAC,GAAG,EAAE,SAAS,CAAC,IAAI,CAAC,EAAE,IAAI,SAAS,MAAM,SAAS,CAAC,SAAS,CAAC,GAAG,MAAM,EACpG,QAAQ,EAAE,SAAS,EACnB,OAAO,EAAE,IAAI,GACZ,YAAY,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC,IAAI,CAAC,CAAA;IAC3D,CAAC,SAAS,SAAS,YAAY,CAAC,GAAG,EAAE,SAAS,CAAC,GAAG,CAAC,EAAE,IAAI,SAAS,MAAM,SAAS,CAAC,SAAS,CAAC,GAAG,MAAM,EACnG,QAAQ,EAAE,SAAS,EACnB,OAAO,EAAE,IAAI,GACZ,YAAY,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC,GAAG,CAAC,CAAA;CAc3D,CAAA;AAED,eAAO,MAAM,sBAAsB,GAChC,yDAKE;IACD,EAAE,CAAC,EAAE,MAAM,GAAG,eAAe,GAAG,MAAM,CAAA;IACtC,YAAY,CAAC,EAAE,GAAG,CAAA;IAClB,KAAK,EAAE,QAAQ,CAAC,YAAY,CAAA;IAC5B,WAAW,EAAE,IAAI,CAAC,OAAO,GAAG,SAAS,CAAA;CACtC,MACA,WAAW,sBAAsB,cA2BjC,CAAA"}
|