@livestore/livestore 0.4.0-dev.3 → 0.4.0-dev.5
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/live-queries/db-query.test.js +13 -7
- package/dist/live-queries/db-query.test.js.map +1 -1
- package/dist/mod.d.ts +1 -1
- package/dist/mod.d.ts.map +1 -1
- package/dist/mod.js.map +1 -1
- package/dist/reactive.d.ts.map +1 -1
- package/dist/reactive.js +19 -10
- package/dist/reactive.js.map +1 -1
- package/dist/reactive.test.js +80 -0
- package/dist/reactive.test.js.map +1 -1
- package/dist/store/create-store.d.ts.map +1 -1
- package/dist/store/create-store.js.map +1 -1
- package/dist/store/store-types.d.ts +2 -2
- package/dist/store/store-types.d.ts.map +1 -1
- package/dist/store/store-types.js.map +1 -1
- package/dist/store/store.d.ts +3 -2
- package/dist/store/store.d.ts.map +1 -1
- package/dist/store/store.js +82 -81
- package/dist/store/store.js.map +1 -1
- package/dist/utils/tests/otel.d.ts +2 -1
- package/dist/utils/tests/otel.d.ts.map +1 -1
- package/dist/utils/tests/otel.js +18 -14
- package/dist/utils/tests/otel.js.map +1 -1
- package/package.json +6 -6
- package/src/live-queries/__snapshots__/db-query.test.ts.snap +268 -131
- package/src/live-queries/db-query.test.ts +13 -7
- package/src/mod.ts +1 -0
- package/src/reactive.test.ts +100 -0
- package/src/reactive.ts +19 -10
- package/src/store/create-store.ts +9 -1
- package/src/store/store-types.ts +5 -2
- package/src/store/store.ts +148 -140
- package/src/utils/tests/otel.ts +29 -19
@@ -40,25 +40,6 @@ exports[`otel > QueryBuilder subscription - basic functionality 1`] = `
|
|
40
40
|
},
|
41
41
|
{
|
42
42
|
"_name": "LiveStore:commits",
|
43
|
-
"children": [
|
44
|
-
{
|
45
|
-
"_name": "LiveStore:commit",
|
46
|
-
"attributes": {
|
47
|
-
"livestore.eventTags": [
|
48
|
-
"todo.created",
|
49
|
-
],
|
50
|
-
"livestore.eventsCount": 1,
|
51
|
-
},
|
52
|
-
"children": [
|
53
|
-
{
|
54
|
-
"_name": "livestore.in-memory-db:execute",
|
55
|
-
"attributes": {
|
56
|
-
"sql.query": "INSERT INTO 'todos' (id, text, completed) VALUES (?, ?, ?)",
|
57
|
-
},
|
58
|
-
},
|
59
|
-
],
|
60
|
-
},
|
61
|
-
],
|
62
43
|
},
|
63
44
|
{
|
64
45
|
"_name": "LiveStore:queries",
|
@@ -113,6 +94,45 @@ exports[`otel > QueryBuilder subscription - basic functionality 1`] = `
|
|
113
94
|
}
|
114
95
|
`;
|
115
96
|
|
97
|
+
exports[`otel > QueryBuilder subscription - basic functionality 2`] = `
|
98
|
+
[
|
99
|
+
{
|
100
|
+
"_name": "LiveStore:commit",
|
101
|
+
"attributes": {
|
102
|
+
"livestore.eventTags": "[
|
103
|
+
"todo.created"
|
104
|
+
]",
|
105
|
+
"livestore.eventsCount": 1,
|
106
|
+
},
|
107
|
+
"children": [
|
108
|
+
{
|
109
|
+
"_name": "client-session-sync-processor:push",
|
110
|
+
"attributes": {
|
111
|
+
"batchSize": 1,
|
112
|
+
"eventCounts": "{
|
113
|
+
"todo.created": 1
|
114
|
+
}",
|
115
|
+
"mergeResultTag": "advance",
|
116
|
+
},
|
117
|
+
"children": [
|
118
|
+
{
|
119
|
+
"_name": "client-session-sync-processor:materialize-event",
|
120
|
+
"children": [
|
121
|
+
{
|
122
|
+
"_name": "livestore.in-memory-db:execute",
|
123
|
+
"attributes": {
|
124
|
+
"sql.query": "INSERT INTO 'todos' (id, text, completed) VALUES (?, ?, ?)",
|
125
|
+
},
|
126
|
+
},
|
127
|
+
],
|
128
|
+
},
|
129
|
+
],
|
130
|
+
},
|
131
|
+
],
|
132
|
+
},
|
133
|
+
]
|
134
|
+
`;
|
135
|
+
|
116
136
|
exports[`otel > QueryBuilder subscription - direct table subscription 1`] = `
|
117
137
|
{
|
118
138
|
"_name": "createStore",
|
@@ -153,25 +173,6 @@ exports[`otel > QueryBuilder subscription - direct table subscription 1`] = `
|
|
153
173
|
},
|
154
174
|
{
|
155
175
|
"_name": "LiveStore:commits",
|
156
|
-
"children": [
|
157
|
-
{
|
158
|
-
"_name": "LiveStore:commit",
|
159
|
-
"attributes": {
|
160
|
-
"livestore.eventTags": [
|
161
|
-
"todo.created",
|
162
|
-
],
|
163
|
-
"livestore.eventsCount": 1,
|
164
|
-
},
|
165
|
-
"children": [
|
166
|
-
{
|
167
|
-
"_name": "livestore.in-memory-db:execute",
|
168
|
-
"attributes": {
|
169
|
-
"sql.query": "INSERT INTO 'todos' (id, text, completed) VALUES (?, ?, ?)",
|
170
|
-
},
|
171
|
-
},
|
172
|
-
],
|
173
|
-
},
|
174
|
-
],
|
175
176
|
},
|
176
177
|
{
|
177
178
|
"_name": "LiveStore:queries",
|
@@ -226,6 +227,45 @@ exports[`otel > QueryBuilder subscription - direct table subscription 1`] = `
|
|
226
227
|
}
|
227
228
|
`;
|
228
229
|
|
230
|
+
exports[`otel > QueryBuilder subscription - direct table subscription 2`] = `
|
231
|
+
[
|
232
|
+
{
|
233
|
+
"_name": "LiveStore:commit",
|
234
|
+
"attributes": {
|
235
|
+
"livestore.eventTags": "[
|
236
|
+
"todo.created"
|
237
|
+
]",
|
238
|
+
"livestore.eventsCount": 1,
|
239
|
+
},
|
240
|
+
"children": [
|
241
|
+
{
|
242
|
+
"_name": "client-session-sync-processor:push",
|
243
|
+
"attributes": {
|
244
|
+
"batchSize": 1,
|
245
|
+
"eventCounts": "{
|
246
|
+
"todo.created": 1
|
247
|
+
}",
|
248
|
+
"mergeResultTag": "advance",
|
249
|
+
},
|
250
|
+
"children": [
|
251
|
+
{
|
252
|
+
"_name": "client-session-sync-processor:materialize-event",
|
253
|
+
"children": [
|
254
|
+
{
|
255
|
+
"_name": "livestore.in-memory-db:execute",
|
256
|
+
"attributes": {
|
257
|
+
"sql.query": "INSERT INTO 'todos' (id, text, completed) VALUES (?, ?, ?)",
|
258
|
+
},
|
259
|
+
},
|
260
|
+
],
|
261
|
+
},
|
262
|
+
],
|
263
|
+
},
|
264
|
+
],
|
265
|
+
},
|
266
|
+
]
|
267
|
+
`;
|
268
|
+
|
229
269
|
exports[`otel > QueryBuilder subscription - unsubscribe functionality 1`] = `
|
230
270
|
{
|
231
271
|
"_name": "createStore",
|
@@ -273,42 +313,6 @@ exports[`otel > QueryBuilder subscription - unsubscribe functionality 1`] = `
|
|
273
313
|
},
|
274
314
|
{
|
275
315
|
"_name": "LiveStore:commits",
|
276
|
-
"children": [
|
277
|
-
{
|
278
|
-
"_name": "LiveStore:commit",
|
279
|
-
"attributes": {
|
280
|
-
"livestore.eventTags": [
|
281
|
-
"todo.created",
|
282
|
-
],
|
283
|
-
"livestore.eventsCount": 1,
|
284
|
-
},
|
285
|
-
"children": [
|
286
|
-
{
|
287
|
-
"_name": "livestore.in-memory-db:execute",
|
288
|
-
"attributes": {
|
289
|
-
"sql.query": "INSERT INTO 'todos' (id, text, completed) VALUES (?, ?, ?)",
|
290
|
-
},
|
291
|
-
},
|
292
|
-
],
|
293
|
-
},
|
294
|
-
{
|
295
|
-
"_name": "LiveStore:commit",
|
296
|
-
"attributes": {
|
297
|
-
"livestore.eventTags": [
|
298
|
-
"todo.created",
|
299
|
-
],
|
300
|
-
"livestore.eventsCount": 1,
|
301
|
-
},
|
302
|
-
"children": [
|
303
|
-
{
|
304
|
-
"_name": "livestore.in-memory-db:execute",
|
305
|
-
"attributes": {
|
306
|
-
"sql.query": "INSERT INTO 'todos' (id, text, completed) VALUES (?, ?, ?)",
|
307
|
-
},
|
308
|
-
},
|
309
|
-
],
|
310
|
-
},
|
311
|
-
],
|
312
316
|
},
|
313
317
|
{
|
314
318
|
"_name": "LiveStore:queries",
|
@@ -389,6 +393,79 @@ exports[`otel > QueryBuilder subscription - unsubscribe functionality 1`] = `
|
|
389
393
|
}
|
390
394
|
`;
|
391
395
|
|
396
|
+
exports[`otel > QueryBuilder subscription - unsubscribe functionality 2`] = `
|
397
|
+
[
|
398
|
+
{
|
399
|
+
"_name": "LiveStore:commit",
|
400
|
+
"attributes": {
|
401
|
+
"livestore.eventTags": "[
|
402
|
+
"todo.created"
|
403
|
+
]",
|
404
|
+
"livestore.eventsCount": 1,
|
405
|
+
},
|
406
|
+
"children": [
|
407
|
+
{
|
408
|
+
"_name": "client-session-sync-processor:push",
|
409
|
+
"attributes": {
|
410
|
+
"batchSize": 1,
|
411
|
+
"eventCounts": "{
|
412
|
+
"todo.created": 1
|
413
|
+
}",
|
414
|
+
"mergeResultTag": "advance",
|
415
|
+
},
|
416
|
+
"children": [
|
417
|
+
{
|
418
|
+
"_name": "client-session-sync-processor:materialize-event",
|
419
|
+
"children": [
|
420
|
+
{
|
421
|
+
"_name": "livestore.in-memory-db:execute",
|
422
|
+
"attributes": {
|
423
|
+
"sql.query": "INSERT INTO 'todos' (id, text, completed) VALUES (?, ?, ?)",
|
424
|
+
},
|
425
|
+
},
|
426
|
+
],
|
427
|
+
},
|
428
|
+
],
|
429
|
+
},
|
430
|
+
],
|
431
|
+
},
|
432
|
+
{
|
433
|
+
"_name": "LiveStore:commit",
|
434
|
+
"attributes": {
|
435
|
+
"livestore.eventTags": "[
|
436
|
+
"todo.created"
|
437
|
+
]",
|
438
|
+
"livestore.eventsCount": 1,
|
439
|
+
},
|
440
|
+
"children": [
|
441
|
+
{
|
442
|
+
"_name": "client-session-sync-processor:push",
|
443
|
+
"attributes": {
|
444
|
+
"batchSize": 1,
|
445
|
+
"eventCounts": "{
|
446
|
+
"todo.created": 1
|
447
|
+
}",
|
448
|
+
"mergeResultTag": "advance",
|
449
|
+
},
|
450
|
+
"children": [
|
451
|
+
{
|
452
|
+
"_name": "client-session-sync-processor:materialize-event",
|
453
|
+
"children": [
|
454
|
+
{
|
455
|
+
"_name": "livestore.in-memory-db:execute",
|
456
|
+
"attributes": {
|
457
|
+
"sql.query": "INSERT INTO 'todos' (id, text, completed) VALUES (?, ?, ?)",
|
458
|
+
},
|
459
|
+
},
|
460
|
+
],
|
461
|
+
},
|
462
|
+
],
|
463
|
+
},
|
464
|
+
],
|
465
|
+
},
|
466
|
+
]
|
467
|
+
`;
|
468
|
+
|
392
469
|
exports[`otel > otel 3`] = `
|
393
470
|
{
|
394
471
|
"_name": "createStore",
|
@@ -429,25 +506,6 @@ exports[`otel > otel 3`] = `
|
|
429
506
|
},
|
430
507
|
{
|
431
508
|
"_name": "LiveStore:commits",
|
432
|
-
"children": [
|
433
|
-
{
|
434
|
-
"_name": "LiveStore:commit",
|
435
|
-
"attributes": {
|
436
|
-
"livestore.eventTags": [
|
437
|
-
"todo.created",
|
438
|
-
],
|
439
|
-
"livestore.eventsCount": 1,
|
440
|
-
},
|
441
|
-
"children": [
|
442
|
-
{
|
443
|
-
"_name": "livestore.in-memory-db:execute",
|
444
|
-
"attributes": {
|
445
|
-
"sql.query": "INSERT INTO 'todos' (id, text, completed) VALUES (?, ?, ?)",
|
446
|
-
},
|
447
|
-
},
|
448
|
-
],
|
449
|
-
},
|
450
|
-
],
|
451
509
|
},
|
452
510
|
{
|
453
511
|
"_name": "LiveStore:queries",
|
@@ -492,6 +550,45 @@ exports[`otel > otel 3`] = `
|
|
492
550
|
}
|
493
551
|
`;
|
494
552
|
|
553
|
+
exports[`otel > otel 4`] = `
|
554
|
+
[
|
555
|
+
{
|
556
|
+
"_name": "LiveStore:commit",
|
557
|
+
"attributes": {
|
558
|
+
"livestore.eventTags": "[
|
559
|
+
"todo.created"
|
560
|
+
]",
|
561
|
+
"livestore.eventsCount": 1,
|
562
|
+
},
|
563
|
+
"children": [
|
564
|
+
{
|
565
|
+
"_name": "client-session-sync-processor:push",
|
566
|
+
"attributes": {
|
567
|
+
"batchSize": 1,
|
568
|
+
"eventCounts": "{
|
569
|
+
"todo.created": 1
|
570
|
+
}",
|
571
|
+
"mergeResultTag": "advance",
|
572
|
+
},
|
573
|
+
"children": [
|
574
|
+
{
|
575
|
+
"_name": "client-session-sync-processor:materialize-event",
|
576
|
+
"children": [
|
577
|
+
{
|
578
|
+
"_name": "livestore.in-memory-db:execute",
|
579
|
+
"attributes": {
|
580
|
+
"sql.query": "INSERT INTO 'todos' (id, text, completed) VALUES (?, ?, ?)",
|
581
|
+
},
|
582
|
+
},
|
583
|
+
],
|
584
|
+
},
|
585
|
+
],
|
586
|
+
},
|
587
|
+
],
|
588
|
+
},
|
589
|
+
]
|
590
|
+
`;
|
591
|
+
|
495
592
|
exports[`otel > with thunks 1`] = `
|
496
593
|
{
|
497
594
|
"atoms": [
|
@@ -704,25 +801,6 @@ exports[`otel > with thunks 7`] = `
|
|
704
801
|
},
|
705
802
|
{
|
706
803
|
"_name": "LiveStore:commits",
|
707
|
-
"children": [
|
708
|
-
{
|
709
|
-
"_name": "LiveStore:commit",
|
710
|
-
"attributes": {
|
711
|
-
"livestore.eventTags": [
|
712
|
-
"todo.created",
|
713
|
-
],
|
714
|
-
"livestore.eventsCount": 1,
|
715
|
-
},
|
716
|
-
"children": [
|
717
|
-
{
|
718
|
-
"_name": "livestore.in-memory-db:execute",
|
719
|
-
"attributes": {
|
720
|
-
"sql.query": "INSERT INTO 'todos' (id, text, completed) VALUES (?, ?, ?)",
|
721
|
-
},
|
722
|
-
},
|
723
|
-
],
|
724
|
-
},
|
725
|
-
],
|
726
804
|
},
|
727
805
|
{
|
728
806
|
"_name": "LiveStore:queries",
|
@@ -773,6 +851,45 @@ exports[`otel > with thunks 7`] = `
|
|
773
851
|
}
|
774
852
|
`;
|
775
853
|
|
854
|
+
exports[`otel > with thunks 8`] = `
|
855
|
+
[
|
856
|
+
{
|
857
|
+
"_name": "LiveStore:commit",
|
858
|
+
"attributes": {
|
859
|
+
"livestore.eventTags": "[
|
860
|
+
"todo.created"
|
861
|
+
]",
|
862
|
+
"livestore.eventsCount": 1,
|
863
|
+
},
|
864
|
+
"children": [
|
865
|
+
{
|
866
|
+
"_name": "client-session-sync-processor:push",
|
867
|
+
"attributes": {
|
868
|
+
"batchSize": 1,
|
869
|
+
"eventCounts": "{
|
870
|
+
"todo.created": 1
|
871
|
+
}",
|
872
|
+
"mergeResultTag": "advance",
|
873
|
+
},
|
874
|
+
"children": [
|
875
|
+
{
|
876
|
+
"_name": "client-session-sync-processor:materialize-event",
|
877
|
+
"children": [
|
878
|
+
{
|
879
|
+
"_name": "livestore.in-memory-db:execute",
|
880
|
+
"attributes": {
|
881
|
+
"sql.query": "INSERT INTO 'todos' (id, text, completed) VALUES (?, ?, ?)",
|
882
|
+
},
|
883
|
+
},
|
884
|
+
],
|
885
|
+
},
|
886
|
+
],
|
887
|
+
},
|
888
|
+
],
|
889
|
+
},
|
890
|
+
]
|
891
|
+
`;
|
892
|
+
|
776
893
|
exports[`otel > with thunks with query builder and without labels 3`] = `
|
777
894
|
{
|
778
895
|
"_name": "createStore",
|
@@ -813,25 +930,6 @@ exports[`otel > with thunks with query builder and without labels 3`] = `
|
|
813
930
|
},
|
814
931
|
{
|
815
932
|
"_name": "LiveStore:commits",
|
816
|
-
"children": [
|
817
|
-
{
|
818
|
-
"_name": "LiveStore:commit",
|
819
|
-
"attributes": {
|
820
|
-
"livestore.eventTags": [
|
821
|
-
"todo.created",
|
822
|
-
],
|
823
|
-
"livestore.eventsCount": 1,
|
824
|
-
},
|
825
|
-
"children": [
|
826
|
-
{
|
827
|
-
"_name": "livestore.in-memory-db:execute",
|
828
|
-
"attributes": {
|
829
|
-
"sql.query": "INSERT INTO 'todos' (id, text, completed) VALUES (?, ?, ?)",
|
830
|
-
},
|
831
|
-
},
|
832
|
-
],
|
833
|
-
},
|
834
|
-
],
|
835
933
|
},
|
836
934
|
{
|
837
935
|
"_name": "LiveStore:queries",
|
@@ -881,3 +979,42 @@ exports[`otel > with thunks with query builder and without labels 3`] = `
|
|
881
979
|
],
|
882
980
|
}
|
883
981
|
`;
|
982
|
+
|
983
|
+
exports[`otel > with thunks with query builder and without labels 4`] = `
|
984
|
+
[
|
985
|
+
{
|
986
|
+
"_name": "LiveStore:commit",
|
987
|
+
"attributes": {
|
988
|
+
"livestore.eventTags": "[
|
989
|
+
"todo.created"
|
990
|
+
]",
|
991
|
+
"livestore.eventsCount": 1,
|
992
|
+
},
|
993
|
+
"children": [
|
994
|
+
{
|
995
|
+
"_name": "client-session-sync-processor:push",
|
996
|
+
"attributes": {
|
997
|
+
"batchSize": 1,
|
998
|
+
"eventCounts": "{
|
999
|
+
"todo.created": 1
|
1000
|
+
}",
|
1001
|
+
"mergeResultTag": "advance",
|
1002
|
+
},
|
1003
|
+
"children": [
|
1004
|
+
{
|
1005
|
+
"_name": "client-session-sync-processor:materialize-event",
|
1006
|
+
"children": [
|
1007
|
+
{
|
1008
|
+
"_name": "livestore.in-memory-db:execute",
|
1009
|
+
"attributes": {
|
1010
|
+
"sql.query": "INSERT INTO 'todos' (id, text, completed) VALUES (?, ?, ?)",
|
1011
|
+
},
|
1012
|
+
},
|
1013
|
+
],
|
1014
|
+
},
|
1015
|
+
],
|
1016
|
+
},
|
1017
|
+
],
|
1018
|
+
},
|
1019
|
+
]
|
1020
|
+
`;
|
@@ -6,7 +6,7 @@ import { expect } from 'vitest'
|
|
6
6
|
|
7
7
|
import * as RG from '../reactive.ts'
|
8
8
|
import { events, makeTodoMvc, tables } from '../utils/tests/fixture.ts'
|
9
|
-
import { getSimplifiedRootSpan } from '../utils/tests/otel.ts'
|
9
|
+
import { getAllSimplifiedRootSpans, getSimplifiedRootSpan } from '../utils/tests/otel.ts'
|
10
10
|
import { computed } from './computed.ts'
|
11
11
|
import { queryDb } from './db-query.ts'
|
12
12
|
|
@@ -83,7 +83,8 @@ Vitest.describe('otel', () => {
|
|
83
83
|
Effect.tap(({ exporter, provider }) =>
|
84
84
|
Effect.promise(async () => {
|
85
85
|
await provider.forceFlush()
|
86
|
-
expect(getSimplifiedRootSpan(exporter, mapAttributes)).toMatchSnapshot()
|
86
|
+
expect(getSimplifiedRootSpan(exporter, 'createStore', mapAttributes)).toMatchSnapshot()
|
87
|
+
expect(getAllSimplifiedRootSpans(exporter, 'LiveStore:commit', mapAttributes)).toMatchSnapshot()
|
87
88
|
await provider.shutdown()
|
88
89
|
}),
|
89
90
|
),
|
@@ -139,7 +140,8 @@ Vitest.describe('otel', () => {
|
|
139
140
|
Effect.tap(({ exporter, provider }) =>
|
140
141
|
Effect.promise(async () => {
|
141
142
|
await provider.forceFlush()
|
142
|
-
expect(getSimplifiedRootSpan(exporter, mapAttributes)).toMatchSnapshot()
|
143
|
+
expect(getSimplifiedRootSpan(exporter, 'createStore', mapAttributes)).toMatchSnapshot()
|
144
|
+
expect(getAllSimplifiedRootSpans(exporter, 'LiveStore:commit', mapAttributes)).toMatchSnapshot()
|
143
145
|
await provider.shutdown()
|
144
146
|
}),
|
145
147
|
),
|
@@ -183,7 +185,8 @@ Vitest.describe('otel', () => {
|
|
183
185
|
Effect.tap(({ exporter, provider }) =>
|
184
186
|
Effect.promise(async () => {
|
185
187
|
await provider.forceFlush()
|
186
|
-
expect(getSimplifiedRootSpan(exporter, mapAttributes)).toMatchSnapshot()
|
188
|
+
expect(getSimplifiedRootSpan(exporter, 'createStore', mapAttributes)).toMatchSnapshot()
|
189
|
+
expect(getAllSimplifiedRootSpans(exporter, 'LiveStore:commit', mapAttributes)).toMatchSnapshot()
|
187
190
|
await provider.shutdown()
|
188
191
|
}),
|
189
192
|
),
|
@@ -228,7 +231,8 @@ Vitest.describe('otel', () => {
|
|
228
231
|
Effect.tap(({ exporter, provider }) =>
|
229
232
|
Effect.promise(async () => {
|
230
233
|
await provider.forceFlush()
|
231
|
-
expect(getSimplifiedRootSpan(exporter, mapAttributes)).toMatchSnapshot()
|
234
|
+
expect(getSimplifiedRootSpan(exporter, 'createStore', mapAttributes)).toMatchSnapshot()
|
235
|
+
expect(getAllSimplifiedRootSpans(exporter, 'LiveStore:commit', mapAttributes)).toMatchSnapshot()
|
232
236
|
await provider.shutdown()
|
233
237
|
}),
|
234
238
|
),
|
@@ -283,7 +287,8 @@ Vitest.describe('otel', () => {
|
|
283
287
|
Effect.tap(({ exporter, provider }) =>
|
284
288
|
Effect.promise(async () => {
|
285
289
|
await provider.forceFlush()
|
286
|
-
expect(getSimplifiedRootSpan(exporter, mapAttributes)).toMatchSnapshot()
|
290
|
+
expect(getSimplifiedRootSpan(exporter, 'createStore', mapAttributes)).toMatchSnapshot()
|
291
|
+
expect(getAllSimplifiedRootSpans(exporter, 'LiveStore:commit', mapAttributes)).toMatchSnapshot()
|
287
292
|
await provider.shutdown()
|
288
293
|
}),
|
289
294
|
),
|
@@ -324,7 +329,8 @@ Vitest.describe('otel', () => {
|
|
324
329
|
Effect.tap(({ exporter, provider }) =>
|
325
330
|
Effect.promise(async () => {
|
326
331
|
await provider.forceFlush()
|
327
|
-
expect(getSimplifiedRootSpan(exporter, mapAttributes)).toMatchSnapshot()
|
332
|
+
expect(getSimplifiedRootSpan(exporter, 'createStore', mapAttributes)).toMatchSnapshot()
|
333
|
+
expect(getAllSimplifiedRootSpans(exporter, 'LiveStore:commit', mapAttributes)).toMatchSnapshot()
|
328
334
|
await provider.shutdown()
|
329
335
|
}),
|
330
336
|
),
|
package/src/mod.ts
CHANGED
package/src/reactive.test.ts
CHANGED
@@ -424,3 +424,103 @@ describe('error handling', () => {
|
|
424
424
|
)
|
425
425
|
})
|
426
426
|
})
|
427
|
+
|
428
|
+
// Bug: When an effect calls setRef during execution, it triggers nested runEffects calls.
|
429
|
+
// The nested call would overwrite and clear the shared currentDebugRefresh state,
|
430
|
+
// causing a TypeError when the outer runEffects tried to access currentDebugRefresh.refreshedAtoms.
|
431
|
+
// Fix: Use local variables to capture debug state instead of relying on shared mutable state.
|
432
|
+
describe('bug fix: currentDebugRefresh race condition', () => {
|
433
|
+
it('handles nested runEffects from effect calling setRef', () => {
|
434
|
+
const graph = new ReactiveGraph()
|
435
|
+
graph.context = {}
|
436
|
+
|
437
|
+
const a = graph.makeRef(1)
|
438
|
+
const b = graph.makeRef(2)
|
439
|
+
|
440
|
+
// Effect that calls setRef, triggering nested runEffects
|
441
|
+
graph
|
442
|
+
.makeEffect((get) => {
|
443
|
+
get(a)
|
444
|
+
graph.setRef(b, 3)
|
445
|
+
})
|
446
|
+
.doEffect()
|
447
|
+
|
448
|
+
// Effect observing b
|
449
|
+
graph.makeEffect((get) => get(b)).doEffect()
|
450
|
+
|
451
|
+
// Previously crashed with: Cannot read properties of undefined (reading 'refreshedAtoms')
|
452
|
+
// Now handles nested runEffects correctly
|
453
|
+
expect(() => graph.setRef(a, 2)).not.toThrow()
|
454
|
+
})
|
455
|
+
|
456
|
+
it('handles thunk calling setRef directly', () => {
|
457
|
+
const graph = new ReactiveGraph()
|
458
|
+
graph.context = {}
|
459
|
+
|
460
|
+
const a = graph.makeRef(1)
|
461
|
+
const b = graph.makeRef(2)
|
462
|
+
|
463
|
+
// Effect observing b so setRef(b) triggers runEffects
|
464
|
+
graph.makeEffect((get) => get(b)).doEffect()
|
465
|
+
|
466
|
+
// Thunk that calls setRef during its computation
|
467
|
+
const thunk = graph.makeThunk((get) => {
|
468
|
+
const val = get(a)
|
469
|
+
graph.setRef(b, val * 2) // This triggers nested runEffects
|
470
|
+
return val + get(b)
|
471
|
+
})
|
472
|
+
|
473
|
+
// With our fix, this handles nested currentDebugRefresh correctly
|
474
|
+
expect(() => thunk.computeResult()).not.toThrow()
|
475
|
+
expect(thunk.computeResult()).toBe(3) // 1 + 2 (b was already set to 2)
|
476
|
+
})
|
477
|
+
|
478
|
+
it('handles nested thunk computations', () => {
|
479
|
+
const graph = new ReactiveGraph()
|
480
|
+
graph.context = {}
|
481
|
+
|
482
|
+
const a = graph.makeRef(1)
|
483
|
+
|
484
|
+
// Outer thunk that creates and computes inner thunk
|
485
|
+
const outerThunk = graph.makeThunk((get) => {
|
486
|
+
const val = get(a)
|
487
|
+
|
488
|
+
// Create and compute inner thunk during outer computation
|
489
|
+
const innerThunk = graph.makeThunk((innerGet) => innerGet(a) * 2)
|
490
|
+
|
491
|
+
// Nested thunk computation - previously could corrupt currentDebugRefresh
|
492
|
+
return val + innerThunk.computeResult()
|
493
|
+
})
|
494
|
+
|
495
|
+
// With our fix, nested thunk computations work correctly
|
496
|
+
expect(() => outerThunk.computeResult()).not.toThrow()
|
497
|
+
expect(outerThunk.computeResult()).toBe(3) // 1 + (1 * 2)
|
498
|
+
})
|
499
|
+
})
|
500
|
+
|
501
|
+
// Bug: Nodes could have undefined or deleted super/sub properties in certain edge cases,
|
502
|
+
// causing crashes with "Cannot read properties of undefined" errors.
|
503
|
+
// Fix: Added validation checks in destroyNode to handle corrupted nodes gracefully.
|
504
|
+
// Note: Full addEdge protection was removed, so some scenarios still crash with native errors.
|
505
|
+
describe('bug fix: node corruption protection', () => {
|
506
|
+
it('handles node destruction during effect execution', () => {
|
507
|
+
const graph = new ReactiveGraph()
|
508
|
+
graph.context = {}
|
509
|
+
|
510
|
+
const a = graph.makeRef(1)
|
511
|
+
const thunk1 = graph.makeThunk((get) => get(a) * 2)
|
512
|
+
const thunk2 = graph.makeThunk((get) => get(thunk1))
|
513
|
+
|
514
|
+
let firstRun = true
|
515
|
+
const effect = graph.makeEffect((get) => {
|
516
|
+
if (firstRun) {
|
517
|
+
firstRun = false
|
518
|
+
graph.destroyNode(thunk1) // Destroy dependency mid-execution
|
519
|
+
}
|
520
|
+
get(thunk2)
|
521
|
+
})
|
522
|
+
|
523
|
+
// Should detect the destroyed node
|
524
|
+
expect(() => effect.doEffect()).toThrow('LiveStore Error: Attempted to compute destroyed')
|
525
|
+
})
|
526
|
+
})
|