@livestore/livestore 0.0.12 → 0.0.14

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 (226) hide show
  1. package/README.md +25 -28
  2. package/dist/.tsbuildinfo +1 -0
  3. package/dist/QueryCache.d.ts +20 -0
  4. package/dist/QueryCache.d.ts.map +1 -0
  5. package/dist/QueryCache.js +71 -0
  6. package/dist/QueryCache.js.map +1 -0
  7. package/dist/__tests__/react/fixture.d.ts +26 -0
  8. package/dist/__tests__/react/fixture.d.ts.map +1 -0
  9. package/dist/__tests__/react/fixture.js +60 -0
  10. package/dist/__tests__/react/fixture.js.map +1 -0
  11. package/dist/__tests__/react/useComponentState.test.d.ts +2 -0
  12. package/dist/__tests__/react/useComponentState.test.d.ts.map +1 -0
  13. package/dist/__tests__/react/useComponentState.test.js +68 -0
  14. package/dist/__tests__/react/useComponentState.test.js.map +1 -0
  15. package/dist/__tests__/react/useLQuery.test.d.ts +2 -0
  16. package/dist/__tests__/react/useLQuery.test.d.ts.map +1 -0
  17. package/dist/__tests__/react/useLQuery.test.js +38 -0
  18. package/dist/__tests__/react/useLQuery.test.js.map +1 -0
  19. package/dist/__tests__/react/useLiveStoreComponent.test.d.ts +2 -0
  20. package/dist/__tests__/react/useLiveStoreComponent.test.d.ts.map +1 -0
  21. package/dist/__tests__/react/useLiveStoreComponent.test.js +73 -0
  22. package/dist/__tests__/react/useLiveStoreComponent.test.js.map +1 -0
  23. package/dist/__tests__/react/useQuery.test.d.ts +2 -0
  24. package/dist/__tests__/react/useQuery.test.d.ts.map +1 -0
  25. package/dist/__tests__/react/useQuery.test.js +33 -0
  26. package/dist/__tests__/react/useQuery.test.js.map +1 -0
  27. package/dist/__tests__/react/utils/extractStackInfoFromStackTrace.test.d.ts +2 -0
  28. package/dist/__tests__/react/utils/extractStackInfoFromStackTrace.test.d.ts.map +1 -0
  29. package/dist/__tests__/react/utils/extractStackInfoFromStackTrace.test.js +38 -0
  30. package/dist/__tests__/react/utils/extractStackInfoFromStackTrace.test.js.map +1 -0
  31. package/dist/__tests__/reactive.test.d.ts +2 -0
  32. package/dist/__tests__/reactive.test.d.ts.map +1 -0
  33. package/dist/__tests__/reactive.test.js +271 -0
  34. package/dist/__tests__/reactive.test.js.map +1 -0
  35. package/dist/__tests__/reactiveQueries/sql.test.d.ts +2 -0
  36. package/dist/__tests__/reactiveQueries/sql.test.d.ts.map +1 -0
  37. package/dist/__tests__/reactiveQueries/sql.test.js +337 -0
  38. package/dist/__tests__/reactiveQueries/sql.test.js.map +1 -0
  39. package/dist/bounded-collections.d.ts +34 -0
  40. package/dist/bounded-collections.d.ts.map +1 -0
  41. package/dist/bounded-collections.js +103 -0
  42. package/dist/bounded-collections.js.map +1 -0
  43. package/dist/componentKey.d.ts +20 -0
  44. package/dist/componentKey.d.ts.map +1 -0
  45. package/dist/componentKey.js +3 -0
  46. package/dist/componentKey.js.map +1 -0
  47. package/dist/effect/LiveStore.d.ts +36 -0
  48. package/dist/effect/LiveStore.d.ts.map +1 -0
  49. package/dist/effect/LiveStore.js +41 -0
  50. package/dist/effect/LiveStore.js.map +1 -0
  51. package/dist/effect/index.d.ts +2 -0
  52. package/dist/effect/index.d.ts.map +1 -0
  53. package/dist/effect/index.js +2 -0
  54. package/dist/effect/index.js.map +1 -0
  55. package/dist/events.d.ts +7 -0
  56. package/dist/events.d.ts.map +1 -0
  57. package/dist/events.js +2 -0
  58. package/dist/events.js.map +1 -0
  59. package/dist/inMemoryDatabase.d.ts +56 -0
  60. package/dist/inMemoryDatabase.d.ts.map +1 -0
  61. package/dist/inMemoryDatabase.js +223 -0
  62. package/dist/inMemoryDatabase.js.map +1 -0
  63. package/dist/index.d.ts +22 -0
  64. package/dist/index.d.ts.map +1 -0
  65. package/dist/index.js +13 -0
  66. package/dist/index.js.map +1 -0
  67. package/dist/migrations.d.ts +16 -0
  68. package/dist/migrations.d.ts.map +1 -0
  69. package/dist/migrations.js +67 -0
  70. package/dist/migrations.js.map +1 -0
  71. package/dist/otel.d.ts +4 -0
  72. package/dist/otel.d.ts.map +1 -0
  73. package/dist/otel.js +6 -0
  74. package/dist/otel.js.map +1 -0
  75. package/dist/react/LiveStoreContext.d.ts +11 -0
  76. package/dist/react/LiveStoreContext.d.ts.map +1 -0
  77. package/dist/react/LiveStoreContext.js +10 -0
  78. package/dist/react/LiveStoreContext.js.map +1 -0
  79. package/dist/react/LiveStoreProvider.d.ts +20 -0
  80. package/dist/react/LiveStoreProvider.d.ts.map +1 -0
  81. package/dist/react/LiveStoreProvider.js +52 -0
  82. package/dist/react/LiveStoreProvider.js.map +1 -0
  83. package/dist/react/index.d.ts +8 -0
  84. package/dist/react/index.d.ts.map +1 -0
  85. package/dist/react/index.js +6 -0
  86. package/dist/react/index.js.map +1 -0
  87. package/dist/react/useComponentState.d.ts +50 -0
  88. package/dist/react/useComponentState.d.ts.map +1 -0
  89. package/dist/react/useComponentState.js +248 -0
  90. package/dist/react/useComponentState.js.map +1 -0
  91. package/dist/react/useGlobalQuery.d.ts +3 -0
  92. package/dist/react/useGlobalQuery.d.ts.map +1 -0
  93. package/dist/react/useGlobalQuery.js +26 -0
  94. package/dist/react/useGlobalQuery.js.map +1 -0
  95. package/dist/react/useGraphQL.d.ts +13 -0
  96. package/dist/react/useGraphQL.d.ts.map +1 -0
  97. package/dist/react/useGraphQL.js +87 -0
  98. package/dist/react/useGraphQL.js.map +1 -0
  99. package/dist/react/useLiveStoreComponent.d.ts +75 -0
  100. package/dist/react/useLiveStoreComponent.d.ts.map +1 -0
  101. package/dist/react/useLiveStoreComponent.js +361 -0
  102. package/dist/react/useLiveStoreComponent.js.map +1 -0
  103. package/dist/react/useQuery.d.ts +3 -0
  104. package/dist/react/useQuery.d.ts.map +1 -0
  105. package/dist/react/useQuery.js +42 -0
  106. package/dist/react/useQuery.js.map +1 -0
  107. package/dist/react/useTemporaryQuery.d.ts +8 -0
  108. package/dist/react/useTemporaryQuery.d.ts.map +1 -0
  109. package/dist/react/useTemporaryQuery.js +17 -0
  110. package/dist/react/useTemporaryQuery.js.map +1 -0
  111. package/dist/react/utils/extractNamesFromStackTrace.d.ts +3 -0
  112. package/dist/react/utils/extractNamesFromStackTrace.d.ts.map +1 -0
  113. package/dist/react/utils/extractNamesFromStackTrace.js +40 -0
  114. package/dist/react/utils/extractNamesFromStackTrace.js.map +1 -0
  115. package/dist/react/utils/extractStackInfoFromStackTrace.d.ts +7 -0
  116. package/dist/react/utils/extractStackInfoFromStackTrace.d.ts.map +1 -0
  117. package/dist/react/utils/extractStackInfoFromStackTrace.js +40 -0
  118. package/dist/react/utils/extractStackInfoFromStackTrace.js.map +1 -0
  119. package/dist/react/utils/useStateRefWithReactiveInput.d.ts +13 -0
  120. package/dist/react/utils/useStateRefWithReactiveInput.d.ts.map +1 -0
  121. package/dist/react/utils/useStateRefWithReactiveInput.js +38 -0
  122. package/dist/react/utils/useStateRefWithReactiveInput.js.map +1 -0
  123. package/dist/reactive.d.ts +134 -0
  124. package/dist/reactive.d.ts.map +1 -0
  125. package/dist/reactive.js +409 -0
  126. package/dist/reactive.js.map +1 -0
  127. package/dist/reactiveQueries/base-class.d.ts +32 -0
  128. package/dist/reactiveQueries/base-class.d.ts.map +1 -0
  129. package/dist/reactiveQueries/base-class.js +30 -0
  130. package/dist/reactiveQueries/base-class.js.map +1 -0
  131. package/dist/reactiveQueries/graph.d.ts +10 -0
  132. package/dist/reactiveQueries/graph.d.ts.map +1 -0
  133. package/dist/reactiveQueries/graph.js +6 -0
  134. package/dist/reactiveQueries/graph.js.map +1 -0
  135. package/dist/reactiveQueries/graphql.d.ts +42 -0
  136. package/dist/reactiveQueries/graphql.d.ts.map +1 -0
  137. package/dist/reactiveQueries/graphql.js +99 -0
  138. package/dist/reactiveQueries/graphql.js.map +1 -0
  139. package/dist/reactiveQueries/js.d.ts +23 -0
  140. package/dist/reactiveQueries/js.d.ts.map +1 -0
  141. package/dist/reactiveQueries/js.js +36 -0
  142. package/dist/reactiveQueries/js.js.map +1 -0
  143. package/dist/reactiveQueries/sql.d.ts +35 -0
  144. package/dist/reactiveQueries/sql.d.ts.map +1 -0
  145. package/dist/reactiveQueries/sql.js +97 -0
  146. package/dist/reactiveQueries/sql.js.map +1 -0
  147. package/dist/schema.d.ts +81 -0
  148. package/dist/schema.d.ts.map +1 -0
  149. package/dist/schema.js +46 -0
  150. package/dist/schema.js.map +1 -0
  151. package/dist/storage/in-memory/index.d.ts +15 -0
  152. package/dist/storage/in-memory/index.d.ts.map +1 -0
  153. package/dist/storage/in-memory/index.js +14 -0
  154. package/dist/storage/in-memory/index.js.map +1 -0
  155. package/dist/storage/index.d.ts +14 -0
  156. package/dist/storage/index.d.ts.map +1 -0
  157. package/dist/storage/index.js +9 -0
  158. package/dist/storage/index.js.map +1 -0
  159. package/dist/storage/tauri/index.d.ts +19 -0
  160. package/dist/storage/tauri/index.d.ts.map +1 -0
  161. package/dist/storage/tauri/index.js +38 -0
  162. package/dist/storage/tauri/index.js.map +1 -0
  163. package/dist/storage/utils/idb.d.ts +10 -0
  164. package/dist/storage/utils/idb.d.ts.map +1 -0
  165. package/dist/storage/utils/idb.js +58 -0
  166. package/dist/storage/utils/idb.js.map +1 -0
  167. package/dist/storage/web-worker/index.d.ts +27 -0
  168. package/dist/storage/web-worker/index.d.ts.map +1 -0
  169. package/dist/storage/web-worker/index.js +74 -0
  170. package/dist/storage/web-worker/index.js.map +1 -0
  171. package/dist/storage/web-worker/worker.d.ts +13 -0
  172. package/dist/storage/web-worker/worker.d.ts.map +1 -0
  173. package/dist/storage/web-worker/worker.js +110 -0
  174. package/dist/storage/web-worker/worker.js.map +1 -0
  175. package/dist/store.d.ts +159 -0
  176. package/dist/store.d.ts.map +1 -0
  177. package/dist/store.js +626 -0
  178. package/dist/store.js.map +1 -0
  179. package/dist/util.d.ts +28 -0
  180. package/dist/util.d.ts.map +1 -0
  181. package/dist/util.js +55 -0
  182. package/dist/util.js.map +1 -0
  183. package/package.json +47 -19
  184. package/src/QueryCache.ts +1 -1
  185. package/src/__tests__/react/fixture.tsx +35 -39
  186. package/src/__tests__/react/{useLiveStoreComponent.test.tsx → useComponentState.test.tsx} +9 -20
  187. package/src/__tests__/react/useQuery.test.tsx +48 -0
  188. package/src/__tests__/react/utils/extractStackInfoFromStackTrace.test.ts +40 -0
  189. package/src/__tests__/reactive.test.ts +194 -142
  190. package/src/__tests__/reactiveQueries/sql.test.ts +372 -0
  191. package/src/effect/LiveStore.ts +22 -31
  192. package/src/events.ts +1 -1
  193. package/src/inMemoryDatabase.ts +117 -142
  194. package/src/index.ts +18 -22
  195. package/src/migrations.ts +119 -0
  196. package/src/otel.ts +0 -11
  197. package/src/react/LiveStoreProvider.tsx +24 -23
  198. package/src/react/index.ts +12 -7
  199. package/src/react/useComponentState.ts +409 -0
  200. package/src/react/useQuery.ts +58 -0
  201. package/src/react/useTemporaryQuery.ts +21 -0
  202. package/src/react/utils/extractStackInfoFromStackTrace.ts +47 -0
  203. package/src/reactive.ts +386 -267
  204. package/src/reactiveQueries/base-class.ts +61 -39
  205. package/src/reactiveQueries/graph.ts +15 -0
  206. package/src/reactiveQueries/graphql.ts +147 -31
  207. package/src/reactiveQueries/js.ts +54 -21
  208. package/src/reactiveQueries/sql.ts +128 -37
  209. package/src/schema.ts +69 -145
  210. package/src/storage/in-memory/index.ts +21 -0
  211. package/src/storage/index.ts +27 -0
  212. package/src/{backends/tauri.ts → storage/tauri/index.ts} +14 -28
  213. package/src/storage/web-worker/index.ts +116 -0
  214. package/src/{backends/web-worker.ts → storage/web-worker/worker.ts} +17 -52
  215. package/src/store.ts +466 -457
  216. package/src/util.ts +13 -3
  217. package/tsconfig.json +1 -3
  218. package/src/backends/base.ts +0 -67
  219. package/src/backends/index.ts +0 -98
  220. package/src/backends/noop.ts +0 -32
  221. package/src/backends/web-in-memory.ts +0 -65
  222. package/src/backends/web.ts +0 -97
  223. package/src/react/useGlobalQuery.ts +0 -40
  224. package/src/react/useGraphQL.ts +0 -112
  225. package/src/react/useLiveStoreComponent.ts +0 -483
  226. /package/src/{backends → storage}/utils/idb.ts +0 -0
@@ -0,0 +1,372 @@
1
+ import * as otel from '@opentelemetry/api'
2
+ import type { ReadableSpan } from '@opentelemetry/sdk-trace-base'
3
+ import { BasicTracerProvider, InMemorySpanExporter, SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base'
4
+ import { describe, expect, it } from 'vitest'
5
+
6
+ import { queryJS, querySQL, sql } from '../../index.js'
7
+ import { makeTodoMvc } from '../react/fixture.js'
8
+
9
+ describe('otel', () => {
10
+ let cachedProvider: BasicTracerProvider | undefined
11
+
12
+ const makeQuery = async () => {
13
+ const exporter = new InMemorySpanExporter()
14
+
15
+ const provider = cachedProvider ?? new BasicTracerProvider()
16
+ cachedProvider = provider
17
+ provider.addSpanProcessor(new SimpleSpanProcessor(exporter))
18
+ provider.register()
19
+
20
+ const tracer = otel.trace.getTracer('test')
21
+
22
+ const span = tracer.startSpan('test')
23
+ const otelContext = otel.trace.setSpan(otel.context.active(), span)
24
+
25
+ const { store } = await makeTodoMvc({ otelTracer: tracer, otelContext })
26
+
27
+ return { store, tracer, exporter, span, provider }
28
+ }
29
+
30
+ it('otel', async () => {
31
+ const { store, exporter, span } = await makeQuery()
32
+
33
+ const query = querySQL(`select * from todos`, { queriedTables: ['todos'] })
34
+ expect(query.run()).toMatchInlineSnapshot('[]')
35
+
36
+ store.applyEvent('RawSql', {
37
+ sql: sql`INSERT INTO todos (id, text, completed) VALUES ('t1', 'buy milk', 0);`,
38
+ bindValues: {},
39
+ writeTables: ['todos'],
40
+ })
41
+
42
+ expect(query.run()).toMatchInlineSnapshot(`
43
+ [
44
+ {
45
+ "completed": 0,
46
+ "id": "t1",
47
+ "text": "buy milk",
48
+ },
49
+ ]
50
+ `)
51
+
52
+ store.destroy()
53
+ query.destroy()
54
+ span.end()
55
+
56
+ expect(getSimplifiedRootSpan(exporter)).toMatchInlineSnapshot(`
57
+ {
58
+ "_name": "test",
59
+ "children": [
60
+ {
61
+ "_name": "livestore.in-memory-db:execute",
62
+ "attributes": {
63
+ "sql.query": "
64
+ PRAGMA page_size=32768;
65
+ PRAGMA cache_size=10000;
66
+ PRAGMA journal_mode='MEMORY'; -- we don't flush to disk before committing a write
67
+ PRAGMA synchronous='OFF';
68
+ PRAGMA temp_store='MEMORY';
69
+ PRAGMA foreign_keys='ON'; -- we want foreign key constraints to be enforced
70
+ ",
71
+ },
72
+ },
73
+ {
74
+ "_name": "sql-in-memory-select",
75
+ "attributes": {
76
+ "sql.cached": false,
77
+ "sql.query": "SELECT * FROM __livestore_schema",
78
+ "sql.rowsCount": 0,
79
+ },
80
+ },
81
+ {
82
+ "_name": "livestore.in-memory-db:execute",
83
+ "attributes": {
84
+ "sql.query": "INSERT OR IGNORE INTO app (id, newTodoText, filter) VALUES ('static', '', 'all');",
85
+ },
86
+ },
87
+ {
88
+ "_name": "LiveStore:applyEvents",
89
+ "children": [
90
+ {
91
+ "_name": "LiveStore:applyEvent",
92
+ "children": [
93
+ {
94
+ "_name": "LiveStore:applyEventWithoutRefresh",
95
+ "attributes": {
96
+ "livestore.actionType": "RawSql",
97
+ "livestore.args": "{
98
+ \\"sql\\": \\"INSERT INTO todos (id, text, completed) VALUES ('t1', 'buy milk', 0);\\",
99
+ \\"bindValues\\": {},
100
+ \\"writeTables\\": [
101
+ \\"todos\\"
102
+ ]
103
+ }",
104
+ },
105
+ "children": [
106
+ {
107
+ "_name": "livestore.in-memory-db:execute",
108
+ "attributes": {
109
+ "sql.query": "INSERT INTO todos (id, text, completed) VALUES ('t1', 'buy milk', 0);",
110
+ },
111
+ },
112
+ ],
113
+ },
114
+ ],
115
+ },
116
+ ],
117
+ },
118
+ {
119
+ "_name": "LiveStore:queries",
120
+ "children": [
121
+ {
122
+ "_name": "sql:select * from todos",
123
+ "attributes": {
124
+ "sql.query": "select * from todos",
125
+ "sql.rowsCount": 0,
126
+ },
127
+ "children": [
128
+ {
129
+ "_name": "sql-in-memory-select",
130
+ "attributes": {
131
+ "sql.cached": false,
132
+ "sql.query": "select * from todos",
133
+ "sql.rowsCount": 0,
134
+ },
135
+ },
136
+ ],
137
+ },
138
+ {
139
+ "_name": "sql:select * from todos",
140
+ "attributes": {
141
+ "sql.query": "select * from todos",
142
+ "sql.rowsCount": 1,
143
+ },
144
+ "children": [
145
+ {
146
+ "_name": "sql-in-memory-select",
147
+ "attributes": {
148
+ "sql.cached": false,
149
+ "sql.query": "select * from todos",
150
+ "sql.rowsCount": 1,
151
+ },
152
+ },
153
+ ],
154
+ },
155
+ ],
156
+ },
157
+ ],
158
+ }
159
+ `)
160
+ })
161
+
162
+ it('with thunks', async () => {
163
+ const { store, exporter, span } = await makeQuery()
164
+
165
+ const defaultTodo = { id: '', text: '', completed: 0 }
166
+
167
+ const filter = queryJS(() => `where completed = 0`, { label: 'where-filter' })
168
+ const query = querySQL((get) => `select * from todos ${get(filter)}`, {
169
+ queriedTables: ['todos'],
170
+ label: 'all todos',
171
+ }).getFirstRow({
172
+ defaultValue: defaultTodo,
173
+ })
174
+
175
+ expect(query.run()).toMatchInlineSnapshot(`
176
+ {
177
+ "completed": 0,
178
+ "id": "",
179
+ "text": "",
180
+ }
181
+ `)
182
+
183
+ store.applyEvent('RawSql', {
184
+ sql: sql`INSERT INTO todos (id, text, completed) VALUES ('t1', 'buy milk', 0);`,
185
+ bindValues: {},
186
+ writeTables: ['todos'],
187
+ })
188
+
189
+ expect(query.run()).toMatchInlineSnapshot(`
190
+ {
191
+ "completed": 0,
192
+ "id": "t1",
193
+ "text": "buy milk",
194
+ }
195
+ `)
196
+
197
+ store.destroy()
198
+ query.destroy()
199
+ span.end()
200
+
201
+ expect(getSimplifiedRootSpan(exporter)).toMatchInlineSnapshot(`
202
+ {
203
+ "_name": "test",
204
+ "children": [
205
+ {
206
+ "_name": "livestore.in-memory-db:execute",
207
+ "attributes": {
208
+ "sql.query": "
209
+ PRAGMA page_size=32768;
210
+ PRAGMA cache_size=10000;
211
+ PRAGMA journal_mode='MEMORY'; -- we don't flush to disk before committing a write
212
+ PRAGMA synchronous='OFF';
213
+ PRAGMA temp_store='MEMORY';
214
+ PRAGMA foreign_keys='ON'; -- we want foreign key constraints to be enforced
215
+ ",
216
+ },
217
+ },
218
+ {
219
+ "_name": "sql-in-memory-select",
220
+ "attributes": {
221
+ "sql.cached": false,
222
+ "sql.query": "SELECT * FROM __livestore_schema",
223
+ "sql.rowsCount": 0,
224
+ },
225
+ },
226
+ {
227
+ "_name": "livestore.in-memory-db:execute",
228
+ "attributes": {
229
+ "sql.query": "INSERT OR IGNORE INTO app (id, newTodoText, filter) VALUES ('static', '', 'all');",
230
+ },
231
+ },
232
+ {
233
+ "_name": "LiveStore:applyEvents",
234
+ "children": [
235
+ {
236
+ "_name": "LiveStore:applyEvent",
237
+ "children": [
238
+ {
239
+ "_name": "LiveStore:applyEventWithoutRefresh",
240
+ "attributes": {
241
+ "livestore.actionType": "RawSql",
242
+ "livestore.args": "{
243
+ \\"sql\\": \\"INSERT INTO todos (id, text, completed) VALUES ('t1', 'buy milk', 0);\\",
244
+ \\"bindValues\\": {},
245
+ \\"writeTables\\": [
246
+ \\"todos\\"
247
+ ]
248
+ }",
249
+ },
250
+ "children": [
251
+ {
252
+ "_name": "livestore.in-memory-db:execute",
253
+ "attributes": {
254
+ "sql.query": "INSERT INTO todos (id, text, completed) VALUES ('t1', 'buy milk', 0);",
255
+ },
256
+ },
257
+ ],
258
+ },
259
+ ],
260
+ },
261
+ ],
262
+ },
263
+ {
264
+ "_name": "LiveStore:queries",
265
+ "children": [
266
+ {
267
+ "_name": "js:all todos:first",
268
+ "children": [
269
+ {
270
+ "_name": "sql:select * from todos where completed = 0",
271
+ "attributes": {
272
+ "sql.query": "select * from todos where completed = 0",
273
+ "sql.rowsCount": 0,
274
+ },
275
+ "children": [
276
+ {
277
+ "_name": "js:where-filter",
278
+ },
279
+ {
280
+ "_name": "sql-in-memory-select",
281
+ "attributes": {
282
+ "sql.cached": false,
283
+ "sql.query": "select * from todos where completed = 0",
284
+ "sql.rowsCount": 0,
285
+ },
286
+ },
287
+ ],
288
+ },
289
+ ],
290
+ },
291
+ {
292
+ "_name": "js:all todos:first",
293
+ "children": [
294
+ {
295
+ "_name": "sql:select * from todos where completed = 0",
296
+ "attributes": {
297
+ "sql.query": "select * from todos where completed = 0",
298
+ "sql.rowsCount": 1,
299
+ },
300
+ "children": [
301
+ {
302
+ "_name": "sql-in-memory-select",
303
+ "attributes": {
304
+ "sql.cached": false,
305
+ "sql.query": "select * from todos where completed = 0",
306
+ "sql.rowsCount": 1,
307
+ },
308
+ },
309
+ ],
310
+ },
311
+ ],
312
+ },
313
+ ],
314
+ },
315
+ ],
316
+ }
317
+ `)
318
+ })
319
+ })
320
+
321
+ const compareHrTime = (a: [number, number], b: [number, number]) => {
322
+ if (a[0] !== b[0]) return a[0] - b[0]
323
+ return a[1] - b[1]
324
+ }
325
+
326
+ const omitEmpty = (obj: any) => {
327
+ const result: any = {}
328
+ for (const key in obj) {
329
+ if (
330
+ obj[key] !== undefined &&
331
+ !(Array.isArray(obj[key]) && obj[key].length === 0) &&
332
+ Object.keys(obj[key]).length > 0
333
+ ) {
334
+ result[key] = obj[key]
335
+ }
336
+ }
337
+ return result
338
+ }
339
+
340
+ const getSimplifiedRootSpan = (exporter: InMemorySpanExporter) => {
341
+ const spans = exporter.getFinishedSpans()
342
+ const spansMap = new Map<string, NestedSpan>(spans.map((span) => [span.spanContext().spanId, { span, children: [] }]))
343
+
344
+ spansMap.forEach((nestedSpan) => {
345
+ const parentSpan = nestedSpan.span.parentSpanId ? spansMap.get(nestedSpan.span.parentSpanId) : undefined
346
+ if (parentSpan) {
347
+ parentSpan.children.push(nestedSpan)
348
+ }
349
+ })
350
+
351
+ type NestedSpan = { span: ReadableSpan; children: NestedSpan[] }
352
+ const rootSpan = spansMap.get(spans.find((_) => _.name === 'test')!.spanContext().spanId)!
353
+
354
+ type SimplifiedNestedSpan = { _name: string; attributes: any; children: SimplifiedNestedSpan[] }
355
+
356
+ const simplifySpan = (span: NestedSpan): SimplifiedNestedSpan =>
357
+ omitEmpty({
358
+ _name: span.span.name,
359
+ attributes: span.span.attributes,
360
+ children: span.children
361
+ .filter((_) => _.span.name !== 'createStore')
362
+ .sort((a, b) => compareHrTime(a.span.startTime, b.span.startTime))
363
+ .map(simplifySpan),
364
+ })
365
+
366
+ // console.dir(
367
+ // spans.map((_) => [_.spanContext().spanId, _.name, _.attributes, _.parentSpanId]),
368
+ // { depth: 10 },
369
+ // )
370
+
371
+ return simplifySpan(rootSpan)
372
+ }
@@ -2,31 +2,35 @@ import type { Scope } from '@livestore/utils/effect'
2
2
  import { Context, Deferred, Duration, Effect, Layer, OtelTracer, pipe, Runtime } from '@livestore/utils/effect'
3
3
  import * as otel from '@opentelemetry/api'
4
4
  import type { GraphQLSchema } from 'graphql'
5
- import { mapValues } from 'lodash-es'
5
+ import initSqlite3Wasm from 'sqlite-esm'
6
6
 
7
- import type { Backend, BackendOptions } from '../backends/index.js'
8
7
  import type { InMemoryDatabase } from '../inMemoryDatabase.js'
9
8
  import type { Schema } from '../schema.js'
9
+ import type { StorageInit } from '../storage/index.js'
10
10
  import type { BaseGraphQLContext, GraphQLOptions, LiveStoreQuery, Store } from '../store.js'
11
11
  import { createStore } from '../store.js'
12
12
 
13
+ // NOTE we're starting to initialize the sqlite wasm binary here (already before calling `createStore`),
14
+ // so that it's ready when we need it
15
+ const sqlite3Promise = initSqlite3Wasm({
16
+ print: (message) => console.log(`[livestore sqlite] ${message}`),
17
+ printErr: (message) => console.error(`[livestore sqlite] ${message}`),
18
+ })
19
+
13
20
  // TODO get rid of `LiveStoreContext` wrapper and only expose the `Store` directly
14
21
  export type LiveStoreContext = {
15
- store: Store<any>
16
- globalQueries: LiveStoreQueryTypes
22
+ store: Store
17
23
  }
18
24
 
19
- export type QueryDefinition = (store: Store<any>) => LiveStoreQuery
20
- export type GlobalQueryDefs = { [key: string]: QueryDefinition }
25
+ export type QueryDefinition = (store: Store) => LiveStoreQuery
21
26
 
22
27
  export type LiveStoreCreateStoreOptions<GraphQLContext extends BaseGraphQLContext> = {
23
28
  schema: Schema
24
- globalQueryDefs: GlobalQueryDefs
25
- backendOptions: BackendOptions
29
+ loadStorage: () => StorageInit | Promise<StorageInit>
26
30
  graphQLOptions?: GraphQLOptions<GraphQLContext>
27
31
  otelTracer?: otel.Tracer
28
32
  otelRootSpanContext?: otel.Context
29
- boot?: (backend: Backend, parentSpan: otel.Span) => Promise<void>
33
+ boot?: (db: InMemoryDatabase, parentSpan: otel.Span) => unknown | Promise<unknown>
30
34
  }
31
35
 
32
36
  export const LiveStoreContext = Context.Tag<LiveStoreContext>('@livestore/livestore/LiveStoreContext')
@@ -40,13 +44,12 @@ export const DeferredStoreContext = Context.Tag<DeferredStoreContext>(
40
44
 
41
45
  export type LiveStoreContextProps<GraphQLContext extends BaseGraphQLContext> = {
42
46
  schema: Schema
43
- globalQueryDefs?: Effect.Effect<never, never, GlobalQueryDefs>
44
- backendOptions: Effect.Effect<never, never, BackendOptions>
47
+ loadStorage: () => StorageInit | Promise<StorageInit>
45
48
  graphQLOptions?: {
46
49
  schema: Effect.Effect<otel.Tracer, never, GraphQLSchema>
47
50
  makeContext: (db: InMemoryDatabase) => GraphQLContext
48
51
  }
49
- boot?: (backend: Backend) => Effect.Effect<never, never, void>
52
+ boot?: (db: InMemoryDatabase) => Effect.Effect<never, never, void>
50
53
  }
51
54
 
52
55
  export const LiveStoreContextLayer = <GraphQLContext extends BaseGraphQLContext>(
@@ -60,9 +63,8 @@ export const LiveStoreContextLayer = <GraphQLContext extends BaseGraphQLContext>
60
63
  export const LiveStoreContextDeferred = Layer.effect(DeferredStoreContext, Deferred.make<never, LiveStoreContext>())
61
64
 
62
65
  export const makeLiveStoreContext = <GraphQLContext extends BaseGraphQLContext>({
63
- globalQueryDefs,
64
66
  schema,
65
- backendOptions: backendOptions_,
67
+ loadStorage,
66
68
  graphQLOptions: graphQLOptions_,
67
69
  boot: boot_,
68
70
  }: LiveStoreContextProps<GraphQLContext>): Effect.Effect<
@@ -84,22 +86,23 @@ export const makeLiveStoreContext = <GraphQLContext extends BaseGraphQLContext>(
84
86
  : Effect.succeed(undefined),
85
87
  )
86
88
 
87
- const backendOptions = yield* $(backendOptions_)
88
-
89
89
  const boot = boot_
90
- ? (db: Backend) =>
90
+ ? (db: InMemoryDatabase) =>
91
91
  boot_(db).pipe(Effect.withSpan('boot'), Effect.tapCauseLogPretty, Runtime.runPromise(runtime))
92
92
  : undefined
93
93
 
94
+ const sqlite3 = yield* $(Effect.promise(() => sqlite3Promise))
95
+
94
96
  const store = yield* $(
95
97
  Effect.tryPromise(() =>
96
98
  createStore({
97
99
  schema,
98
- backendOptions,
100
+ loadStorage,
99
101
  graphQLOptions,
100
102
  otelTracer,
101
103
  otelRootSpanContext,
102
104
  boot,
105
+ sqlite3,
103
106
  }),
104
107
  ),
105
108
  Effect.acquireRelease((store) => Effect.sync(() => store.destroy())),
@@ -107,19 +110,7 @@ export const makeLiveStoreContext = <GraphQLContext extends BaseGraphQLContext>(
107
110
 
108
111
  window.__debugLiveStore = store
109
112
 
110
- // TODO remove global queries concept
111
- const globalQueries = yield* $(
112
- globalQueryDefs ?? Effect.succeed({} as GlobalQueryDefs),
113
- Effect.map((defs) => mapValues(defs, (queryDef) => queryDef(store))),
114
- Effect.withSpan('LiveStore:makeGlobalQueries', {
115
- parent: OtelTracer.makeExternalSpan(otel.trace.getSpanContext(store.otel.queriesSpanContext)!),
116
- }),
117
- )
118
-
119
- // NOTE give main thread a chance to render
120
- yield* $(Effect.yieldNow())
121
-
122
- return { store, globalQueries }
113
+ return { store }
123
114
  }),
124
115
  Effect.tap((storeCtx) => Effect.flatMap(DeferredStoreContext, (def) => Deferred.succeed(def, storeCtx))),
125
116
  Effect.timeoutFail({
package/src/events.ts CHANGED
@@ -5,4 +5,4 @@ export type LiveStoreEvent = {
5
5
  args?: any
6
6
  }
7
7
 
8
- export const EVENTS_TABLE_NAME = '__events'
8
+ export const EVENTS_TABLE_NAME = '__livestore_events'