@livestore/livestore 0.3.0-dev.5 → 0.3.0-dev.50

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 (170) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/QueryCache.d.ts.map +1 -1
  3. package/dist/SqliteDbWrapper.d.ts +60 -0
  4. package/dist/SqliteDbWrapper.d.ts.map +1 -0
  5. package/dist/{SynchronousDatabaseWrapper.js → SqliteDbWrapper.js} +69 -34
  6. package/dist/SqliteDbWrapper.js.map +1 -0
  7. package/dist/effect/LiveStore.d.ts +6 -34
  8. package/dist/effect/LiveStore.d.ts.map +1 -1
  9. package/dist/effect/LiveStore.js +10 -12
  10. package/dist/effect/LiveStore.js.map +1 -1
  11. package/dist/effect/mod.d.ts +3 -0
  12. package/dist/effect/mod.d.ts.map +1 -0
  13. package/dist/effect/mod.js +3 -0
  14. package/dist/effect/mod.js.map +1 -0
  15. package/dist/internal/mod.d.ts +3 -0
  16. package/dist/internal/mod.d.ts.map +1 -0
  17. package/dist/internal/mod.js +3 -0
  18. package/dist/internal/mod.js.map +1 -0
  19. package/dist/live-queries/base-class.d.ts +65 -27
  20. package/dist/live-queries/base-class.d.ts.map +1 -1
  21. package/dist/live-queries/base-class.js +54 -13
  22. package/dist/live-queries/base-class.js.map +1 -1
  23. package/dist/live-queries/client-document-get-query.d.ts +12 -0
  24. package/dist/live-queries/client-document-get-query.d.ts.map +1 -0
  25. package/dist/live-queries/client-document-get-query.js +18 -0
  26. package/dist/live-queries/client-document-get-query.js.map +1 -0
  27. package/dist/live-queries/computed.d.ts +12 -14
  28. package/dist/live-queries/computed.d.ts.map +1 -1
  29. package/dist/live-queries/computed.js +37 -15
  30. package/dist/live-queries/computed.js.map +1 -1
  31. package/dist/live-queries/db-query.d.ts +93 -0
  32. package/dist/live-queries/db-query.d.ts.map +1 -0
  33. package/dist/live-queries/{db.js → db-query.js} +111 -40
  34. package/dist/live-queries/db-query.js.map +1 -0
  35. package/dist/live-queries/db-query.test.d.ts +2 -0
  36. package/dist/live-queries/db-query.test.d.ts.map +1 -0
  37. package/dist/live-queries/db-query.test.js +133 -0
  38. package/dist/live-queries/db-query.test.js.map +1 -0
  39. package/dist/live-queries/mod.d.ts +5 -0
  40. package/dist/live-queries/mod.d.ts.map +1 -0
  41. package/dist/live-queries/mod.js +5 -0
  42. package/dist/live-queries/mod.js.map +1 -0
  43. package/dist/live-queries/signal.d.ts +20 -0
  44. package/dist/live-queries/signal.d.ts.map +1 -0
  45. package/dist/live-queries/signal.js +33 -0
  46. package/dist/live-queries/signal.js.map +1 -0
  47. package/dist/live-queries/signal.test.d.ts +2 -0
  48. package/dist/live-queries/signal.test.d.ts.map +1 -0
  49. package/dist/live-queries/signal.test.js +25 -0
  50. package/dist/live-queries/signal.test.js.map +1 -0
  51. package/dist/mod.d.ts +14 -0
  52. package/dist/mod.d.ts.map +1 -0
  53. package/dist/mod.js +13 -0
  54. package/dist/mod.js.map +1 -0
  55. package/dist/reactive.d.ts +23 -17
  56. package/dist/reactive.d.ts.map +1 -1
  57. package/dist/reactive.js +23 -19
  58. package/dist/reactive.js.map +1 -1
  59. package/dist/reactive.test.js +1 -1
  60. package/dist/reactive.test.js.map +1 -1
  61. package/dist/store/create-store.d.ts +70 -12
  62. package/dist/store/create-store.d.ts.map +1 -1
  63. package/dist/store/create-store.js +68 -19
  64. package/dist/store/create-store.js.map +1 -1
  65. package/dist/store/devtools.d.ts +5 -4
  66. package/dist/store/devtools.d.ts.map +1 -1
  67. package/dist/store/devtools.js +92 -40
  68. package/dist/store/devtools.js.map +1 -1
  69. package/dist/store/store-types.d.ts +54 -42
  70. package/dist/store/store-types.d.ts.map +1 -1
  71. package/dist/store/store-types.js +2 -5
  72. package/dist/store/store-types.js.map +1 -1
  73. package/dist/store/store.d.ts +141 -35
  74. package/dist/store/store.d.ts.map +1 -1
  75. package/dist/store/store.js +319 -153
  76. package/dist/store/store.js.map +1 -1
  77. package/dist/utils/data-structures.d.ts.map +1 -1
  78. package/dist/utils/dev.d.ts.map +1 -1
  79. package/dist/utils/dev.js +6 -1
  80. package/dist/utils/dev.js.map +1 -1
  81. package/dist/utils/function-string.d.ts +7 -0
  82. package/dist/utils/function-string.d.ts.map +1 -0
  83. package/dist/utils/function-string.js +9 -0
  84. package/dist/utils/function-string.js.map +1 -0
  85. package/dist/utils/stack-info.d.ts.map +1 -1
  86. package/dist/utils/stack-info.js +6 -1
  87. package/dist/utils/stack-info.js.map +1 -1
  88. package/dist/utils/stack-info.test.js +54 -1
  89. package/dist/utils/stack-info.test.js.map +1 -1
  90. package/dist/utils/tests/fixture.d.ts +59 -216
  91. package/dist/utils/tests/fixture.d.ts.map +1 -1
  92. package/dist/utils/tests/fixture.js +23 -18
  93. package/dist/utils/tests/fixture.js.map +1 -1
  94. package/dist/utils/tests/mod.d.ts +1 -0
  95. package/dist/utils/tests/mod.d.ts.map +1 -1
  96. package/dist/utils/tests/mod.js +1 -0
  97. package/dist/utils/tests/mod.js.map +1 -1
  98. package/dist/utils/tests/otel.d.ts.map +1 -1
  99. package/dist/utils/tests/otel.js +8 -3
  100. package/dist/utils/tests/otel.js.map +1 -1
  101. package/package.json +29 -26
  102. package/src/{SynchronousDatabaseWrapper.ts → SqliteDbWrapper.ts} +92 -42
  103. package/src/effect/LiveStore.ts +27 -64
  104. package/src/effect/{index.ts → mod.ts} +2 -3
  105. package/src/internal/mod.ts +2 -0
  106. package/src/live-queries/__snapshots__/{db.test.ts.snap → db-query.test.ts.snap} +241 -45
  107. package/src/live-queries/base-class.ts +152 -50
  108. package/src/live-queries/client-document-get-query.ts +52 -0
  109. package/src/live-queries/computed.ts +51 -33
  110. package/src/live-queries/db-query.test.ts +192 -0
  111. package/src/live-queries/{db.ts → db-query.ts} +168 -81
  112. package/src/live-queries/mod.ts +4 -0
  113. package/src/live-queries/signal.test.ts +40 -0
  114. package/src/live-queries/signal.ts +47 -0
  115. package/src/mod.ts +42 -0
  116. package/src/reactive.test.ts +1 -1
  117. package/src/reactive.ts +66 -43
  118. package/src/store/create-store.ts +188 -62
  119. package/src/store/devtools.ts +124 -46
  120. package/src/store/store-types.ts +54 -43
  121. package/src/store/store.ts +454 -236
  122. package/src/utils/dev.ts +6 -1
  123. package/src/utils/function-string.ts +12 -0
  124. package/src/utils/stack-info.test.ts +58 -1
  125. package/src/utils/stack-info.ts +6 -1
  126. package/src/utils/tests/fixture.ts +22 -31
  127. package/src/utils/tests/mod.ts +1 -0
  128. package/src/utils/tests/otel.ts +10 -3
  129. package/dist/SynchronousDatabaseWrapper.d.ts +0 -41
  130. package/dist/SynchronousDatabaseWrapper.d.ts.map +0 -1
  131. package/dist/SynchronousDatabaseWrapper.js.map +0 -1
  132. package/dist/effect/index.d.ts +0 -2
  133. package/dist/effect/index.d.ts.map +0 -1
  134. package/dist/effect/index.js +0 -2
  135. package/dist/effect/index.js.map +0 -1
  136. package/dist/global-state.d.ts +0 -14
  137. package/dist/global-state.d.ts.map +0 -1
  138. package/dist/global-state.js +0 -16
  139. package/dist/global-state.js.map +0 -1
  140. package/dist/index.d.ts +0 -20
  141. package/dist/index.d.ts.map +0 -1
  142. package/dist/index.js +0 -16
  143. package/dist/index.js.map +0 -1
  144. package/dist/live-queries/db.d.ts +0 -66
  145. package/dist/live-queries/db.d.ts.map +0 -1
  146. package/dist/live-queries/db.js.map +0 -1
  147. package/dist/live-queries/db.test.d.ts +0 -2
  148. package/dist/live-queries/db.test.d.ts.map +0 -1
  149. package/dist/live-queries/db.test.js +0 -118
  150. package/dist/live-queries/db.test.js.map +0 -1
  151. package/dist/live-queries/graphql.d.ts +0 -49
  152. package/dist/live-queries/graphql.d.ts.map +0 -1
  153. package/dist/live-queries/graphql.js +0 -122
  154. package/dist/live-queries/graphql.js.map +0 -1
  155. package/dist/row-query-utils.d.ts +0 -17
  156. package/dist/row-query-utils.d.ts.map +0 -1
  157. package/dist/row-query-utils.js +0 -30
  158. package/dist/row-query-utils.js.map +0 -1
  159. package/dist/utils/otel.d.ts +0 -4
  160. package/dist/utils/otel.d.ts.map +0 -1
  161. package/dist/utils/otel.js +0 -6
  162. package/dist/utils/otel.js.map +0 -1
  163. package/src/global-state.ts +0 -20
  164. package/src/index.ts +0 -66
  165. package/src/live-queries/db.test.ts +0 -154
  166. package/src/live-queries/graphql.ts +0 -219
  167. package/src/row-query-utils.ts +0 -65
  168. package/src/utils/otel.ts +0 -9
  169. package/tsconfig.json +0 -18
  170. package/vitest.config.js +0 -9
@@ -14,7 +14,6 @@ exports[`otel > otel 3`] = `
14
14
  "sql.query": "
15
15
  PRAGMA page_size=32768;
16
16
  PRAGMA cache_size=10000;
17
- PRAGMA journal_mode='MEMORY'; -- we don't flush to disk before committing a write
18
17
  PRAGMA synchronous='OFF';
19
18
  PRAGMA temp_store='MEMORY';
20
19
  PRAGMA foreign_keys='ON'; -- we want foreign key constraints to be enforced
@@ -22,33 +21,40 @@ exports[`otel > otel 3`] = `
22
21
  },
23
22
  },
24
23
  {
25
- "_name": "LiveStore:createStore",
24
+ "_name": "@livestore/common:LeaderSyncProcessor:push",
25
+ "attributes": {
26
+ "batch": "undefined",
27
+ "batchSize": 1,
28
+ },
29
+ },
30
+ {
31
+ "_name": "client-session-sync-processor:pull",
32
+ "attributes": {
33
+ "code.stacktrace": "<STACKTRACE>",
34
+ "span.label": "⚠︎ Interrupted",
35
+ "status.interrupted": true,
36
+ },
26
37
  },
27
38
  {
28
39
  "_name": "LiveStore:sync",
29
40
  },
30
41
  {
31
- "_name": "LiveStore:mutations",
42
+ "_name": "LiveStore:commits",
32
43
  "children": [
33
44
  {
34
- "_name": "LiveStore:mutate",
45
+ "_name": "LiveStore:commit",
35
46
  "attributes": {
36
- "livestore.mutateLabel": "mutate",
47
+ "livestore.eventTags": [
48
+ "livestore.RawSql",
49
+ ],
50
+ "livestore.eventsCount": 1,
37
51
  },
38
52
  "children": [
39
53
  {
40
- "_name": "LiveStore:mutate:applyMutations",
54
+ "_name": "livestore.in-memory-db:execute",
41
55
  "attributes": {
42
- "livestore.mutateLabel": "mutate",
56
+ "sql.query": "INSERT INTO todos (id, text, completed) VALUES ('t1', 'buy milk', 0)",
43
57
  },
44
- "children": [
45
- {
46
- "_name": "livestore.in-memory-db:execute",
47
- "attributes": {
48
- "sql.query": "INSERT INTO todos (id, text, completed) VALUES ('t1', 'buy milk', 0)",
49
- },
50
- },
51
- ],
52
58
  },
53
59
  ],
54
60
  },
@@ -97,7 +103,179 @@ exports[`otel > otel 3`] = `
97
103
  }
98
104
  `;
99
105
 
106
+ exports[`otel > with thunks 1`] = `
107
+ {
108
+ "atoms": [
109
+ {
110
+ "_tag": "ref",
111
+ "id": "node-1",
112
+ "isDestroyed": false,
113
+ "isDirty": false,
114
+ "label": "tableRef:todos",
115
+ "meta": {
116
+ "liveStoreRefType": "table",
117
+ },
118
+ "previousResult": {
119
+ "_tag": "Some",
120
+ "value": "null",
121
+ },
122
+ "refreshes": 0,
123
+ "sub": [],
124
+ "super": [],
125
+ },
126
+ {
127
+ "_tag": "ref",
128
+ "id": "node-2",
129
+ "isDestroyed": false,
130
+ "isDirty": false,
131
+ "label": "tableRef:app",
132
+ "meta": {
133
+ "liveStoreRefType": "table",
134
+ },
135
+ "previousResult": {
136
+ "_tag": "Some",
137
+ "value": "null",
138
+ },
139
+ "refreshes": 0,
140
+ "sub": [],
141
+ "super": [],
142
+ },
143
+ ],
144
+ "deferredEffects": [],
145
+ "effects": [],
146
+ }
147
+ `;
148
+
100
149
  exports[`otel > with thunks 3`] = `
150
+ {
151
+ "atoms": [
152
+ {
153
+ "_tag": "ref",
154
+ "id": "node-1",
155
+ "isDestroyed": false,
156
+ "isDirty": false,
157
+ "label": "tableRef:todos",
158
+ "meta": {
159
+ "liveStoreRefType": "table",
160
+ },
161
+ "previousResult": {
162
+ "_tag": "Some",
163
+ "value": "null",
164
+ },
165
+ "refreshes": 0,
166
+ "sub": [],
167
+ "super": [],
168
+ },
169
+ {
170
+ "_tag": "ref",
171
+ "id": "node-2",
172
+ "isDestroyed": false,
173
+ "isDirty": false,
174
+ "label": "tableRef:app",
175
+ "meta": {
176
+ "liveStoreRefType": "table",
177
+ },
178
+ "previousResult": {
179
+ "_tag": "Some",
180
+ "value": "null",
181
+ },
182
+ "refreshes": 0,
183
+ "sub": [],
184
+ "super": [],
185
+ },
186
+ ],
187
+ "deferredEffects": [],
188
+ "effects": [],
189
+ }
190
+ `;
191
+
192
+ exports[`otel > with thunks 4`] = `
193
+ {
194
+ "atoms": [
195
+ {
196
+ "_tag": "ref",
197
+ "id": "node-1",
198
+ "isDestroyed": false,
199
+ "isDirty": false,
200
+ "label": "tableRef:todos",
201
+ "meta": {
202
+ "liveStoreRefType": "table",
203
+ },
204
+ "previousResult": {
205
+ "_tag": "Some",
206
+ "value": "null",
207
+ },
208
+ "refreshes": 1,
209
+ "sub": [],
210
+ "super": [],
211
+ },
212
+ {
213
+ "_tag": "ref",
214
+ "id": "node-2",
215
+ "isDestroyed": false,
216
+ "isDirty": false,
217
+ "label": "tableRef:app",
218
+ "meta": {
219
+ "liveStoreRefType": "table",
220
+ },
221
+ "previousResult": {
222
+ "_tag": "Some",
223
+ "value": "null",
224
+ },
225
+ "refreshes": 0,
226
+ "sub": [],
227
+ "super": [],
228
+ },
229
+ ],
230
+ "deferredEffects": [],
231
+ "effects": [],
232
+ }
233
+ `;
234
+
235
+ exports[`otel > with thunks 6`] = `
236
+ {
237
+ "atoms": [
238
+ {
239
+ "_tag": "ref",
240
+ "id": "node-1",
241
+ "isDestroyed": false,
242
+ "isDirty": false,
243
+ "label": "tableRef:todos",
244
+ "meta": {
245
+ "liveStoreRefType": "table",
246
+ },
247
+ "previousResult": {
248
+ "_tag": "Some",
249
+ "value": "null",
250
+ },
251
+ "refreshes": 1,
252
+ "sub": [],
253
+ "super": [],
254
+ },
255
+ {
256
+ "_tag": "ref",
257
+ "id": "node-2",
258
+ "isDestroyed": false,
259
+ "isDirty": false,
260
+ "label": "tableRef:app",
261
+ "meta": {
262
+ "liveStoreRefType": "table",
263
+ },
264
+ "previousResult": {
265
+ "_tag": "Some",
266
+ "value": "null",
267
+ },
268
+ "refreshes": 0,
269
+ "sub": [],
270
+ "super": [],
271
+ },
272
+ ],
273
+ "deferredEffects": [],
274
+ "effects": [],
275
+ }
276
+ `;
277
+
278
+ exports[`otel > with thunks 7`] = `
101
279
  {
102
280
  "_name": "createStore",
103
281
  "attributes": {
@@ -111,7 +289,6 @@ exports[`otel > with thunks 3`] = `
111
289
  "sql.query": "
112
290
  PRAGMA page_size=32768;
113
291
  PRAGMA cache_size=10000;
114
- PRAGMA journal_mode='MEMORY'; -- we don't flush to disk before committing a write
115
292
  PRAGMA synchronous='OFF';
116
293
  PRAGMA temp_store='MEMORY';
117
294
  PRAGMA foreign_keys='ON'; -- we want foreign key constraints to be enforced
@@ -119,33 +296,40 @@ exports[`otel > with thunks 3`] = `
119
296
  },
120
297
  },
121
298
  {
122
- "_name": "LiveStore:createStore",
299
+ "_name": "@livestore/common:LeaderSyncProcessor:push",
300
+ "attributes": {
301
+ "batch": "undefined",
302
+ "batchSize": 1,
303
+ },
304
+ },
305
+ {
306
+ "_name": "client-session-sync-processor:pull",
307
+ "attributes": {
308
+ "code.stacktrace": "<STACKTRACE>",
309
+ "span.label": "⚠︎ Interrupted",
310
+ "status.interrupted": true,
311
+ },
123
312
  },
124
313
  {
125
314
  "_name": "LiveStore:sync",
126
315
  },
127
316
  {
128
- "_name": "LiveStore:mutations",
317
+ "_name": "LiveStore:commits",
129
318
  "children": [
130
319
  {
131
- "_name": "LiveStore:mutate",
320
+ "_name": "LiveStore:commit",
132
321
  "attributes": {
133
- "livestore.mutateLabel": "mutate",
322
+ "livestore.eventTags": [
323
+ "livestore.RawSql",
324
+ ],
325
+ "livestore.eventsCount": 1,
134
326
  },
135
327
  "children": [
136
328
  {
137
- "_name": "LiveStore:mutate:applyMutations",
329
+ "_name": "livestore.in-memory-db:execute",
138
330
  "attributes": {
139
- "livestore.mutateLabel": "mutate",
331
+ "sql.query": "INSERT INTO todos (id, text, completed) VALUES ('t1', 'buy milk', 0)",
140
332
  },
141
- "children": [
142
- {
143
- "_name": "livestore.in-memory-db:execute",
144
- "attributes": {
145
- "sql.query": "INSERT INTO todos (id, text, completed) VALUES ('t1', 'buy milk', 0)",
146
- },
147
- },
148
- ],
149
333
  },
150
334
  ],
151
335
  },
@@ -181,6 +365,9 @@ exports[`otel > with thunks 3`] = `
181
365
  "sql.rowsCount": 1,
182
366
  },
183
367
  "children": [
368
+ {
369
+ "_name": "js:where-filter",
370
+ },
184
371
  {
185
372
  "_name": "sql-in-memory-select",
186
373
  "attributes": {
@@ -211,7 +398,6 @@ exports[`otel > with thunks with query builder and without labels 3`] = `
211
398
  "sql.query": "
212
399
  PRAGMA page_size=32768;
213
400
  PRAGMA cache_size=10000;
214
- PRAGMA journal_mode='MEMORY'; -- we don't flush to disk before committing a write
215
401
  PRAGMA synchronous='OFF';
216
402
  PRAGMA temp_store='MEMORY';
217
403
  PRAGMA foreign_keys='ON'; -- we want foreign key constraints to be enforced
@@ -219,33 +405,40 @@ exports[`otel > with thunks with query builder and without labels 3`] = `
219
405
  },
220
406
  },
221
407
  {
222
- "_name": "LiveStore:createStore",
408
+ "_name": "@livestore/common:LeaderSyncProcessor:push",
409
+ "attributes": {
410
+ "batch": "undefined",
411
+ "batchSize": 1,
412
+ },
413
+ },
414
+ {
415
+ "_name": "client-session-sync-processor:pull",
416
+ "attributes": {
417
+ "code.stacktrace": "<STACKTRACE>",
418
+ "span.label": "⚠︎ Interrupted",
419
+ "status.interrupted": true,
420
+ },
223
421
  },
224
422
  {
225
423
  "_name": "LiveStore:sync",
226
424
  },
227
425
  {
228
- "_name": "LiveStore:mutations",
426
+ "_name": "LiveStore:commits",
229
427
  "children": [
230
428
  {
231
- "_name": "LiveStore:mutate",
429
+ "_name": "LiveStore:commit",
232
430
  "attributes": {
233
- "livestore.mutateLabel": "mutate",
431
+ "livestore.eventTags": [
432
+ "livestore.RawSql",
433
+ ],
434
+ "livestore.eventsCount": 1,
234
435
  },
235
436
  "children": [
236
437
  {
237
- "_name": "LiveStore:mutate:applyMutations",
438
+ "_name": "livestore.in-memory-db:execute",
238
439
  "attributes": {
239
- "livestore.mutateLabel": "mutate",
440
+ "sql.query": "INSERT INTO todos (id, text, completed) VALUES ('t1', 'buy milk', 0)",
240
441
  },
241
- "children": [
242
- {
243
- "_name": "livestore.in-memory-db:execute",
244
- "attributes": {
245
- "sql.query": "INSERT INTO todos (id, text, completed) VALUES ('t1', 'buy milk', 0)",
246
- },
247
- },
248
- ],
249
442
  },
250
443
  ],
251
444
  },
@@ -281,6 +474,9 @@ exports[`otel > with thunks with query builder and without labels 3`] = `
281
474
  "sql.rowsCount": 1,
282
475
  },
283
476
  "children": [
477
+ {
478
+ "_name": "js:() => ({ completed: false })",
479
+ },
284
480
  {
285
481
  "_name": "sql-in-memory-select",
286
482
  "attributes": {
@@ -1,72 +1,119 @@
1
- import type { QueryInfo } from '@livestore/common'
1
+ import { isNotNil } from '@livestore/utils'
2
2
  import type * as otel from '@opentelemetry/api'
3
3
 
4
- import { type Atom, type GetAtom, ReactiveGraph, throwContextNotSetError, type Thunk } from '../reactive.js'
4
+ import * as RG from '../reactive.js'
5
5
  import type { Store } from '../store/store.js'
6
6
  import type { QueryDebugInfo, RefreshReason } from '../store/store-types.js'
7
7
  import type { StackInfo } from '../utils/stack-info.js'
8
8
 
9
- export type ReactivityGraph = ReactiveGraph<RefreshReason, QueryDebugInfo, QueryContext>
9
+ export type ReactivityGraph = RG.ReactiveGraph<RefreshReason, QueryDebugInfo, ReactivityGraphContext>
10
10
 
11
11
  export const makeReactivityGraph = (): ReactivityGraph =>
12
- new ReactiveGraph<RefreshReason, QueryDebugInfo, QueryContext>()
12
+ new RG.ReactiveGraph<RefreshReason, QueryDebugInfo, ReactivityGraphContext>()
13
13
 
14
- export type QueryContext = {
14
+ export type ReactivityGraphContext = {
15
15
  store: Store
16
+ /** Maps from the hash of the query definition to the RcRef of the query */
17
+ defRcMap: Map<string, RcRef<LiveQuery.Any | ISignal<any>>>
18
+ /** Back-reference to the reactivity graph for convenience */
19
+ reactivityGraph: WeakRef<ReactivityGraph>
16
20
  otelTracer: otel.Tracer
17
21
  rootOtelContext: otel.Context
18
22
  effectsWrapper: (run: () => void) => void
19
23
  }
20
24
 
21
- export type UnsubscribeQuery = () => void
22
-
23
- export type GetResult<TQuery extends LiveQueryAny> =
24
- TQuery extends LiveQuery<infer TResult, infer _1> ? TResult : unknown
25
+ export type GetResult<TQuery extends LiveQueryDef.Any | LiveQuery.Any> =
26
+ TQuery extends LiveQuery<infer TResult> ? TResult : TQuery extends LiveQueryDef<infer TResult> ? TResult : unknown
25
27
 
26
28
  let queryIdCounter = 0
27
29
 
28
- export type LiveQueryAny = LiveQuery<any, QueryInfo>
30
+ export interface SignalDef<T> {
31
+ _tag: 'signal-def'
32
+ defaultValue: T
33
+ make: (ctx: ReactivityGraphContext) => RcRef<ISignal<T>>
34
+ }
35
+
36
+ export interface ISignal<T> {
37
+ _tag: 'signal'
38
+ reactivityGraph: ReactivityGraph
39
+ ref: RG.Ref<T, ReactivityGraphContext, RefreshReason>
40
+ set: (value: T) => void
41
+ get: () => T
42
+ destroy: () => void
43
+ }
29
44
 
30
45
  export const TypeId = Symbol.for('LiveQuery')
31
46
  export type TypeId = typeof TypeId
32
47
 
33
- export interface LiveQuery<TResult, TQueryInfo extends QueryInfo = QueryInfo.None> {
48
+ export interface RcRef<T> {
49
+ rc: number
50
+ value: T
51
+ deref: () => void
52
+ }
53
+
54
+ export type DepKey = string | number | ReadonlyArray<string | number | undefined | null>
55
+
56
+ export const depsToString = (deps: DepKey): string => {
57
+ if (typeof deps === 'string' || typeof deps === 'number') {
58
+ return deps.toString()
59
+ }
60
+ return deps.filter(isNotNil).join(',')
61
+ }
62
+
63
+ export interface LiveQueryDef<TResult> {
64
+ _tag: 'def'
65
+ /** Creates a new LiveQuery instance bound to a specific store/reactivityGraph */
66
+ make: (ctx: ReactivityGraphContext, otelContext?: otel.Context) => RcRef<LiveQuery<TResult>>
67
+ label: string
68
+ hash: string
69
+ }
70
+
71
+ export namespace LiveQueryDef {
72
+ export type Any = LiveQueryDef<any>
73
+ }
74
+
75
+ /**
76
+ * A LiveQuery is stateful
77
+ */
78
+ export interface LiveQuery<TResult> {
34
79
  id: number
35
80
  _tag: 'computed' | 'db' | 'graphql'
36
81
  [TypeId]: TypeId
37
82
 
83
+ // reactivityGraph: ReactivityGraph
84
+
38
85
  /** This should only be used on a type-level and doesn't hold any value during runtime */
39
86
  '__result!': TResult
40
87
 
41
88
  /** A reactive thunk representing the query results */
42
- results$: Thunk<TResult, QueryContext, RefreshReason>
89
+ results$: RG.Thunk<TResult, ReactivityGraphContext, RefreshReason>
43
90
 
44
91
  label: string
45
92
 
46
- run: (otelContext?: otel.Context, debugRefreshReason?: RefreshReason) => TResult
93
+ run: (args: { otelContext?: otel.Context; debugRefreshReason?: RefreshReason }) => TResult
47
94
 
48
- runAndDestroy: (otelContext?: otel.Context, debugRefreshReason?: RefreshReason) => TResult
95
+ destroy: () => void
96
+ isDestroyed: boolean
49
97
 
50
- destroy(): void
51
-
52
- subscribe(
53
- onNewValue: (value: TResult) => void,
54
- onUnsubsubscribe?: () => void,
55
- options?: { label?: string; otelContext?: otel.Context },
56
- ): () => void
98
+ // subscribe(
99
+ // onNewValue: (value: TResult) => void,
100
+ // onUnsubsubscribe?: () => void,
101
+ // options?: { label?: string; otelContext?: otel.Context },
102
+ // ): () => void
57
103
 
58
104
  activeSubscriptions: Set<StackInfo>
59
105
 
60
- queryInfo: TQueryInfo
61
-
62
106
  runs: number
63
107
 
64
108
  executionTimes: number[]
109
+ def: LiveQueryDef<TResult>
65
110
  }
66
111
 
67
- export abstract class LiveStoreQueryBase<TResult, TQueryInfo extends QueryInfo>
68
- implements LiveQuery<TResult, TQueryInfo>
69
- {
112
+ export namespace LiveQuery {
113
+ export type Any = LiveQuery<any>
114
+ }
115
+
116
+ export abstract class LiveStoreQueryBase<TResult> implements LiveQuery<TResult> {
70
117
  '__result!'!: TResult
71
118
  id = queryIdCounter++;
72
119
  [TypeId]: TypeId = TypeId
@@ -75,13 +122,13 @@ export abstract class LiveStoreQueryBase<TResult, TQueryInfo extends QueryInfo>
75
122
  /** Human-readable label for the query for debugging */
76
123
  abstract label: string
77
124
 
78
- abstract results$: Thunk<TResult, QueryContext, RefreshReason>
125
+ abstract def: LiveQueryDef<TResult>
79
126
 
80
- activeSubscriptions: Set<StackInfo> = new Set()
127
+ abstract results$: RG.Thunk<TResult, ReactivityGraphContext, RefreshReason>
81
128
 
82
- protected abstract reactivityGraph: ReactivityGraph
129
+ activeSubscriptions: Set<StackInfo> = new Set()
83
130
 
84
- abstract queryInfo: TQueryInfo
131
+ abstract readonly reactivityGraph: ReactivityGraph
85
132
 
86
133
  get runs() {
87
134
  return this.results$.recomputations
@@ -89,33 +136,88 @@ export abstract class LiveStoreQueryBase<TResult, TQueryInfo extends QueryInfo>
89
136
 
90
137
  executionTimes: number[] = []
91
138
 
139
+ // TODO double check if this is needed
140
+ isDestroyed = false
92
141
  abstract destroy: () => void
93
142
 
94
- run = (otelContext?: otel.Context, debugRefreshReason?: RefreshReason): TResult =>
95
- this.results$.computeResult(otelContext, debugRefreshReason)
96
-
97
- runAndDestroy = (otelContext?: otel.Context, debugRefreshReason?: RefreshReason): TResult => {
98
- const result = this.run(otelContext, debugRefreshReason)
99
- this.destroy()
100
- return result
143
+ run = (args: { otelContext?: otel.Context; debugRefreshReason?: RefreshReason }): TResult => {
144
+ return this.results$.computeResult(args.otelContext, args.debugRefreshReason)
101
145
  }
102
146
 
103
- subscribe = (
104
- onNewValue: (value: TResult) => void,
105
- onUnsubsubscribe?: () => void,
106
- options?: { label?: string; otelContext?: otel.Context } | undefined,
107
- ): (() => void) =>
108
- this.reactivityGraph.context?.store.subscribe(this, onNewValue, onUnsubsubscribe, options) ??
109
- throwContextNotSetError(this.reactivityGraph)
110
- }
147
+ protected dependencyQueriesRef: DependencyQueriesRef = new Set()
111
148
 
112
- export type GetAtomResult = <T>(atom: Atom<T, any, RefreshReason> | LiveQuery<T, any>) => T
149
+ // subscribe = (
150
+ // onNewValue: (value: TResult) => void,
151
+ // onUnsubsubscribe?: () => void,
152
+ // options?: { label?: string; otelContext?: otel.Context } | undefined,
153
+ // ): (() => void) =>
154
+ // this.reactivityGraph.context?.store.subscribe(this, onNewValue, onUnsubsubscribe, options) ??
155
+ // RG.throwContextNotSetError(this.reactivityGraph)
156
+ }
113
157
 
114
- export const makeGetAtomResult = (get: GetAtom, otelContext: otel.Context) => {
115
- const getAtom: GetAtomResult = (atom) => {
116
- if (atom._tag === 'thunk' || atom._tag === 'ref') return get(atom, otelContext)
117
- return get(atom.results$, otelContext)
158
+ export type GetAtomResult = <T>(
159
+ atom: RG.Atom<T, any, RefreshReason> | LiveQueryDef<T> | LiveQuery<T> | ISignal<T> | SignalDef<T>,
160
+ otelContext?: otel.Context | undefined,
161
+ debugRefreshReason?: RefreshReason | undefined,
162
+ ) => T
163
+
164
+ export type DependencyQueriesRef = Set<RcRef<LiveQuery.Any | ISignal<any>>>
165
+
166
+ export const makeGetAtomResult = (
167
+ get: RG.GetAtom,
168
+ ctx: ReactivityGraphContext,
169
+ otelContext: otel.Context,
170
+ dependencyQueriesRef: DependencyQueriesRef,
171
+ ) => {
172
+ // NOTE we're using the `otelContext` from `makeGetAtomResult` here, not the `otelContext` from `getAtom`
173
+ const getAtom: GetAtomResult = (atom, _otelContext, debugRefreshReason) => {
174
+ // ReactivityGraph atoms case
175
+ if (atom._tag === 'thunk' || atom._tag === 'ref') return get(atom, otelContext, debugRefreshReason)
176
+
177
+ // def case
178
+ if (atom._tag === 'def' || atom._tag === 'signal-def') {
179
+ const query = atom.make(ctx)
180
+ dependencyQueriesRef.add(query)
181
+ // TODO deref the query on destroy
182
+ return getAtom(query.value, _otelContext, debugRefreshReason)
183
+ }
184
+
185
+ // Signal case
186
+ if (atom._tag === 'signal') return get(atom.ref, otelContext, debugRefreshReason)
187
+
188
+ // LiveQuery case
189
+ return get(atom.results$, otelContext, debugRefreshReason)
118
190
  }
119
191
 
120
192
  return getAtom
121
193
  }
194
+
195
+ export const withRCMap = <T extends LiveQuery.Any | ISignal<any>>(
196
+ id: string,
197
+ make: (ctx: ReactivityGraphContext, otelContext?: otel.Context) => T,
198
+ ): ((ctx: ReactivityGraphContext, otelContext?: otel.Context) => RcRef<T>) => {
199
+ return (ctx, otelContext) => {
200
+ let item = ctx.defRcMap.get(id)
201
+ if (item) {
202
+ item.rc++
203
+ return item as RcRef<T>
204
+ }
205
+
206
+ const query$ = make(ctx, otelContext)
207
+
208
+ item = {
209
+ rc: 1,
210
+ value: query$,
211
+ deref: () => {
212
+ item!.rc--
213
+ if (item!.rc === 0) {
214
+ item!.value.destroy()
215
+ ctx.defRcMap.delete(id)
216
+ }
217
+ },
218
+ }
219
+ ctx.defRcMap.set(id, item)
220
+
221
+ return item as RcRef<T>
222
+ }
223
+ }