@livestore/livestore 0.4.0-dev.16 → 0.4.0-dev.18
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.test.js +2 -1
- package/dist/SqliteDbWrapper.test.js.map +1 -1
- package/dist/live-queries/client-document-get-query.js +3 -2
- package/dist/live-queries/client-document-get-query.js.map +1 -1
- package/dist/live-queries/db-query.d.ts.map +1 -1
- package/dist/live-queries/db-query.js +6 -4
- package/dist/live-queries/db-query.js.map +1 -1
- package/dist/live-queries/db-query.test.js +64 -4
- package/dist/live-queries/db-query.test.js.map +1 -1
- package/dist/mod.d.ts +1 -2
- package/dist/mod.d.ts.map +1 -1
- package/dist/mod.js +1 -1
- package/dist/mod.js.map +1 -1
- package/dist/store/create-store.d.ts.map +1 -1
- package/dist/store/create-store.js +3 -2
- package/dist/store/create-store.js.map +1 -1
- package/dist/store/devtools.d.ts +2 -13
- package/dist/store/devtools.d.ts.map +1 -1
- package/dist/store/devtools.js +34 -13
- package/dist/store/devtools.js.map +1 -1
- package/dist/store/store-types.d.ts +89 -4
- package/dist/store/store-types.d.ts.map +1 -1
- package/dist/store/store-types.js +1 -0
- package/dist/store/store-types.js.map +1 -1
- package/dist/store/store.d.ts +20 -26
- package/dist/store/store.d.ts.map +1 -1
- package/dist/store/store.js +129 -91
- package/dist/store/store.js.map +1 -1
- package/package.json +5 -5
- package/src/SqliteDbWrapper.test.ts +2 -2
- package/src/live-queries/__snapshots__/db-query.test.ts.snap +220 -0
- package/src/live-queries/client-document-get-query.ts +3 -3
- package/src/live-queries/db-query.test.ts +103 -6
- package/src/live-queries/db-query.ts +7 -4
- package/src/mod.ts +8 -8
- package/src/store/create-store.ts +3 -2
- package/src/store/devtools.ts +40 -26
- package/src/store/store-types.ts +107 -4
- package/src/store/store.ts +166 -123
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@livestore/livestore",
|
|
3
|
-
"version": "0.4.0-dev.
|
|
3
|
+
"version": "0.4.0-dev.18",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"exports": {
|
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
},
|
|
12
12
|
"dependencies": {
|
|
13
13
|
"@opentelemetry/api": "1.9.0",
|
|
14
|
-
"@livestore/common": "0.4.0-dev.
|
|
15
|
-
"@livestore/utils": "0.4.0-dev.
|
|
14
|
+
"@livestore/common": "0.4.0-dev.18",
|
|
15
|
+
"@livestore/utils": "0.4.0-dev.18"
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
18
18
|
"@opentelemetry/sdk-trace-base": "^2.0.1",
|
|
@@ -20,8 +20,8 @@
|
|
|
20
20
|
"typescript": "5.9.2",
|
|
21
21
|
"vite": "7.1.7",
|
|
22
22
|
"vitest": "3.2.4",
|
|
23
|
-
"@livestore/utils-dev": "0.4.0-dev.
|
|
24
|
-
"@livestore/adapter-web": "0.4.0-dev.
|
|
23
|
+
"@livestore/utils-dev": "0.4.0-dev.18",
|
|
24
|
+
"@livestore/adapter-web": "0.4.0-dev.18"
|
|
25
25
|
},
|
|
26
26
|
"files": [
|
|
27
27
|
"package.json",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Effect } from '@livestore/utils/effect'
|
|
2
2
|
import { Vitest } from '@livestore/utils-dev/node-vitest'
|
|
3
3
|
import { expect } from 'vitest'
|
|
4
|
-
|
|
4
|
+
import { StoreInternalsSymbol } from './store/store-types.ts'
|
|
5
5
|
import { makeTodoMvc } from './utils/tests/fixture.ts'
|
|
6
6
|
|
|
7
7
|
Vitest.describe('SqliteDbWrapper', () => {
|
|
@@ -9,7 +9,7 @@ Vitest.describe('SqliteDbWrapper', () => {
|
|
|
9
9
|
const getTablesUsed = (query: string) =>
|
|
10
10
|
Effect.gen(function* () {
|
|
11
11
|
const store = yield* makeTodoMvc({})
|
|
12
|
-
return store.sqliteDbWrapper.getTablesUsed(query)
|
|
12
|
+
return store[StoreInternalsSymbol].sqliteDbWrapper.getTablesUsed(query)
|
|
13
13
|
})
|
|
14
14
|
|
|
15
15
|
Vitest.scopedLive('should return the correct tables used', (_test) =>
|
|
@@ -87,6 +87,93 @@ exports[`otel > QueryBuilder subscription - async iterator 2`] = `
|
|
|
87
87
|
]
|
|
88
88
|
`;
|
|
89
89
|
|
|
90
|
+
exports[`otel > QueryBuilder subscription - async iterator with skipInitialRun 1`] = `
|
|
91
|
+
{
|
|
92
|
+
"_name": "createStore",
|
|
93
|
+
"attributes": {
|
|
94
|
+
"debugInstanceId": "test",
|
|
95
|
+
"storeId": "default",
|
|
96
|
+
},
|
|
97
|
+
"children": [
|
|
98
|
+
{
|
|
99
|
+
"_name": "livestore.in-memory-db:execute",
|
|
100
|
+
"attributes": {
|
|
101
|
+
"sql.query": "
|
|
102
|
+
PRAGMA page_size=32768;
|
|
103
|
+
PRAGMA cache_size=10000;
|
|
104
|
+
PRAGMA synchronous='OFF';
|
|
105
|
+
PRAGMA temp_store='MEMORY';
|
|
106
|
+
PRAGMA foreign_keys='ON'; -- we want foreign key constraints to be enforced
|
|
107
|
+
",
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"_name": "@livestore/common:LeaderSyncProcessor:push",
|
|
112
|
+
"attributes": {
|
|
113
|
+
"batch": "undefined",
|
|
114
|
+
"batchSize": 1,
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
"_name": "client-session-sync-processor:pull",
|
|
119
|
+
"attributes": {
|
|
120
|
+
"code.stacktrace": "<STACKTRACE>",
|
|
121
|
+
"span.label": "⚠︎ Interrupted",
|
|
122
|
+
"status.interrupted": true,
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
"_name": "LiveStore:sync",
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"_name": "LiveStore:commits",
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
"_name": "LiveStore:queries",
|
|
133
|
+
},
|
|
134
|
+
],
|
|
135
|
+
}
|
|
136
|
+
`;
|
|
137
|
+
|
|
138
|
+
exports[`otel > QueryBuilder subscription - async iterator with skipInitialRun 2`] = `
|
|
139
|
+
[
|
|
140
|
+
{
|
|
141
|
+
"_name": "LiveStore:commit",
|
|
142
|
+
"attributes": {
|
|
143
|
+
"livestore.eventTags": "[
|
|
144
|
+
"todo.created"
|
|
145
|
+
]",
|
|
146
|
+
"livestore.eventsCount": 1,
|
|
147
|
+
},
|
|
148
|
+
"children": [
|
|
149
|
+
{
|
|
150
|
+
"_name": "client-session-sync-processor:push",
|
|
151
|
+
"attributes": {
|
|
152
|
+
"batchSize": 1,
|
|
153
|
+
"eventCounts": "{
|
|
154
|
+
"todo.created": 1
|
|
155
|
+
}",
|
|
156
|
+
"mergeResultTag": "advance",
|
|
157
|
+
},
|
|
158
|
+
"children": [
|
|
159
|
+
{
|
|
160
|
+
"_name": "client-session-sync-processor:materialize-event",
|
|
161
|
+
"children": [
|
|
162
|
+
{
|
|
163
|
+
"_name": "livestore.in-memory-db:execute",
|
|
164
|
+
"attributes": {
|
|
165
|
+
"sql.query": "INSERT INTO 'todos' (id, text, completed) VALUES (?, ?, ?)",
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
],
|
|
169
|
+
},
|
|
170
|
+
],
|
|
171
|
+
},
|
|
172
|
+
],
|
|
173
|
+
},
|
|
174
|
+
]
|
|
175
|
+
`;
|
|
176
|
+
|
|
90
177
|
exports[`otel > QueryBuilder subscription - basic functionality 1`] = `
|
|
91
178
|
{
|
|
92
179
|
"_name": "createStore",
|
|
@@ -353,6 +440,139 @@ exports[`otel > QueryBuilder subscription - direct table subscription 2`] = `
|
|
|
353
440
|
]
|
|
354
441
|
`;
|
|
355
442
|
|
|
443
|
+
exports[`otel > QueryBuilder subscription - skipInitialRun 1`] = `
|
|
444
|
+
{
|
|
445
|
+
"_name": "createStore",
|
|
446
|
+
"attributes": {
|
|
447
|
+
"debugInstanceId": "test",
|
|
448
|
+
"storeId": "default",
|
|
449
|
+
},
|
|
450
|
+
"children": [
|
|
451
|
+
{
|
|
452
|
+
"_name": "livestore.in-memory-db:execute",
|
|
453
|
+
"attributes": {
|
|
454
|
+
"sql.query": "
|
|
455
|
+
PRAGMA page_size=32768;
|
|
456
|
+
PRAGMA cache_size=10000;
|
|
457
|
+
PRAGMA synchronous='OFF';
|
|
458
|
+
PRAGMA temp_store='MEMORY';
|
|
459
|
+
PRAGMA foreign_keys='ON'; -- we want foreign key constraints to be enforced
|
|
460
|
+
",
|
|
461
|
+
},
|
|
462
|
+
},
|
|
463
|
+
{
|
|
464
|
+
"_name": "@livestore/common:LeaderSyncProcessor:push",
|
|
465
|
+
"attributes": {
|
|
466
|
+
"batch": "undefined",
|
|
467
|
+
"batchSize": 1,
|
|
468
|
+
},
|
|
469
|
+
},
|
|
470
|
+
{
|
|
471
|
+
"_name": "client-session-sync-processor:pull",
|
|
472
|
+
"attributes": {
|
|
473
|
+
"code.stacktrace": "<STACKTRACE>",
|
|
474
|
+
"span.label": "⚠︎ Interrupted",
|
|
475
|
+
"status.interrupted": true,
|
|
476
|
+
},
|
|
477
|
+
},
|
|
478
|
+
{
|
|
479
|
+
"_name": "LiveStore:sync",
|
|
480
|
+
},
|
|
481
|
+
{
|
|
482
|
+
"_name": "LiveStore:commits",
|
|
483
|
+
},
|
|
484
|
+
{
|
|
485
|
+
"_name": "LiveStore:queries",
|
|
486
|
+
"children": [
|
|
487
|
+
{
|
|
488
|
+
"_name": "LiveStore.subscribe",
|
|
489
|
+
"attributes": {
|
|
490
|
+
"queryLabel": "SELECT * FROM 'todos' WHERE completed = ? LIMIT ?",
|
|
491
|
+
},
|
|
492
|
+
"children": [
|
|
493
|
+
{
|
|
494
|
+
"_name": "db:SELECT * FROM 'todos' WHERE completed = ? LIMIT ?",
|
|
495
|
+
"attributes": {
|
|
496
|
+
"livestore.debugRefreshReason": "subscribe-initial-run:undefined",
|
|
497
|
+
"sql.query": "SELECT * FROM 'todos' WHERE completed = ? LIMIT ?",
|
|
498
|
+
"sql.rowsCount": 0,
|
|
499
|
+
},
|
|
500
|
+
"children": [
|
|
501
|
+
{
|
|
502
|
+
"_name": "sql-in-memory-select",
|
|
503
|
+
"attributes": {
|
|
504
|
+
"sql.cached": false,
|
|
505
|
+
"sql.query": "SELECT * FROM 'todos' WHERE completed = ? LIMIT ?",
|
|
506
|
+
"sql.rowsCount": 0,
|
|
507
|
+
},
|
|
508
|
+
},
|
|
509
|
+
],
|
|
510
|
+
},
|
|
511
|
+
{
|
|
512
|
+
"_name": "db:SELECT * FROM 'todos' WHERE completed = ? LIMIT ?",
|
|
513
|
+
"attributes": {
|
|
514
|
+
"livestore.debugRefreshReason": "commit",
|
|
515
|
+
"sql.query": "SELECT * FROM 'todos' WHERE completed = ? LIMIT ?",
|
|
516
|
+
"sql.rowsCount": 1,
|
|
517
|
+
},
|
|
518
|
+
"children": [
|
|
519
|
+
{
|
|
520
|
+
"_name": "sql-in-memory-select",
|
|
521
|
+
"attributes": {
|
|
522
|
+
"sql.cached": false,
|
|
523
|
+
"sql.query": "SELECT * FROM 'todos' WHERE completed = ? LIMIT ?",
|
|
524
|
+
"sql.rowsCount": 1,
|
|
525
|
+
},
|
|
526
|
+
},
|
|
527
|
+
],
|
|
528
|
+
},
|
|
529
|
+
],
|
|
530
|
+
},
|
|
531
|
+
],
|
|
532
|
+
},
|
|
533
|
+
],
|
|
534
|
+
}
|
|
535
|
+
`;
|
|
536
|
+
|
|
537
|
+
exports[`otel > QueryBuilder subscription - skipInitialRun 2`] = `
|
|
538
|
+
[
|
|
539
|
+
{
|
|
540
|
+
"_name": "LiveStore:commit",
|
|
541
|
+
"attributes": {
|
|
542
|
+
"livestore.eventTags": "[
|
|
543
|
+
"todo.created"
|
|
544
|
+
]",
|
|
545
|
+
"livestore.eventsCount": 1,
|
|
546
|
+
},
|
|
547
|
+
"children": [
|
|
548
|
+
{
|
|
549
|
+
"_name": "client-session-sync-processor:push",
|
|
550
|
+
"attributes": {
|
|
551
|
+
"batchSize": 1,
|
|
552
|
+
"eventCounts": "{
|
|
553
|
+
"todo.created": 1
|
|
554
|
+
}",
|
|
555
|
+
"mergeResultTag": "advance",
|
|
556
|
+
},
|
|
557
|
+
"children": [
|
|
558
|
+
{
|
|
559
|
+
"_name": "client-session-sync-processor:materialize-event",
|
|
560
|
+
"children": [
|
|
561
|
+
{
|
|
562
|
+
"_name": "livestore.in-memory-db:execute",
|
|
563
|
+
"attributes": {
|
|
564
|
+
"sql.query": "INSERT INTO 'todos' (id, text, completed) VALUES (?, ?, ?)",
|
|
565
|
+
},
|
|
566
|
+
},
|
|
567
|
+
],
|
|
568
|
+
},
|
|
569
|
+
],
|
|
570
|
+
},
|
|
571
|
+
],
|
|
572
|
+
},
|
|
573
|
+
]
|
|
574
|
+
`;
|
|
575
|
+
|
|
356
576
|
exports[`otel > QueryBuilder subscription - unsubscribe functionality 1`] = `
|
|
357
577
|
{
|
|
358
578
|
"_name": "createStore",
|
|
@@ -3,7 +3,7 @@ import { SessionIdSymbol } from '@livestore/common'
|
|
|
3
3
|
import { State } from '@livestore/common/schema'
|
|
4
4
|
import { shouldNeverHappen } from '@livestore/utils'
|
|
5
5
|
import type * as otel from '@opentelemetry/api'
|
|
6
|
-
|
|
6
|
+
import { StoreInternalsSymbol } from '../store/store-types.ts'
|
|
7
7
|
import type { ReactivityGraphContext } from './base-class.ts'
|
|
8
8
|
|
|
9
9
|
export const rowQueryLabel = (
|
|
@@ -30,11 +30,11 @@ export const makeExecBeforeFirstRun =
|
|
|
30
30
|
)
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
const otelContext = otelContext_ ?? store.otel.queriesSpanContext
|
|
33
|
+
const otelContext = otelContext_ ?? store[StoreInternalsSymbol].otel.queriesSpanContext
|
|
34
34
|
|
|
35
35
|
const idVal = id === SessionIdSymbol ? store.sessionId : id!
|
|
36
36
|
const rowExists =
|
|
37
|
-
store.sqliteDbWrapper.cachedSelect(
|
|
37
|
+
store[StoreInternalsSymbol].sqliteDbWrapper.cachedSelect(
|
|
38
38
|
`SELECT 1 FROM '${table.sqliteDef.name}' WHERE id = ?`,
|
|
39
39
|
[idVal] as any as PreparedBindValues,
|
|
40
40
|
{ otelContext },
|
|
@@ -5,7 +5,8 @@ import { BasicTracerProvider, InMemorySpanExporter, SimpleSpanProcessor } from '
|
|
|
5
5
|
import { assert, expect } from 'vitest'
|
|
6
6
|
|
|
7
7
|
import * as RG from '../reactive.ts'
|
|
8
|
-
import {
|
|
8
|
+
import { StoreInternalsSymbol } from '../store/store-types.ts'
|
|
9
|
+
import { events, makeTodoMvc, type Todo, tables } from '../utils/tests/fixture.ts'
|
|
9
10
|
import { getAllSimplifiedRootSpans, getSimplifiedRootSpan } from '../utils/tests/otel.ts'
|
|
10
11
|
import { computed } from './computed.ts'
|
|
11
12
|
import { queryDb } from './db-query.ts'
|
|
@@ -106,7 +107,7 @@ Vitest.describe('otel', () => {
|
|
|
106
107
|
{ label: 'all todos' },
|
|
107
108
|
)
|
|
108
109
|
|
|
109
|
-
expect(store.reactivityGraph.getSnapshot({ includeResults: true })).toMatchSnapshot()
|
|
110
|
+
expect(store[StoreInternalsSymbol].reactivityGraph.getSnapshot({ includeResults: true })).toMatchSnapshot()
|
|
110
111
|
|
|
111
112
|
expect(store.query(query$)).toMatchInlineSnapshot(`
|
|
112
113
|
{
|
|
@@ -116,11 +117,11 @@ Vitest.describe('otel', () => {
|
|
|
116
117
|
}
|
|
117
118
|
`)
|
|
118
119
|
|
|
119
|
-
expect(store.reactivityGraph.getSnapshot({ includeResults: true })).toMatchSnapshot()
|
|
120
|
+
expect(store[StoreInternalsSymbol].reactivityGraph.getSnapshot({ includeResults: true })).toMatchSnapshot()
|
|
120
121
|
|
|
121
122
|
store.commit(events.todoCreated({ id: 't1', text: 'buy milk', completed: false }))
|
|
122
123
|
|
|
123
|
-
expect(store.reactivityGraph.getSnapshot({ includeResults: true })).toMatchSnapshot()
|
|
124
|
+
expect(store[StoreInternalsSymbol].reactivityGraph.getSnapshot({ includeResults: true })).toMatchSnapshot()
|
|
124
125
|
|
|
125
126
|
expect(store.query(query$)).toMatchInlineSnapshot(`
|
|
126
127
|
{
|
|
@@ -130,7 +131,7 @@ Vitest.describe('otel', () => {
|
|
|
130
131
|
}
|
|
131
132
|
`)
|
|
132
133
|
|
|
133
|
-
expect(store.reactivityGraph.getSnapshot({ includeResults: true })).toMatchSnapshot()
|
|
134
|
+
expect(store[StoreInternalsSymbol].reactivityGraph.getSnapshot({ includeResults: true })).toMatchSnapshot()
|
|
134
135
|
|
|
135
136
|
span.end()
|
|
136
137
|
|
|
@@ -237,6 +238,53 @@ Vitest.describe('otel', () => {
|
|
|
237
238
|
),
|
|
238
239
|
)
|
|
239
240
|
|
|
241
|
+
Vitest.scopedLive('QueryBuilder subscription - skipInitialRun', () =>
|
|
242
|
+
Effect.gen(function* () {
|
|
243
|
+
const { store, exporter, span, provider } = yield* makeQuery
|
|
244
|
+
|
|
245
|
+
const callbackResults: Todo[] = []
|
|
246
|
+
const defaultTodo: Todo = { id: '', text: '', completed: false }
|
|
247
|
+
|
|
248
|
+
const queryBuilder = tables.todos
|
|
249
|
+
.where({ completed: false })
|
|
250
|
+
.first({ behaviour: 'fallback', fallback: () => defaultTodo })
|
|
251
|
+
|
|
252
|
+
const unsubscribe = store.subscribe(
|
|
253
|
+
queryBuilder,
|
|
254
|
+
(result) => {
|
|
255
|
+
callbackResults.push(result)
|
|
256
|
+
},
|
|
257
|
+
{ skipInitialRun: true },
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
expect(callbackResults).toHaveLength(0)
|
|
261
|
+
|
|
262
|
+
store.commit(events.todoCreated({ id: 't-skip', text: 'skip initial', completed: false }))
|
|
263
|
+
|
|
264
|
+
expect(callbackResults).toHaveLength(1)
|
|
265
|
+
expect(callbackResults[0]).toMatchObject({
|
|
266
|
+
id: 't-skip',
|
|
267
|
+
text: 'skip initial',
|
|
268
|
+
completed: false,
|
|
269
|
+
})
|
|
270
|
+
|
|
271
|
+
unsubscribe()
|
|
272
|
+
span.end()
|
|
273
|
+
|
|
274
|
+
return { exporter, provider }
|
|
275
|
+
}).pipe(
|
|
276
|
+
Effect.scoped,
|
|
277
|
+
Effect.tap(({ exporter, provider }) =>
|
|
278
|
+
Effect.promise(async () => {
|
|
279
|
+
await provider.forceFlush()
|
|
280
|
+
expect(getSimplifiedRootSpan(exporter, 'createStore', mapAttributes)).toMatchSnapshot()
|
|
281
|
+
expect(getAllSimplifiedRootSpans(exporter, 'LiveStore:commit', mapAttributes)).toMatchSnapshot()
|
|
282
|
+
await provider.shutdown()
|
|
283
|
+
}),
|
|
284
|
+
),
|
|
285
|
+
),
|
|
286
|
+
)
|
|
287
|
+
|
|
240
288
|
Vitest.scopedLive('QueryBuilder subscription - unsubscribe functionality', () =>
|
|
241
289
|
Effect.gen(function* () {
|
|
242
290
|
const { store, exporter, span, provider } = yield* makeQuery
|
|
@@ -293,7 +341,7 @@ Vitest.describe('otel', () => {
|
|
|
293
341
|
Effect.gen(function* () {
|
|
294
342
|
const { store, exporter, span, provider } = yield* makeQuery
|
|
295
343
|
|
|
296
|
-
const defaultTodo = { id: '', text: '', completed: false }
|
|
344
|
+
const defaultTodo: Todo = { id: '', text: '', completed: false }
|
|
297
345
|
|
|
298
346
|
const queryBuilder = tables.todos
|
|
299
347
|
.where({ completed: false })
|
|
@@ -337,6 +385,55 @@ Vitest.describe('otel', () => {
|
|
|
337
385
|
),
|
|
338
386
|
)
|
|
339
387
|
|
|
388
|
+
Vitest.scopedLive('QueryBuilder subscription - async iterator with skipInitialRun', () =>
|
|
389
|
+
Effect.gen(function* () {
|
|
390
|
+
const { store, exporter, span, provider } = yield* makeQuery
|
|
391
|
+
|
|
392
|
+
const defaultTodo: Todo = { id: '', text: '', completed: false }
|
|
393
|
+
|
|
394
|
+
const queryBuilder = tables.todos
|
|
395
|
+
.where({ completed: false })
|
|
396
|
+
.first({ behaviour: 'fallback', fallback: () => defaultTodo })
|
|
397
|
+
|
|
398
|
+
yield* Effect.promise(async () => {
|
|
399
|
+
const iterator = store.subscribe(queryBuilder, { skipInitialRun: true })[Symbol.asyncIterator]()
|
|
400
|
+
|
|
401
|
+
const pending = Symbol('pending')
|
|
402
|
+
const nextPromise = iterator.next()
|
|
403
|
+
const raceResult = await Promise.race([nextPromise, Promise.resolve(pending)])
|
|
404
|
+
expect(raceResult).toBe(pending)
|
|
405
|
+
|
|
406
|
+
store.commit(events.todoCreated({ id: 't-async-skip', text: 'write tests later', completed: false }))
|
|
407
|
+
|
|
408
|
+
const update = await nextPromise
|
|
409
|
+
expect(update.done).toBe(false)
|
|
410
|
+
expect(update.value).toMatchObject({
|
|
411
|
+
id: 't-async-skip',
|
|
412
|
+
text: 'write tests later',
|
|
413
|
+
completed: false,
|
|
414
|
+
})
|
|
415
|
+
|
|
416
|
+
const doneResult = await iterator.return?.()
|
|
417
|
+
assert(doneResult)
|
|
418
|
+
expect(doneResult.done).toBe(true)
|
|
419
|
+
})
|
|
420
|
+
|
|
421
|
+
span.end()
|
|
422
|
+
|
|
423
|
+
return { exporter, provider }
|
|
424
|
+
}).pipe(
|
|
425
|
+
Effect.scoped,
|
|
426
|
+
Effect.tap(({ exporter, provider }) =>
|
|
427
|
+
Effect.promise(async () => {
|
|
428
|
+
await provider.forceFlush()
|
|
429
|
+
expect(getSimplifiedRootSpan(exporter, 'createStore', mapAttributes)).toMatchSnapshot()
|
|
430
|
+
expect(getAllSimplifiedRootSpans(exporter, 'LiveStore:commit', mapAttributes)).toMatchSnapshot()
|
|
431
|
+
await provider.shutdown()
|
|
432
|
+
}),
|
|
433
|
+
),
|
|
434
|
+
),
|
|
435
|
+
)
|
|
436
|
+
|
|
340
437
|
Vitest.scopedLive('QueryBuilder subscription - direct table subscription', () =>
|
|
341
438
|
Effect.gen(function* () {
|
|
342
439
|
const { store, exporter, span, provider } = yield* makeQuery
|
|
@@ -16,6 +16,7 @@ import * as otel from '@opentelemetry/api'
|
|
|
16
16
|
import type { Thunk } from '../reactive.ts'
|
|
17
17
|
import { isThunk, NOT_REFRESHED_YET } from '../reactive.ts'
|
|
18
18
|
import type { RefreshReason } from '../store/store-types.ts'
|
|
19
|
+
import { StoreInternalsSymbol } from '../store/store-types.ts'
|
|
19
20
|
import { isValidFunctionString } from '../utils/function-string.ts'
|
|
20
21
|
import type { DepKey, GetAtomResult, LiveQueryDef, ReactivityGraph, ReactivityGraphContext } from './base-class.ts'
|
|
21
22
|
import { depsToString, LiveStoreQueryBase, makeGetAtomResult, withRCMap } from './base-class.ts'
|
|
@@ -364,23 +365,25 @@ export class LiveStoreDbQuery<TResultSchema, TResult = TResultSchema> extends Li
|
|
|
364
365
|
const bindValues = queryInputResult.bindValues
|
|
365
366
|
|
|
366
367
|
if (queriedTablesRef.current === undefined) {
|
|
367
|
-
queriedTablesRef.current = store.sqliteDbWrapper.getTablesUsed(sqlString)
|
|
368
|
+
queriedTablesRef.current = store[StoreInternalsSymbol].sqliteDbWrapper.getTablesUsed(sqlString)
|
|
368
369
|
}
|
|
369
370
|
|
|
370
371
|
if (bindValues !== undefined) {
|
|
371
|
-
replaceSessionIdSymbol(bindValues, store.
|
|
372
|
+
replaceSessionIdSymbol(bindValues, store.sessionId)
|
|
372
373
|
}
|
|
373
374
|
|
|
374
375
|
// Establish a reactive dependency on the tables used in the query
|
|
375
376
|
for (const tableName of queriedTablesRef.current) {
|
|
376
|
-
const tableRef =
|
|
377
|
+
const tableRef =
|
|
378
|
+
store[StoreInternalsSymbol].tableRefs[tableName] ??
|
|
379
|
+
shouldNeverHappen(`No table ref found for ${tableName}`)
|
|
377
380
|
get(tableRef, otelContext, debugRefreshReason)
|
|
378
381
|
}
|
|
379
382
|
|
|
380
383
|
span.setAttribute('sql.query', sqlString)
|
|
381
384
|
span.updateName(`db:${sqlString.slice(0, 50)}`)
|
|
382
385
|
|
|
383
|
-
const rawDbResults = store.sqliteDbWrapper.cachedSelect<any>(
|
|
386
|
+
const rawDbResults = store[StoreInternalsSymbol].sqliteDbWrapper.cachedSelect<any>(
|
|
384
387
|
sqlString,
|
|
385
388
|
bindValues ? prepareBindValues(bindValues, sqlString) : undefined,
|
|
386
389
|
{
|
package/src/mod.ts
CHANGED
|
@@ -37,20 +37,20 @@ export {
|
|
|
37
37
|
export { emptyDebugInfo, SqliteDbWrapper } from './SqliteDbWrapper.ts'
|
|
38
38
|
export { type CreateStoreOptions, createStore, createStorePromise } from './store/create-store.ts'
|
|
39
39
|
export { Store } from './store/store.ts'
|
|
40
|
-
export type {
|
|
41
|
-
OtelOptions,
|
|
42
|
-
Queryable,
|
|
43
|
-
QueryDebugInfo,
|
|
44
|
-
RefreshReason,
|
|
45
|
-
SubscribeOptions,
|
|
46
|
-
Unsubscribe,
|
|
47
|
-
} from './store/store-types.ts'
|
|
48
40
|
export {
|
|
49
41
|
isQueryable,
|
|
50
42
|
type LiveStoreContext,
|
|
51
43
|
type LiveStoreContextRunning,
|
|
52
44
|
makeShutdownDeferred,
|
|
45
|
+
type OtelOptions,
|
|
46
|
+
type Queryable,
|
|
47
|
+
type QueryDebugInfo,
|
|
48
|
+
type RefreshReason,
|
|
53
49
|
type ShutdownDeferred,
|
|
50
|
+
type StoreInternals,
|
|
51
|
+
StoreInternalsSymbol,
|
|
52
|
+
type SubscribeOptions,
|
|
53
|
+
type Unsubscribe,
|
|
54
54
|
} from './store/store-types.ts'
|
|
55
55
|
export { exposeDebugUtils } from './utils/dev.ts'
|
|
56
56
|
export * from './utils/stack-info.ts'
|
|
@@ -41,6 +41,7 @@ import type {
|
|
|
41
41
|
OtelOptions,
|
|
42
42
|
ShutdownDeferred,
|
|
43
43
|
} from './store-types.ts'
|
|
44
|
+
import { StoreInternalsSymbol } from './store-types.ts'
|
|
44
45
|
|
|
45
46
|
export const DEFAULT_PARAMS = {
|
|
46
47
|
leaderPushBatchSize: 100,
|
|
@@ -346,7 +347,7 @@ export const createStore = <
|
|
|
346
347
|
})
|
|
347
348
|
|
|
348
349
|
// Starts background fibers (syncing, event processing, etc) for store
|
|
349
|
-
yield* store.boot
|
|
350
|
+
yield* store[StoreInternalsSymbol].boot
|
|
350
351
|
|
|
351
352
|
if (boot !== undefined) {
|
|
352
353
|
// TODO also incorporate `boot` function progress into `bootStatusQueue`
|
|
@@ -364,7 +365,7 @@ export const createStore = <
|
|
|
364
365
|
|
|
365
366
|
if (batchUpdates !== undefined) {
|
|
366
367
|
// Replacing the default batchUpdates function with the provided one after boot
|
|
367
|
-
store.reactivityGraph.context!.effectsWrapper = batchUpdates
|
|
368
|
+
store[StoreInternalsSymbol].reactivityGraph.context!.effectsWrapper = batchUpdates
|
|
368
369
|
}
|
|
369
370
|
|
|
370
371
|
yield* Deferred.succeed(storeDeferred, store as any as Store)
|