@livestore/livestore 0.0.56-dev.2 → 0.0.56
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/SynchronousDatabaseWrapper.d.ts.map +1 -1
- package/dist/SynchronousDatabaseWrapper.js +6 -15
- package/dist/SynchronousDatabaseWrapper.js.map +1 -1
- package/dist/__tests__/react/fixture.d.ts +3 -4
- package/dist/__tests__/react/fixture.d.ts.map +1 -1
- package/dist/__tests__/react/fixture.js +7 -5
- package/dist/__tests__/react/fixture.js.map +1 -1
- package/dist/effect/LiveStore.d.ts +4 -24
- package/dist/effect/LiveStore.d.ts.map +1 -1
- package/dist/effect/LiveStore.js +2 -1
- package/dist/effect/LiveStore.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/react/LiveStoreContext.d.ts +1 -2
- package/dist/react/LiveStoreContext.d.ts.map +1 -1
- package/dist/react/LiveStoreProvider.d.ts +5 -13
- package/dist/react/LiveStoreProvider.d.ts.map +1 -1
- package/dist/react/LiveStoreProvider.js +25 -12
- package/dist/react/LiveStoreProvider.js.map +1 -1
- package/dist/react/LiveStoreProvider.test.js +1 -1
- package/dist/react/LiveStoreProvider.test.js.map +1 -1
- package/dist/react/useQuery.test.js +7 -7
- package/dist/react/useQuery.test.js.map +1 -1
- package/dist/react/useRow.test.js +52 -46
- package/dist/react/useRow.test.js.map +1 -1
- package/dist/react/useTemporaryQuery.test.js +4 -4
- package/dist/react/useTemporaryQuery.test.js.map +1 -1
- package/dist/reactiveQueries/sql.test.js +34 -33
- package/dist/reactiveQueries/sql.test.js.map +1 -1
- package/dist/store-context.d.ts +26 -0
- package/dist/store-context.d.ts.map +1 -0
- package/dist/store-context.js +6 -0
- package/dist/store-context.js.map +1 -0
- package/dist/store-devtools.d.ts +1 -1
- package/dist/store-devtools.d.ts.map +1 -1
- package/dist/store-devtools.js +5 -0
- package/dist/store-devtools.js.map +1 -1
- package/dist/store.d.ts +8 -23
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +30 -35
- package/dist/store.js.map +1 -1
- package/package.json +5 -5
- package/src/SynchronousDatabaseWrapper.ts +7 -15
- package/src/__tests__/react/fixture.tsx +53 -50
- package/src/effect/LiveStore.ts +5 -34
- package/src/index.ts +2 -10
- package/src/react/LiveStoreProvider.test.tsx +1 -1
- package/src/react/LiveStoreProvider.tsx +37 -19
- package/src/react/useQuery.test.tsx +53 -51
- package/src/react/useRow.test.tsx +237 -224
- package/src/react/useTemporaryQuery.test.tsx +46 -45
- package/src/reactiveQueries/sql.test.ts +36 -33
- package/src/store-context.ts +23 -0
- package/src/store-devtools.ts +8 -0
- package/src/store.ts +55 -59
- package/vitest.config.js +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Schema } from '@livestore/utils/effect'
|
|
1
|
+
import { Effect, Schema } from '@livestore/utils/effect'
|
|
2
2
|
import * as otel from '@opentelemetry/api'
|
|
3
3
|
import { BasicTracerProvider, InMemorySpanExporter, SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base'
|
|
4
4
|
import { describe, expect, it } from 'vitest'
|
|
@@ -17,7 +17,7 @@ TODO write tests for:
|
|
|
17
17
|
describe('otel', () => {
|
|
18
18
|
let cachedProvider: BasicTracerProvider | undefined
|
|
19
19
|
|
|
20
|
-
const makeQuery =
|
|
20
|
+
const makeQuery = Effect.gen(function* () {
|
|
21
21
|
const exporter = new InMemorySpanExporter()
|
|
22
22
|
|
|
23
23
|
const provider = cachedProvider ?? new BasicTracerProvider()
|
|
@@ -30,31 +30,30 @@ describe('otel', () => {
|
|
|
30
30
|
const span = otelTracer.startSpan('test')
|
|
31
31
|
const otelContext = otel.trace.setSpan(otel.context.active(), span)
|
|
32
32
|
|
|
33
|
-
const { store } =
|
|
33
|
+
const { store } = yield* makeTodoMvc({ otelTracer, otelContext })
|
|
34
34
|
|
|
35
35
|
return {
|
|
36
|
-
[Symbol.dispose]: () => store.destroy(),
|
|
37
36
|
store,
|
|
38
37
|
otelTracer,
|
|
39
38
|
exporter,
|
|
40
39
|
span,
|
|
41
40
|
provider,
|
|
42
41
|
}
|
|
43
|
-
}
|
|
42
|
+
})
|
|
44
43
|
|
|
45
44
|
it('otel', async () => {
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
const { exporter } = await Effect.gen(function* () {
|
|
46
|
+
const { store, exporter, span } = yield* makeQuery
|
|
48
47
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
48
|
+
const query = querySQL(`select * from todos`, {
|
|
49
|
+
schema: Schema.Array(tables.todos.schema),
|
|
50
|
+
queriedTables: new Set(['todos']),
|
|
51
|
+
})
|
|
52
|
+
expect(query.run()).toMatchInlineSnapshot('[]')
|
|
54
53
|
|
|
55
|
-
|
|
54
|
+
store.mutate(rawSqlMutation({ sql: sql`INSERT INTO todos (id, text, completed) VALUES ('t1', 'buy milk', 0)` }))
|
|
56
55
|
|
|
57
|
-
|
|
56
|
+
expect(query.run()).toMatchInlineSnapshot(`
|
|
58
57
|
[
|
|
59
58
|
{
|
|
60
59
|
"completed": false,
|
|
@@ -64,9 +63,11 @@ describe('otel', () => {
|
|
|
64
63
|
]
|
|
65
64
|
`)
|
|
66
65
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
66
|
+
query.destroy()
|
|
67
|
+
span.end()
|
|
68
|
+
|
|
69
|
+
return { exporter }
|
|
70
|
+
}).pipe(Effect.scoped, Effect.tapCauseLogPretty, Effect.runPromise)
|
|
70
71
|
|
|
71
72
|
expect(getSimplifiedRootSpan(exporter)).toMatchInlineSnapshot(`
|
|
72
73
|
{
|
|
@@ -101,7 +102,7 @@ describe('otel', () => {
|
|
|
101
102
|
},
|
|
102
103
|
"children": [
|
|
103
104
|
{
|
|
104
|
-
"_name": "LiveStore:
|
|
105
|
+
"_name": "LiveStore:mutateWithoutRefresh",
|
|
105
106
|
"attributes": {
|
|
106
107
|
"livestore.args": "{
|
|
107
108
|
"sql": "INSERT INTO todos (id, text, completed) VALUES ('t1', 'buy milk', 0)"
|
|
@@ -168,18 +169,18 @@ describe('otel', () => {
|
|
|
168
169
|
})
|
|
169
170
|
|
|
170
171
|
it('with thunks', async () => {
|
|
171
|
-
|
|
172
|
-
|
|
172
|
+
const { exporter } = await Effect.gen(function* () {
|
|
173
|
+
const { store, exporter, span } = yield* makeQuery
|
|
173
174
|
|
|
174
|
-
|
|
175
|
+
const defaultTodo = { id: '', text: '', completed: false }
|
|
175
176
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
177
|
+
const filter = computed(() => `where completed = 0`, { label: 'where-filter' })
|
|
178
|
+
const query = querySQL((get) => `select * from todos ${get(filter)}`, {
|
|
179
|
+
label: 'all todos',
|
|
180
|
+
schema: Schema.Array(tables.todos.schema).pipe(Schema.headOrElse(() => defaultTodo)),
|
|
181
|
+
})
|
|
181
182
|
|
|
182
|
-
|
|
183
|
+
expect(query.run()).toMatchInlineSnapshot(`
|
|
183
184
|
{
|
|
184
185
|
"completed": false,
|
|
185
186
|
"id": "",
|
|
@@ -187,9 +188,9 @@ describe('otel', () => {
|
|
|
187
188
|
}
|
|
188
189
|
`)
|
|
189
190
|
|
|
190
|
-
|
|
191
|
+
store.mutate(rawSqlMutation({ sql: sql`INSERT INTO todos (id, text, completed) VALUES ('t1', 'buy milk', 0)` }))
|
|
191
192
|
|
|
192
|
-
|
|
193
|
+
expect(query.run()).toMatchInlineSnapshot(`
|
|
193
194
|
{
|
|
194
195
|
"completed": false,
|
|
195
196
|
"id": "t1",
|
|
@@ -197,9 +198,11 @@ describe('otel', () => {
|
|
|
197
198
|
}
|
|
198
199
|
`)
|
|
199
200
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
201
|
+
query.destroy()
|
|
202
|
+
span.end()
|
|
203
|
+
|
|
204
|
+
return { exporter }
|
|
205
|
+
}).pipe(Effect.scoped, Effect.tapCauseLogPretty, Effect.runPromise)
|
|
203
206
|
|
|
204
207
|
expect(getSimplifiedRootSpan(exporter)).toMatchInlineSnapshot(`
|
|
205
208
|
{
|
|
@@ -234,7 +237,7 @@ describe('otel', () => {
|
|
|
234
237
|
},
|
|
235
238
|
"children": [
|
|
236
239
|
{
|
|
237
|
-
"_name": "LiveStore:
|
|
240
|
+
"_name": "LiveStore:mutateWithoutRefresh",
|
|
238
241
|
"attributes": {
|
|
239
242
|
"livestore.args": "{
|
|
240
243
|
"sql": "INSERT INTO todos (id, text, completed) VALUES ('t1', 'buy milk', 0)"
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { IntentionalShutdownCause, UnexpectedError } from '@livestore/common'
|
|
2
|
+
import { Schema } from '@livestore/utils/effect'
|
|
3
|
+
|
|
4
|
+
import type { Store } from './store.js'
|
|
5
|
+
|
|
6
|
+
export type LiveStoreContext =
|
|
7
|
+
| LiveStoreContextRunning
|
|
8
|
+
| {
|
|
9
|
+
stage: 'error'
|
|
10
|
+
error: UnexpectedError | unknown
|
|
11
|
+
}
|
|
12
|
+
| {
|
|
13
|
+
stage: 'shutdown'
|
|
14
|
+
cause: IntentionalShutdownCause | StoreAbort
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export class StoreAbort extends Schema.TaggedError<StoreAbort>()('LiveStore.StoreAbort', {}) {}
|
|
18
|
+
export class StoreInterrupted extends Schema.TaggedError<StoreInterrupted>()('LiveStore.StoreInterrupted', {}) {}
|
|
19
|
+
|
|
20
|
+
export type LiveStoreContextRunning = {
|
|
21
|
+
stage: 'running'
|
|
22
|
+
store: Store
|
|
23
|
+
}
|
package/src/store-devtools.ts
CHANGED
|
@@ -35,6 +35,14 @@ export const connectDevtoolsToStore = ({
|
|
|
35
35
|
const liveQueriesSubscriptions: SubMap = new Map()
|
|
36
36
|
const debugInfoHistorySubscriptions: SubMap = new Map()
|
|
37
37
|
|
|
38
|
+
yield* Effect.addFinalizer(() =>
|
|
39
|
+
Effect.sync(() => {
|
|
40
|
+
reactivityGraphSubcriptions.forEach((unsub) => unsub())
|
|
41
|
+
liveQueriesSubscriptions.forEach((unsub) => unsub())
|
|
42
|
+
debugInfoHistorySubscriptions.forEach((unsub) => unsub())
|
|
43
|
+
}),
|
|
44
|
+
)
|
|
45
|
+
|
|
38
46
|
const sendToDevtools = (message: Devtools.MessageFromAppHostStore) =>
|
|
39
47
|
storeDevtoolsChannel.send(message).pipe(Effect.tapCauseLogPretty, Effect.runSync)
|
|
40
48
|
|
package/src/store.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
BootDb,
|
|
3
3
|
BootStatus,
|
|
4
|
+
IntentionalShutdownCause,
|
|
4
5
|
ParamsObject,
|
|
5
6
|
PreparedBindValues,
|
|
6
|
-
ResetMode,
|
|
7
7
|
StoreAdapter,
|
|
8
8
|
StoreAdapterFactory,
|
|
9
9
|
StoreDevtoolsChannel,
|
|
@@ -12,8 +12,8 @@ import { getExecArgsFromMutation, prepareBindValues, UnexpectedError } from '@li
|
|
|
12
12
|
import type { LiveStoreSchema, MutationEvent } from '@livestore/common/schema'
|
|
13
13
|
import { makeMutationEventSchemaMemo, SCHEMA_META_TABLE, SCHEMA_MUTATIONS_META_TABLE } from '@livestore/common/schema'
|
|
14
14
|
import { assertNever, makeNoopTracer, shouldNeverHappen } from '@livestore/utils'
|
|
15
|
-
import type { Cause } from '@livestore/utils/effect'
|
|
16
15
|
import {
|
|
16
|
+
Cause,
|
|
17
17
|
Deferred,
|
|
18
18
|
Duration,
|
|
19
19
|
Effect,
|
|
@@ -59,9 +59,6 @@ export type OtelOptions = {
|
|
|
59
59
|
rootSpanContext: otel.Context
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
export class ForceStoreShutdown extends Schema.TaggedError<ForceStoreShutdown>()('LiveStore.ForceStoreShutdown', {}) {}
|
|
63
|
-
export class StoreShutdown extends Schema.TaggedError<StoreShutdown>()('LiveStore.StoreShutdown', {}) {}
|
|
64
|
-
|
|
65
62
|
export type StoreOptions<
|
|
66
63
|
TGraphQLContext extends BaseGraphQLContext,
|
|
67
64
|
TSchema extends LiveStoreSchema = LiveStoreSchema,
|
|
@@ -74,6 +71,7 @@ export type StoreOptions<
|
|
|
74
71
|
reactivityGraph: ReactivityGraph
|
|
75
72
|
disableDevtools?: boolean
|
|
76
73
|
fiberSet: FiberSet.FiberSet
|
|
74
|
+
runtime: Runtime.Runtime<Scope.Scope>
|
|
77
75
|
// TODO remove this temporary solution and find a better way to avoid re-processing the same mutation
|
|
78
76
|
__processedMutationIds: Set<string>
|
|
79
77
|
}
|
|
@@ -125,12 +123,15 @@ export type StoreMutateOptions = {
|
|
|
125
123
|
persisted?: boolean
|
|
126
124
|
}
|
|
127
125
|
|
|
126
|
+
if (typeof window !== 'undefined') {
|
|
127
|
+
window.__debugDownloadBlob = downloadBlob
|
|
128
|
+
}
|
|
129
|
+
|
|
128
130
|
export class Store<
|
|
129
131
|
TGraphQLContext extends BaseGraphQLContext = BaseGraphQLContext,
|
|
130
132
|
TSchema extends LiveStoreSchema = LiveStoreSchema,
|
|
131
133
|
> extends Inspectable.Class {
|
|
132
134
|
id = uniqueStoreId()
|
|
133
|
-
private fiberSet: FiberSet.FiberSet
|
|
134
135
|
reactivityGraph: ReactivityGraph
|
|
135
136
|
syncDbWrapper: SynchronousDatabaseWrapper
|
|
136
137
|
adapter: StoreAdapter
|
|
@@ -144,6 +145,9 @@ export class Store<
|
|
|
144
145
|
*/
|
|
145
146
|
tableRefs: { [key: string]: Ref<null, QueryContext, RefreshReason> }
|
|
146
147
|
|
|
148
|
+
private fiberSet: FiberSet.FiberSet
|
|
149
|
+
private runtime: Runtime.Runtime<Scope.Scope>
|
|
150
|
+
|
|
147
151
|
// TODO remove this temporary solution and find a better way to avoid re-processing the same mutation
|
|
148
152
|
private __processedMutationIds
|
|
149
153
|
private __processedMutationWithoutRefreshIds = new Set<string>()
|
|
@@ -163,6 +167,7 @@ export class Store<
|
|
|
163
167
|
disableDevtools,
|
|
164
168
|
__processedMutationIds,
|
|
165
169
|
fiberSet,
|
|
170
|
+
runtime,
|
|
166
171
|
}: StoreOptions<TGraphQLContext, TSchema>) {
|
|
167
172
|
super()
|
|
168
173
|
|
|
@@ -171,6 +176,7 @@ export class Store<
|
|
|
171
176
|
this.schema = schema
|
|
172
177
|
|
|
173
178
|
this.fiberSet = fiberSet
|
|
179
|
+
this.runtime = runtime
|
|
174
180
|
|
|
175
181
|
// TODO refactor
|
|
176
182
|
this.__mutationEventSchema = makeMutationEventSchemaMemo(schema)
|
|
@@ -254,7 +260,7 @@ export class Store<
|
|
|
254
260
|
)
|
|
255
261
|
|
|
256
262
|
yield* Effect.never
|
|
257
|
-
}).pipe(Effect.scoped, Effect.withSpan('LiveStore:
|
|
263
|
+
}).pipe(Effect.scoped, Effect.withSpan('LiveStore:constructor'), this.runEffectFork)
|
|
258
264
|
}
|
|
259
265
|
// #endregion constructor
|
|
260
266
|
|
|
@@ -263,7 +269,7 @@ export class Store<
|
|
|
263
269
|
parentSpan: otel.Span,
|
|
264
270
|
): Store<TGraphQLContext, TSchema> => {
|
|
265
271
|
const ctx = otel.trace.setSpan(otel.context.active(), parentSpan)
|
|
266
|
-
return storeOptions.otelOptions.tracer.startActiveSpan('LiveStore:
|
|
272
|
+
return storeOptions.otelOptions.tracer.startActiveSpan('LiveStore:createStore', {}, ctx, (span) => {
|
|
267
273
|
try {
|
|
268
274
|
return new Store(storeOptions)
|
|
269
275
|
} finally {
|
|
@@ -315,15 +321,6 @@ export class Store<
|
|
|
315
321
|
},
|
|
316
322
|
)
|
|
317
323
|
|
|
318
|
-
/**
|
|
319
|
-
* Destroys the entire store, including all queries and subscriptions.
|
|
320
|
-
*
|
|
321
|
-
* Currently only used when shutting down the app for debugging purposes (e.g. to close Otel spans).
|
|
322
|
-
*/
|
|
323
|
-
destroy = async () => {
|
|
324
|
-
await FiberSet.clear(this.fiberSet).pipe(Effect.withSpan('Store:destroy'), runEffectPromise)
|
|
325
|
-
}
|
|
326
|
-
|
|
327
324
|
// #region mutate
|
|
328
325
|
mutate: {
|
|
329
326
|
<const TMutationArg extends ReadonlyArray<MutationEvent.ForSchema<TSchema>>>(...list: TMutationArg): void
|
|
@@ -509,7 +506,7 @@ export class Store<
|
|
|
509
506
|
const { otelContext, coordinatorMode = 'default' } = options
|
|
510
507
|
|
|
511
508
|
return this.otel.tracer.startActiveSpan(
|
|
512
|
-
'LiveStore:
|
|
509
|
+
'LiveStore:mutateWithoutRefresh',
|
|
513
510
|
{
|
|
514
511
|
attributes: {
|
|
515
512
|
'livestore.mutation': mutationEventDecoded.mutation,
|
|
@@ -548,7 +545,7 @@ export class Store<
|
|
|
548
545
|
// Asynchronously apply mutation to a persistent storage (we're not awaiting this promise here)
|
|
549
546
|
this.adapter.coordinator
|
|
550
547
|
.mutate(mutationEventEncoded as MutationEvent.AnyEncoded, { persisted: coordinatorMode !== 'skip-persist' })
|
|
551
|
-
.pipe(
|
|
548
|
+
.pipe(Runtime.runFork(this.runtime))
|
|
552
549
|
}
|
|
553
550
|
|
|
554
551
|
// Uncomment to print a list of queries currently registered on the store
|
|
@@ -575,14 +572,14 @@ export class Store<
|
|
|
575
572
|
) => {
|
|
576
573
|
this.syncDbWrapper.execute(query, prepareBindValues(params, query), writeTables, { otelContext })
|
|
577
574
|
|
|
578
|
-
this.adapter.coordinator.execute(query, prepareBindValues(params, query)).pipe(runEffectFork)
|
|
575
|
+
this.adapter.coordinator.execute(query, prepareBindValues(params, query)).pipe(this.runEffectFork)
|
|
579
576
|
}
|
|
580
577
|
|
|
581
578
|
select = (query: string, params: ParamsObject = {}) => {
|
|
582
579
|
return this.syncDbWrapper.select(query, { bindValues: prepareBindValues(params, query) })
|
|
583
580
|
}
|
|
584
581
|
|
|
585
|
-
makeTableRef = (tableName: string) =>
|
|
582
|
+
private makeTableRef = (tableName: string) =>
|
|
586
583
|
this.reactivityGraph.makeRef(null, {
|
|
587
584
|
equal: () => false,
|
|
588
585
|
label: `tableRef:${tableName}`,
|
|
@@ -594,13 +591,11 @@ export class Store<
|
|
|
594
591
|
downloadBlob(data, `livestore-${Date.now()}.db`)
|
|
595
592
|
}
|
|
596
593
|
|
|
597
|
-
__devDownloadMutationLogDb =
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
// TODO allow for graceful store reset without requiring a full page reload (which should also call .boot)
|
|
603
|
-
dangerouslyResetStorage = (mode: ResetMode) => this.adapter.coordinator.dangerouslyReset(mode).pipe(runEffectPromise)
|
|
594
|
+
__devDownloadMutationLogDb = () =>
|
|
595
|
+
Effect.gen(this, function* () {
|
|
596
|
+
const data = yield* this.adapter.coordinator.getMutationLogData
|
|
597
|
+
downloadBlob(data, `livestore-mutationlog-${Date.now()}.db`)
|
|
598
|
+
}).pipe(this.runEffectFork)
|
|
604
599
|
|
|
605
600
|
// NOTE This is needed because when booting a Store via Effect it seems to call `toJSON` in the error path
|
|
606
601
|
toJSON = () => {
|
|
@@ -609,6 +604,9 @@ export class Store<
|
|
|
609
604
|
reactivityGraph: this.reactivityGraph.getSnapshot({ includeResults: true }),
|
|
610
605
|
}
|
|
611
606
|
}
|
|
607
|
+
|
|
608
|
+
private runEffectFork = <A, E>(effect: Effect.Effect<A, E, never>) =>
|
|
609
|
+
effect.pipe(Effect.tapCauseLogPretty, FiberSet.run(this.fiberSet), Runtime.runFork(this.runtime))
|
|
612
610
|
}
|
|
613
611
|
|
|
614
612
|
export type CreateStoreOptions<TGraphQLContext extends BaseGraphQLContext, TSchema extends LiveStoreSchema> = {
|
|
@@ -645,7 +643,14 @@ export const createStorePromise = async <
|
|
|
645
643
|
Effect.andThen((fiberSet) => createStore({ ...options, fiberSet })),
|
|
646
644
|
Scope.extend(scope),
|
|
647
645
|
)
|
|
648
|
-
}).pipe(
|
|
646
|
+
}).pipe(
|
|
647
|
+
Effect.withSpan('createStore'),
|
|
648
|
+
Effect.tapCauseLogPretty,
|
|
649
|
+
Effect.annotateLogs({ thread: 'window' }),
|
|
650
|
+
Effect.provide(Logger.pretty),
|
|
651
|
+
Logger.withMinimumLogLevel(LogLevel.Debug),
|
|
652
|
+
Effect.runPromise,
|
|
653
|
+
)
|
|
649
654
|
|
|
650
655
|
// #region createStore
|
|
651
656
|
export const createStore = <
|
|
@@ -695,21 +700,31 @@ export const createStore = <
|
|
|
695
700
|
yield* connectDevtoolsToStore({ storeDevtoolsChannel, store })
|
|
696
701
|
})
|
|
697
702
|
|
|
703
|
+
const runtime = yield* Effect.runtime<Scope.Scope>()
|
|
704
|
+
|
|
705
|
+
const runEffectFork = (effect: Effect.Effect<any, any, never>) =>
|
|
706
|
+
effect.pipe(Effect.tapCauseLogPretty, FiberSet.run(fiberSet), Runtime.runFork(runtime))
|
|
707
|
+
|
|
698
708
|
// TODO close parent scope? (Needs refactor with Mike A)
|
|
699
|
-
const shutdown = (cause: Cause.Cause<
|
|
709
|
+
const shutdown = (cause: Cause.Cause<UnexpectedError | IntentionalShutdownCause>) =>
|
|
700
710
|
Effect.gen(function* () {
|
|
701
|
-
|
|
711
|
+
// NOTE we're calling `cause.toString()` here to avoid triggering a `console.error` in the grouped log
|
|
712
|
+
const logCause =
|
|
713
|
+
Cause.isFailType(cause) && cause.error._tag === 'LiveStore.IntentionalShutdownCause'
|
|
714
|
+
? cause.toString()
|
|
715
|
+
: cause
|
|
716
|
+
yield* Effect.logDebug(`Shutting down LiveStore`, logCause)
|
|
702
717
|
|
|
703
718
|
FiberSet.clear(fiberSet).pipe(
|
|
704
|
-
Effect.andThen(() => FiberSet.run(fiberSet, Effect.
|
|
719
|
+
Effect.andThen(() => FiberSet.run(fiberSet, Effect.failCause(cause))),
|
|
705
720
|
Effect.timeout(Duration.seconds(1)),
|
|
706
721
|
Effect.logWarnIfTakesLongerThan({ label: '@livestore/livestore:shutdown:clear-fiber-set', duration: 500 }),
|
|
707
|
-
Effect.catchTag('TimeoutException', () =>
|
|
708
|
-
Effect.
|
|
709
|
-
Effect.andThen(FiberSet.run(fiberSet, Effect.
|
|
722
|
+
Effect.catchTag('TimeoutException', (err) =>
|
|
723
|
+
Effect.logError('Store shutdown timed out. Forcing shutdown.', err).pipe(
|
|
724
|
+
Effect.andThen(FiberSet.run(fiberSet, Effect.failCause(cause))),
|
|
710
725
|
),
|
|
711
726
|
),
|
|
712
|
-
|
|
727
|
+
Runtime.runFork(runtime), // NOTE we need to fork this separately otherwise it will also be interrupted
|
|
713
728
|
)
|
|
714
729
|
}).pipe(Effect.withSpan('livestore:shutdown'))
|
|
715
730
|
|
|
@@ -775,11 +790,11 @@ export const createStore = <
|
|
|
775
790
|
txn: (callback) => {
|
|
776
791
|
try {
|
|
777
792
|
isInTxn = true
|
|
778
|
-
adapter.syncDb.execute('BEGIN', undefined)
|
|
793
|
+
// adapter.syncDb.execute('BEGIN TRANSACTION', undefined)
|
|
779
794
|
|
|
780
795
|
callback()
|
|
781
796
|
|
|
782
|
-
adapter.syncDb.execute('COMMIT', undefined)
|
|
797
|
+
// adapter.syncDb.execute('COMMIT', undefined)
|
|
783
798
|
|
|
784
799
|
// adapter.coordinator.execute('BEGIN', undefined, undefined)
|
|
785
800
|
for (const [queryStr, bindValues] of txnExecuteStmnts) {
|
|
@@ -787,7 +802,7 @@ export const createStore = <
|
|
|
787
802
|
}
|
|
788
803
|
// adapter.coordinator.execute('COMMIT', undefined, undefined)
|
|
789
804
|
} catch (e: any) {
|
|
790
|
-
adapter.syncDb.execute('ROLLBACK', undefined)
|
|
805
|
+
// adapter.syncDb.execute('ROLLBACK', undefined)
|
|
791
806
|
throw e
|
|
792
807
|
} finally {
|
|
793
808
|
isInTxn = false
|
|
@@ -812,6 +827,7 @@ export const createStore = <
|
|
|
812
827
|
disableDevtools,
|
|
813
828
|
__processedMutationIds,
|
|
814
829
|
fiberSet,
|
|
830
|
+
runtime,
|
|
815
831
|
},
|
|
816
832
|
span,
|
|
817
833
|
)
|
|
@@ -829,23 +845,3 @@ export const createStore = <
|
|
|
829
845
|
)
|
|
830
846
|
}
|
|
831
847
|
// #endregion createStore
|
|
832
|
-
|
|
833
|
-
// TODO propagate runtime
|
|
834
|
-
const runEffectFork = <A, E>(effect: Effect.Effect<A, E, never>) =>
|
|
835
|
-
effect.pipe(
|
|
836
|
-
Effect.tapCauseLogPretty,
|
|
837
|
-
Effect.annotateLogs({ thread: 'window' }),
|
|
838
|
-
Effect.provide(Logger.pretty),
|
|
839
|
-
Logger.withMinimumLogLevel(LogLevel.Debug),
|
|
840
|
-
Effect.runFork,
|
|
841
|
-
)
|
|
842
|
-
|
|
843
|
-
// TODO propagate runtime
|
|
844
|
-
const runEffectPromise = <A, E>(effect: Effect.Effect<A, E, never>) =>
|
|
845
|
-
effect.pipe(
|
|
846
|
-
Effect.tapCauseLogPretty,
|
|
847
|
-
Effect.annotateLogs({ thread: 'window' }),
|
|
848
|
-
Effect.provide(Logger.pretty),
|
|
849
|
-
Logger.withMinimumLogLevel(LogLevel.Debug),
|
|
850
|
-
Effect.runPromise,
|
|
851
|
-
)
|
package/vitest.config.js
CHANGED