@livestore/livestore 0.4.0-dev.21 → 0.4.0-dev.23
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/README.md +0 -1
- package/dist/.tsbuildinfo +1 -1
- package/dist/QueryCache.js +1 -1
- package/dist/QueryCache.js.map +1 -1
- package/dist/SqliteDbWrapper.d.ts +5 -5
- package/dist/SqliteDbWrapper.d.ts.map +1 -1
- package/dist/SqliteDbWrapper.js +8 -8
- package/dist/SqliteDbWrapper.js.map +1 -1
- package/dist/SqliteDbWrapper.test.js +2 -2
- package/dist/SqliteDbWrapper.test.js.map +1 -1
- package/dist/effect/LiveStore.d.ts +130 -2
- package/dist/effect/LiveStore.d.ts.map +1 -1
- package/dist/effect/LiveStore.js +185 -6
- package/dist/effect/LiveStore.js.map +1 -1
- package/dist/effect/LiveStore.test.d.ts +2 -0
- package/dist/effect/LiveStore.test.d.ts.map +1 -0
- package/dist/effect/LiveStore.test.js +42 -0
- package/dist/effect/LiveStore.test.js.map +1 -0
- package/dist/effect/mod.d.ts +1 -1
- package/dist/effect/mod.d.ts.map +1 -1
- package/dist/effect/mod.js +3 -1
- package/dist/effect/mod.js.map +1 -1
- package/dist/live-queries/base-class.d.ts +3 -3
- package/dist/live-queries/base-class.d.ts.map +1 -1
- package/dist/live-queries/base-class.js +2 -2
- package/dist/live-queries/base-class.js.map +1 -1
- package/dist/live-queries/client-document-get-query.d.ts +1 -1
- package/dist/live-queries/client-document-get-query.d.ts.map +1 -1
- package/dist/live-queries/client-document-get-query.js +1 -1
- package/dist/live-queries/client-document-get-query.js.map +1 -1
- package/dist/live-queries/computed.d.ts.map +1 -1
- package/dist/live-queries/computed.js +2 -2
- package/dist/live-queries/computed.js.map +1 -1
- package/dist/live-queries/db-query.js +14 -14
- package/dist/live-queries/db-query.js.map +1 -1
- package/dist/live-queries/db-query.test.js +2 -2
- package/dist/live-queries/db-query.test.js.map +1 -1
- package/dist/live-queries/signal.test.js +2 -2
- package/dist/live-queries/signal.test.js.map +1 -1
- package/dist/mod.d.ts +2 -1
- package/dist/mod.d.ts.map +1 -1
- package/dist/mod.js +1 -0
- package/dist/mod.js.map +1 -1
- package/dist/reactive.d.ts +9 -9
- package/dist/reactive.d.ts.map +1 -1
- package/dist/reactive.js +9 -26
- package/dist/reactive.js.map +1 -1
- package/dist/reactive.test.js +2 -2
- package/dist/reactive.test.js.map +1 -1
- package/dist/store/StoreRegistry.d.ts +215 -0
- package/dist/store/StoreRegistry.d.ts.map +1 -0
- package/dist/store/StoreRegistry.js +267 -0
- package/dist/store/StoreRegistry.js.map +1 -0
- package/dist/store/StoreRegistry.test.d.ts +2 -0
- package/dist/store/StoreRegistry.test.d.ts.map +1 -0
- package/dist/store/StoreRegistry.test.js +381 -0
- package/dist/store/StoreRegistry.test.js.map +1 -0
- package/dist/store/create-store.d.ts +56 -6
- package/dist/store/create-store.d.ts.map +1 -1
- package/dist/store/create-store.js +32 -7
- package/dist/store/create-store.js.map +1 -1
- package/dist/store/devtools.d.ts +1 -1
- package/dist/store/devtools.d.ts.map +1 -1
- package/dist/store/devtools.js +16 -3
- package/dist/store/devtools.js.map +1 -1
- package/dist/store/store-eventstream.test.js +2 -2
- package/dist/store/store-eventstream.test.js.map +1 -1
- package/dist/store/store-types.d.ts +59 -9
- package/dist/store/store-types.d.ts.map +1 -1
- package/dist/store/store-types.js.map +1 -1
- package/dist/store/store-types.test.js +1 -1
- package/dist/store/store-types.test.js.map +1 -1
- package/dist/store/store.d.ts +102 -6
- package/dist/store/store.d.ts.map +1 -1
- package/dist/store/store.js +148 -47
- package/dist/store/store.js.map +1 -1
- package/dist/utils/dev.js.map +1 -1
- package/dist/utils/stack-info.js +2 -2
- package/dist/utils/stack-info.js.map +1 -1
- package/dist/utils/tests/fixture.d.ts +1 -1
- package/dist/utils/tests/fixture.d.ts.map +1 -1
- package/dist/utils/tests/fixture.js.map +1 -1
- package/dist/utils/tests/otel.d.ts.map +1 -1
- package/dist/utils/tests/otel.js +5 -5
- package/dist/utils/tests/otel.js.map +1 -1
- package/package.json +59 -18
- package/src/QueryCache.ts +1 -1
- package/src/SqliteDbWrapper.test.ts +4 -2
- package/src/SqliteDbWrapper.ts +12 -11
- package/src/ambient.d.ts +0 -7
- package/src/effect/LiveStore.test.ts +61 -0
- package/src/effect/LiveStore.ts +381 -8
- package/src/effect/mod.ts +13 -1
- package/src/live-queries/__snapshots__/db-query.test.ts.snap +336 -231
- package/src/live-queries/base-class.ts +7 -6
- package/src/live-queries/client-document-get-query.ts +4 -2
- package/src/live-queries/computed.ts +3 -2
- package/src/live-queries/db-query.test.ts +3 -2
- package/src/live-queries/db-query.ts +15 -15
- package/src/live-queries/signal.test.ts +3 -2
- package/src/mod.ts +2 -0
- package/src/reactive.test.ts +3 -2
- package/src/reactive.ts +22 -23
- package/src/store/StoreRegistry.test.ts +540 -0
- package/src/store/StoreRegistry.ts +418 -0
- package/src/store/create-store.ts +76 -15
- package/src/store/devtools.ts +20 -6
- package/src/store/store-eventstream.test.ts +4 -2
- package/src/store/store-types.test.ts +3 -1
- package/src/store/store-types.ts +64 -13
- package/src/store/store.ts +197 -60
- package/src/utils/dev.ts +2 -2
- package/src/utils/stack-info.ts +2 -2
- package/src/utils/tests/fixture.ts +2 -1
- package/src/utils/tests/otel.ts +8 -7
- package/docs/api/index.md +0 -3
- package/docs/building-with-livestore/complex-ui-state/index.md +0 -5
- package/docs/building-with-livestore/crud/index.md +0 -5
- package/docs/building-with-livestore/data-modeling/index.md +0 -1
- package/docs/building-with-livestore/debugging/index.md +0 -17
- package/docs/building-with-livestore/devtools/index.md +0 -79
- package/docs/building-with-livestore/events/index.md +0 -355
- package/docs/building-with-livestore/examples/ai-agent/index.md +0 -5
- package/docs/building-with-livestore/examples/index.md +0 -30
- package/docs/building-with-livestore/examples/todo-workspaces/index.md +0 -891
- package/docs/building-with-livestore/examples/turnbased-game/index.md +0 -7
- package/docs/building-with-livestore/opentelemetry/index.md +0 -208
- package/docs/building-with-livestore/production-checklist/index.md +0 -5
- package/docs/building-with-livestore/reactivity-system/index.md +0 -202
- package/docs/building-with-livestore/rules-for-ai-agents/index.md +0 -9
- package/docs/building-with-livestore/state/materializers/index.md +0 -300
- package/docs/building-with-livestore/state/sql-queries/index.md +0 -72
- package/docs/building-with-livestore/state/sqlite/index.md +0 -45
- package/docs/building-with-livestore/state/sqlite-schema/index.md +0 -306
- package/docs/building-with-livestore/state/sqlite-schema-effect/index.md +0 -300
- package/docs/building-with-livestore/store/index.md +0 -281
- package/docs/building-with-livestore/syncing/index.md +0 -136
- package/docs/building-with-livestore/tools/cli/index.md +0 -177
- package/docs/building-with-livestore/tools/mcp/index.md +0 -187
- package/docs/examples/cloudflare-adapter/index.md +0 -44
- package/docs/examples/expo-adapter/index.md +0 -44
- package/docs/examples/index.md +0 -55
- package/docs/examples/node-adapter/index.md +0 -44
- package/docs/examples/web-adapter/index.md +0 -52
- package/docs/framework-integrations/custom-elements/index.md +0 -142
- package/docs/framework-integrations/react-integration/index.md +0 -918
- package/docs/framework-integrations/solid-integration/index.md +0 -293
- package/docs/framework-integrations/svelte-integration/index.md +0 -42
- package/docs/framework-integrations/vue-integration/index.md +0 -294
- package/docs/getting-started/expo/index.md +0 -736
- package/docs/getting-started/node/index.md +0 -115
- package/docs/getting-started/react-web/index.md +0 -573
- package/docs/getting-started/solid/index.md +0 -3
- package/docs/getting-started/vue/index.md +0 -471
- package/docs/index.md +0 -209
- package/docs/llms.txt +0 -147
- package/docs/misc/CODE_OF_CONDUCT/index.md +0 -133
- package/docs/misc/FAQ/index.md +0 -37
- package/docs/misc/community/index.md +0 -88
- package/docs/misc/credits/index.md +0 -14
- package/docs/misc/design-partners/index.md +0 -13
- package/docs/misc/package-management/index.md +0 -21
- package/docs/misc/performance/index.md +0 -25
- package/docs/misc/resources/index.md +0 -46
- package/docs/misc/state-of-the-project/index.md +0 -37
- package/docs/misc/troubleshooting/index.md +0 -82
- package/docs/overview/concepts/index.md +0 -78
- package/docs/overview/how-livestore-works/index.md +0 -56
- package/docs/overview/introduction/index.md +0 -5
- package/docs/overview/technology-comparison/index.md +0 -40
- package/docs/overview/when-livestore/index.md +0 -81
- package/docs/overview/why-livestore/index.md +0 -5
- package/docs/patterns/ai/index.md +0 -15
- package/docs/patterns/anonymous-user-transition/index.md +0 -10
- package/docs/patterns/app-evolution/index.md +0 -72
- package/docs/patterns/auth/index.md +0 -226
- package/docs/patterns/effect/index.md +0 -1495
- package/docs/patterns/encryption/index.md +0 -6
- package/docs/patterns/external-data/index.md +0 -5
- package/docs/patterns/file-management/index.md +0 -11
- package/docs/patterns/file-structure/index.md +0 -14
- package/docs/patterns/list-ordering/index.md +0 -369
- package/docs/patterns/offline/index.md +0 -32
- package/docs/patterns/orm/index.md +0 -18
- package/docs/patterns/presence/index.md +0 -11
- package/docs/patterns/rich-text-editing/index.md +0 -11
- package/docs/patterns/server-side-clients/index.md +0 -97
- package/docs/patterns/side-effects/index.md +0 -11
- package/docs/patterns/state-machines/index.md +0 -11
- package/docs/patterns/storybook/index.md +0 -192
- package/docs/patterns/undo-redo/index.md +0 -9
- package/docs/patterns/version-control/index.md +0 -8
- package/docs/platform-adapters/cloudflare-durable-object-adapter/index.md +0 -453
- package/docs/platform-adapters/electron-adapter/index.md +0 -15
- package/docs/platform-adapters/expo-adapter/index.md +0 -245
- package/docs/platform-adapters/node-adapter/index.md +0 -160
- package/docs/platform-adapters/tauri-adapter/index.md +0 -15
- package/docs/platform-adapters/web-adapter/index.md +0 -218
- package/docs/sustainable-open-source/contributing/docs/index.md +0 -94
- package/docs/sustainable-open-source/contributing/info/index.md +0 -63
- package/docs/sustainable-open-source/contributing/monorepo/index.md +0 -195
- package/docs/sustainable-open-source/sponsoring/index.md +0 -104
- package/docs/sync-providers/cloudflare/index.md +0 -773
- package/docs/sync-providers/custom/index.md +0 -65
- package/docs/sync-providers/electricsql/index.md +0 -159
- package/docs/sync-providers/s2/index.md +0 -230
- package/docs/tutorial/0-welcome/index.md +0 -48
- package/docs/tutorial/1-setup-starter-project/index.md +0 -105
- package/docs/tutorial/2-deploy-to-cloudflare/index.md +0 -195
- package/docs/tutorial/3-read-and-write-todos-via-livestore/index.md +0 -511
- package/docs/tutorial/4-sync-data-via-cloudflare/index.md +0 -210
- package/docs/tutorial/5-expand-business-logic/index.md +0 -174
- package/docs/tutorial/6-persist-ui-state/index.md +0 -453
- package/docs/tutorial/7-next-steps/index.md +0 -22
- package/docs/understanding-livestore/design-decisions/index.md +0 -33
- package/docs/understanding-livestore/event-sourcing/index.md +0 -40
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import type * as otel from '@opentelemetry/api'
|
|
2
|
+
|
|
1
3
|
import { isNotNil } from '@livestore/utils'
|
|
2
4
|
import { Equal, Hash, Predicate } from '@livestore/utils/effect'
|
|
3
|
-
import type * as otel from '@opentelemetry/api'
|
|
4
5
|
|
|
5
6
|
import * as RG from '../reactive.ts'
|
|
6
|
-
import type { Store } from '../store/store.ts'
|
|
7
7
|
import type { QueryDebugInfo, RefreshReason } from '../store/store-types.ts'
|
|
8
|
+
import type { Store } from '../store/store.ts'
|
|
8
9
|
import type { StackInfo } from '../utils/stack-info.ts'
|
|
9
10
|
|
|
10
11
|
export type ReactivityGraph = RG.ReactiveGraph<RefreshReason, QueryDebugInfo, ReactivityGraphContext>
|
|
@@ -272,8 +273,8 @@ export abstract class LiveStoreQueryBase<TResult> implements LiveQuery<TResult>
|
|
|
272
273
|
*/
|
|
273
274
|
export type GetAtomResult = <T>(
|
|
274
275
|
atom: RG.Atom<T, any, RefreshReason> | LiveQueryDef<T> | LiveQuery<T> | ISignal<T> | SignalDef<T>,
|
|
275
|
-
otelContext?: otel.Context
|
|
276
|
-
debugRefreshReason?: RefreshReason
|
|
276
|
+
otelContext?: otel.Context ,
|
|
277
|
+
debugRefreshReason?: RefreshReason ,
|
|
277
278
|
) => T
|
|
278
279
|
|
|
279
280
|
export type DependencyQueriesRef = Set<RcRef<LiveQuery.Any | ISignal<any>>>
|
|
@@ -298,7 +299,7 @@ export const makeGetAtomResult = (
|
|
|
298
299
|
}
|
|
299
300
|
|
|
300
301
|
// Signal case
|
|
301
|
-
if (atom._tag === 'signal' && Predicate.hasProperty(atom, 'ref')) {
|
|
302
|
+
if (atom._tag === 'signal' && Predicate.hasProperty(atom, 'ref') === true) {
|
|
302
303
|
return get(atom.ref, otelContext, debugRefreshReason)
|
|
303
304
|
}
|
|
304
305
|
|
|
@@ -315,7 +316,7 @@ export const withRCMap = <T extends LiveQuery.Any | ISignal<any>>(
|
|
|
315
316
|
): ((ctx: ReactivityGraphContext, otelContext?: otel.Context) => RcRef<T>) => {
|
|
316
317
|
return (ctx, otelContext) => {
|
|
317
318
|
let item = ctx.defRcMap.get(id)
|
|
318
|
-
if (item) {
|
|
319
|
+
if (item !== undefined) {
|
|
319
320
|
item.rc++
|
|
320
321
|
return item as RcRef<T>
|
|
321
322
|
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import type * as otel from '@opentelemetry/api'
|
|
2
|
+
|
|
1
3
|
import type { PreparedBindValues } from '@livestore/common'
|
|
2
4
|
import { SessionIdSymbol } from '@livestore/common'
|
|
3
5
|
import { State } from '@livestore/common/schema'
|
|
4
6
|
import { shouldNeverHappen } from '@livestore/utils'
|
|
5
|
-
|
|
7
|
+
|
|
6
8
|
import { StoreInternalsSymbol } from '../store/store-types.ts'
|
|
7
9
|
import type { ReactivityGraphContext } from './base-class.ts'
|
|
8
10
|
|
|
@@ -40,7 +42,7 @@ export const makeExecBeforeFirstRun =
|
|
|
40
42
|
{ otelContext },
|
|
41
43
|
).length === 1
|
|
42
44
|
|
|
43
|
-
if (rowExists) return
|
|
45
|
+
if (rowExists === true) return
|
|
44
46
|
|
|
45
47
|
// It's important that we only commit and don't refresh here, as this function might be called during a render
|
|
46
48
|
// and otherwise we might end up in a "reactive loop"
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import * as otel from '@opentelemetry/api'
|
|
2
|
+
|
|
1
3
|
import { getDurationMsFromSpan } from '@livestore/common'
|
|
2
4
|
import { Equal, Hash } from '@livestore/utils/effect'
|
|
3
|
-
import * as otel from '@opentelemetry/api'
|
|
4
5
|
|
|
5
6
|
import type { Thunk } from '../reactive.ts'
|
|
6
7
|
import type { RefreshReason } from '../store/store-types.ts'
|
|
@@ -64,7 +65,7 @@ export const computed = <TResult>(
|
|
|
64
65
|
deps?: DepKey
|
|
65
66
|
},
|
|
66
67
|
): LiveQueryDef<TResult> => {
|
|
67
|
-
const hash = options?.deps ? depsToString(options.deps) : fn.toString()
|
|
68
|
+
const hash = options?.deps !== undefined ? depsToString(options.deps) : fn.toString()
|
|
68
69
|
if (isValidFunctionString(hash)._tag === 'invalid') {
|
|
69
70
|
throw new Error(`On Expo/React Native, computed queries must provide a \`deps\` option`)
|
|
70
71
|
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { Effect, ReadonlyRecord, Schema } from '@livestore/utils/effect'
|
|
2
|
-
import { Vitest } from '@livestore/utils-dev/node-vitest'
|
|
3
1
|
import * as otel from '@opentelemetry/api'
|
|
4
2
|
import { BasicTracerProvider, InMemorySpanExporter, SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base'
|
|
5
3
|
import { assert, expect } from 'vitest'
|
|
6
4
|
|
|
5
|
+
import { Vitest } from '@livestore/utils-dev/node-vitest'
|
|
6
|
+
import { Effect, ReadonlyRecord, Schema } from '@livestore/utils/effect'
|
|
7
|
+
|
|
7
8
|
import * as RG from '../reactive.ts'
|
|
8
9
|
import { StoreInternalsSymbol } from '../store/store-types.ts'
|
|
9
10
|
import { events, makeTodoMvc, type Todo, tables } from '../utils/tests/fixture.ts'
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
SessionIdSymbol,
|
|
10
10
|
UnknownError,
|
|
11
11
|
} from '@livestore/common'
|
|
12
|
-
import { deepEqual, omitUndefineds, shouldNeverHappen } from '@livestore/utils'
|
|
12
|
+
import { deepEqual, objectToString, omitUndefineds, shouldNeverHappen } from '@livestore/utils'
|
|
13
13
|
import { Equal, Hash, Predicate, Schema, TreeFormatter } from '@livestore/utils/effect'
|
|
14
14
|
import * as otel from '@opentelemetry/api'
|
|
15
15
|
|
|
@@ -103,7 +103,7 @@ export const queryDb: {
|
|
|
103
103
|
} = (queryInput, options) => {
|
|
104
104
|
const { queryString, extraDeps } = getQueryStringAndExtraDeps(queryInput)
|
|
105
105
|
|
|
106
|
-
const hash = [queryString, options?.deps ? depsToString(options.deps) : undefined, depsToString(extraDeps)]
|
|
106
|
+
const hash = [queryString, options?.deps !== undefined ? depsToString(options.deps) : undefined, depsToString(extraDeps)]
|
|
107
107
|
.filter(Boolean)
|
|
108
108
|
.join('-')
|
|
109
109
|
|
|
@@ -112,7 +112,7 @@ export const queryDb: {
|
|
|
112
112
|
}
|
|
113
113
|
|
|
114
114
|
if (hash.trim() === '') {
|
|
115
|
-
|
|
115
|
+
return shouldNeverHappen('Invalid query hash for query:', objectToString(queryInput))
|
|
116
116
|
}
|
|
117
117
|
|
|
118
118
|
const label = options?.label ?? queryString
|
|
@@ -155,12 +155,12 @@ const bindValuesToDepKey = (bindValues: Bindable | undefined): DepKey => {
|
|
|
155
155
|
const getQueryStringAndExtraDeps = (
|
|
156
156
|
queryInput: QueryInput<any, any> | ((get: GetAtomResult) => QueryInput<any, any>),
|
|
157
157
|
): { queryString: string; extraDeps: DepKey } => {
|
|
158
|
-
if (isQueryBuilder(queryInput)) {
|
|
158
|
+
if (isQueryBuilder(queryInput) === true) {
|
|
159
159
|
const { query, bindValues } = queryInput.asSql()
|
|
160
160
|
return { queryString: query, extraDeps: bindValuesToDepKey(bindValues) }
|
|
161
161
|
}
|
|
162
162
|
|
|
163
|
-
if (isQueryInputRaw(queryInput)) {
|
|
163
|
+
if (isQueryInputRaw(queryInput) === true) {
|
|
164
164
|
return { queryString: queryInput.query, extraDeps: bindValuesToDepKey(queryInput.bindValues) }
|
|
165
165
|
}
|
|
166
166
|
|
|
@@ -168,7 +168,7 @@ const getQueryStringAndExtraDeps = (
|
|
|
168
168
|
return { queryString: queryInput.toString(), extraDeps: [] }
|
|
169
169
|
}
|
|
170
170
|
|
|
171
|
-
return shouldNeverHappen(`Invalid query input: ${queryInput}`)
|
|
171
|
+
return shouldNeverHappen(`Invalid query input: ${String(queryInput)}`)
|
|
172
172
|
}
|
|
173
173
|
|
|
174
174
|
/* An object encapsulating a reactive SQL query */
|
|
@@ -216,7 +216,7 @@ export class LiveStoreDbQuery<TResultSchema, TResult = TResultSchema> extends Li
|
|
|
216
216
|
|
|
217
217
|
const schemaRef: { current: Schema.Schema<any, any> | undefined } = {
|
|
218
218
|
current:
|
|
219
|
-
typeof queryInput === 'function' ? undefined : isQueryBuilder(queryInput) ? undefined : queryInput.schema,
|
|
219
|
+
typeof queryInput === 'function' ? undefined : isQueryBuilder(queryInput) === true ? undefined : queryInput.schema,
|
|
220
220
|
}
|
|
221
221
|
|
|
222
222
|
const execBeforeFirstRunRef: {
|
|
@@ -270,7 +270,7 @@ export class LiveStoreDbQuery<TResultSchema, TResult = TResultSchema> extends Li
|
|
|
270
270
|
|
|
271
271
|
let queryInputRaw: TQueryInputRaw
|
|
272
272
|
|
|
273
|
-
if (isQueryBuilder(queryInputResult)) {
|
|
273
|
+
if (isQueryBuilder(queryInputResult) === true) {
|
|
274
274
|
const res = fromQueryBuilder(queryInputResult, otelContext)
|
|
275
275
|
queryInputRaw = res.queryInputRaw
|
|
276
276
|
// setting label dynamically here
|
|
@@ -297,7 +297,7 @@ export class LiveStoreDbQuery<TResultSchema, TResult = TResultSchema> extends Li
|
|
|
297
297
|
this.queryInput$ = queryInputRaw$OrQueryInputRaw
|
|
298
298
|
} else {
|
|
299
299
|
let queryInputRaw: TQueryInputRaw
|
|
300
|
-
if (isQueryBuilder(queryInput)) {
|
|
300
|
+
if (isQueryBuilder(queryInput) === true) {
|
|
301
301
|
const res = fromQueryBuilder(queryInput, otelContext)
|
|
302
302
|
queryInputRaw = res.queryInputRaw
|
|
303
303
|
label = res.label
|
|
@@ -310,7 +310,7 @@ export class LiveStoreDbQuery<TResultSchema, TResult = TResultSchema> extends Li
|
|
|
310
310
|
queryInputRaw$OrQueryInputRaw = queryInputRaw
|
|
311
311
|
|
|
312
312
|
// this.label = inputLabel ? this.label : `db(${})`
|
|
313
|
-
if (inputLabel === undefined && isQueryBuilder(queryInput)) {
|
|
313
|
+
if (inputLabel === undefined && isQueryBuilder(queryInput) === true) {
|
|
314
314
|
const ast = queryInput[QueryBuilderAstSymbol]
|
|
315
315
|
if (ast._tag === 'RowQuery') {
|
|
316
316
|
label = `db(${rowQueryLabel(ast.tableDef, ast.id)})`
|
|
@@ -342,7 +342,7 @@ export class LiveStoreDbQuery<TResultSchema, TResult = TResultSchema> extends Li
|
|
|
342
342
|
'db:...', // NOTE span name will be overridden further down
|
|
343
343
|
{
|
|
344
344
|
attributes: {
|
|
345
|
-
'livestore.debugRefreshReason': Predicate.hasProperty(debugRefreshReason, 'label')
|
|
345
|
+
'livestore.debugRefreshReason': Predicate.hasProperty(debugRefreshReason, 'label') === true
|
|
346
346
|
? (debugRefreshReason.label as string)
|
|
347
347
|
: debugRefreshReason?._tag,
|
|
348
348
|
},
|
|
@@ -357,7 +357,7 @@ export class LiveStoreDbQuery<TResultSchema, TResult = TResultSchema> extends Li
|
|
|
357
357
|
execBeforeFirstRunRef.current = undefined
|
|
358
358
|
}
|
|
359
359
|
|
|
360
|
-
const queryInputResult = isThunk(queryInputRaw$OrQueryInputRaw)
|
|
360
|
+
const queryInputResult = isThunk(queryInputRaw$OrQueryInputRaw) === true
|
|
361
361
|
? (get(queryInputRaw$OrQueryInputRaw, otelContext, debugRefreshReason) as TQueryInputRaw)
|
|
362
362
|
: (queryInputRaw$OrQueryInputRaw as TQueryInputRaw)
|
|
363
363
|
|
|
@@ -383,12 +383,12 @@ export class LiveStoreDbQuery<TResultSchema, TResult = TResultSchema> extends Li
|
|
|
383
383
|
span.setAttribute('sql.query', sqlString)
|
|
384
384
|
span.updateName(`db:${sqlString.slice(0, 50)}`)
|
|
385
385
|
|
|
386
|
-
const rawDbResults = store[StoreInternalsSymbol].sqliteDbWrapper.cachedSelect
|
|
386
|
+
const rawDbResults = store[StoreInternalsSymbol].sqliteDbWrapper.cachedSelect(
|
|
387
387
|
sqlString,
|
|
388
|
-
bindValues ? prepareBindValues(bindValues, sqlString) : undefined,
|
|
388
|
+
bindValues !== undefined ? prepareBindValues(bindValues, sqlString) : undefined,
|
|
389
389
|
{
|
|
390
|
-
queriedTables: queriedTablesRef.current,
|
|
391
390
|
otelContext,
|
|
391
|
+
...(queriedTablesRef.current !== undefined ? { queriedTables: queriedTablesRef.current } : {}),
|
|
392
392
|
},
|
|
393
393
|
)
|
|
394
394
|
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { Effect } from '@livestore/utils/effect'
|
|
2
|
-
import { Vitest } from '@livestore/utils-dev/node-vitest'
|
|
3
1
|
import { expect } from 'vitest'
|
|
4
2
|
|
|
3
|
+
import { Vitest } from '@livestore/utils-dev/node-vitest'
|
|
4
|
+
import { Effect } from '@livestore/utils/effect'
|
|
5
|
+
|
|
5
6
|
import { makeTodoMvc } from '../utils/tests/fixture.ts'
|
|
6
7
|
import { computed } from './computed.ts'
|
|
7
8
|
import { signal } from './signal.ts'
|
package/src/mod.ts
CHANGED
|
@@ -41,6 +41,7 @@ export {
|
|
|
41
41
|
createStore,
|
|
42
42
|
createStorePromise,
|
|
43
43
|
} from './store/create-store.ts'
|
|
44
|
+
export { type RegistryStoreOptions, StoreRegistry, storeOptions } from './store/StoreRegistry.ts'
|
|
44
45
|
export { Store } from './store/store.ts'
|
|
45
46
|
export {
|
|
46
47
|
isLiveQueryDef,
|
|
@@ -57,6 +58,7 @@ export {
|
|
|
57
58
|
type StoreInternals,
|
|
58
59
|
StoreInternalsSymbol,
|
|
59
60
|
type SubscribeOptions,
|
|
61
|
+
type SyncStatus,
|
|
60
62
|
type Unsubscribe,
|
|
61
63
|
} from './store/store-types.ts'
|
|
62
64
|
export { exposeDebugUtils } from './utils/dev.ts'
|
package/src/reactive.test.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest'
|
|
2
|
+
|
|
2
3
|
import type { DebugRefreshReasonBase, DebugThunkInfo } from './reactive.ts'
|
|
3
4
|
import { ReactiveGraph } from './reactive.ts'
|
|
4
5
|
|
|
@@ -142,7 +143,7 @@ describe('a trivial graph', () => {
|
|
|
142
143
|
expect(numberOfEffectRuns).toBe(0)
|
|
143
144
|
const effect = graph.makeEffect((get) => {
|
|
144
145
|
// establish a dependency on thunk c and mutate an outside value
|
|
145
|
-
expect(get(c)).toBe(aHasChanged ? 3 : 4)
|
|
146
|
+
expect(get(c)).toBe(aHasChanged === true ? 3 : 4)
|
|
146
147
|
numberOfEffectRuns++
|
|
147
148
|
})
|
|
148
149
|
|
|
@@ -562,7 +563,7 @@ describe('bug fix: node corruption protection', () => {
|
|
|
562
563
|
|
|
563
564
|
let firstRun = true
|
|
564
565
|
const effect = graph.makeEffect((get) => {
|
|
565
|
-
if (firstRun) {
|
|
566
|
+
if (firstRun !== undefined) {
|
|
566
567
|
firstRun = false
|
|
567
568
|
graph.destroyNode(thunk1) // Destroy dependency mid-execution
|
|
568
569
|
}
|
package/src/reactive.ts
CHANGED
|
@@ -21,10 +21,11 @@
|
|
|
21
21
|
// is maintained eagerly as edges are added and removed.)
|
|
22
22
|
// - At every thunk we check value equality with the previous value and cutoff propagation if possible.
|
|
23
23
|
|
|
24
|
+
import type * as otel from '@opentelemetry/api'
|
|
25
|
+
|
|
24
26
|
import { BoundArray } from '@livestore/common'
|
|
25
27
|
import { deepEqual, omitUndefineds, shouldNeverHappen } from '@livestore/utils'
|
|
26
28
|
import type { Types } from '@livestore/utils/effect'
|
|
27
|
-
import type * as otel from '@opentelemetry/api'
|
|
28
29
|
// import { getDurationMsFromSpan } from './otel.ts'
|
|
29
30
|
|
|
30
31
|
export const NOT_REFRESHED_YET = Symbol.for('NOT_REFRESHED_YET')
|
|
@@ -32,8 +33,8 @@ export type NOT_REFRESHED_YET = typeof NOT_REFRESHED_YET
|
|
|
32
33
|
|
|
33
34
|
export type GetAtom = <T>(
|
|
34
35
|
atom: Atom<T, any, any>,
|
|
35
|
-
otelContext?: otel.Context
|
|
36
|
-
debugRefreshReason?: TODO
|
|
36
|
+
otelContext?: otel.Context ,
|
|
37
|
+
debugRefreshReason?: TODO ,
|
|
37
38
|
) => T
|
|
38
39
|
|
|
39
40
|
export type Ref<T, TContext, TDebugRefreshReason extends DebugRefreshReason> = {
|
|
@@ -47,7 +48,7 @@ export type Ref<T, TContext, TDebugRefreshReason extends DebugRefreshReason> = {
|
|
|
47
48
|
super: Set<Thunk<any, TContext, TDebugRefreshReason> | Effect<TDebugRefreshReason>>
|
|
48
49
|
label?: string | undefined
|
|
49
50
|
/** Container for meta information (e.g. the LiveStore Store) */
|
|
50
|
-
meta?:
|
|
51
|
+
meta?: unknown
|
|
51
52
|
equal: (a: T, b: T) => boolean
|
|
52
53
|
refreshes: number
|
|
53
54
|
}
|
|
@@ -63,7 +64,7 @@ export type Thunk<TResult, TContext, TDebugRefreshReason extends DebugRefreshRea
|
|
|
63
64
|
super: Set<Thunk<any, TContext, TDebugRefreshReason> | Effect<TDebugRefreshReason>>
|
|
64
65
|
label?: string | undefined
|
|
65
66
|
/** Container for meta information (e.g. the LiveStore Store) */
|
|
66
|
-
meta?:
|
|
67
|
+
meta?: unknown
|
|
67
68
|
equal: (a: TResult, b: TResult) => boolean
|
|
68
69
|
recomputations: number
|
|
69
70
|
|
|
@@ -78,7 +79,7 @@ export type Effect<TDebugRefreshReason extends DebugRefreshReason> = {
|
|
|
78
79
|
_tag: 'effect'
|
|
79
80
|
id: string
|
|
80
81
|
isDestroyed: boolean
|
|
81
|
-
doEffect: (otelContext?: otel.Context
|
|
82
|
+
doEffect: (otelContext?: otel.Context , debugRefreshReason?: TDebugRefreshReason ) => void
|
|
82
83
|
sub: Set<Atom<any, TODO, TODO>>
|
|
83
84
|
label?: string | undefined
|
|
84
85
|
invocations: number
|
|
@@ -91,7 +92,7 @@ export type Node<T, TContext, TDebugRefreshReason extends DebugRefreshReason> =
|
|
|
91
92
|
export const isThunk = <T, TContext, TDebugRefreshReason extends DebugRefreshReason>(
|
|
92
93
|
obj: unknown,
|
|
93
94
|
): obj is Thunk<T, TContext, TDebugRefreshReason> => {
|
|
94
|
-
return typeof obj === 'object' && obj !== null && '_tag' in obj && (obj as
|
|
95
|
+
return typeof obj === 'object' && obj !== null && '_tag' in obj && (obj as { _tag: unknown })._tag === 'thunk'
|
|
95
96
|
}
|
|
96
97
|
|
|
97
98
|
export type DebugThunkInfo<T extends string = string> = {
|
|
@@ -203,9 +204,7 @@ export class ReactiveGraph<
|
|
|
203
204
|
|
|
204
205
|
debugRefreshInfos: BoundArray<RefreshDebugInfo<TDebugRefreshReason, TDebugThunkInfo>> = new BoundArray(200)
|
|
205
206
|
|
|
206
|
-
private currentDebugRefresh:
|
|
207
|
-
| { refreshedAtoms: AtomDebugInfo<TDebugThunkInfo>[]; startMs: DOMHighResTimeStamp }
|
|
208
|
-
| undefined
|
|
207
|
+
private currentDebugRefresh: { refreshedAtoms: AtomDebugInfo<TDebugThunkInfo>[]; startMs: number } | undefined
|
|
209
208
|
|
|
210
209
|
private deferredEffects: Map<Effect<TDebugRefreshReason>, Set<TDebugRefreshReason>> = new Map()
|
|
211
210
|
|
|
@@ -253,7 +252,7 @@ export class ReactiveGraph<
|
|
|
253
252
|
meta?: any
|
|
254
253
|
equal?: (a: T, b: T) => boolean
|
|
255
254
|
}
|
|
256
|
-
|
|
255
|
+
,
|
|
257
256
|
): Thunk<T, TContext, TDebugRefreshReason> {
|
|
258
257
|
const thunk: Thunk<T, TContext, TDebugRefreshReason> = {
|
|
259
258
|
_tag: 'thunk',
|
|
@@ -262,10 +261,10 @@ export class ReactiveGraph<
|
|
|
262
261
|
isDirty: true,
|
|
263
262
|
isDestroyed: false,
|
|
264
263
|
computeResult: (otelContext, debugRefreshReason) => {
|
|
265
|
-
if (thunk.isDirty) {
|
|
264
|
+
if (thunk.isDirty === true) {
|
|
266
265
|
const neededCurrentRefresh = this.currentDebugRefresh === undefined
|
|
267
266
|
let localDebugRefresh: { refreshedAtoms: any[]; startMs: number } | undefined
|
|
268
|
-
if (neededCurrentRefresh) {
|
|
267
|
+
if (neededCurrentRefresh === true) {
|
|
269
268
|
// Use local variable to prevent corruption from nested computations
|
|
270
269
|
localDebugRefresh = { refreshedAtoms: [], startMs: performance.now() }
|
|
271
270
|
this.currentDebugRefresh = localDebugRefresh
|
|
@@ -292,7 +291,7 @@ export class ReactiveGraph<
|
|
|
292
291
|
debugRefreshReason,
|
|
293
292
|
)
|
|
294
293
|
|
|
295
|
-
const resultChanged = thunk.equal(thunk.previousResult as T, result)
|
|
294
|
+
const resultChanged = ! thunk.equal(thunk.previousResult as T, result)
|
|
296
295
|
|
|
297
296
|
const debugInfoForAtom = {
|
|
298
297
|
atom: serializeAtom(thunk, false),
|
|
@@ -302,7 +301,7 @@ export class ReactiveGraph<
|
|
|
302
301
|
|
|
303
302
|
// Use currentDebugRefresh if available (could be from parent or local)
|
|
304
303
|
const debugRefresh = localDebugRefresh ?? this.currentDebugRefresh
|
|
305
|
-
if (debugRefresh) {
|
|
304
|
+
if (debugRefresh !== undefined) {
|
|
306
305
|
debugRefresh.refreshedAtoms.push(debugInfoForAtom)
|
|
307
306
|
}
|
|
308
307
|
|
|
@@ -310,7 +309,7 @@ export class ReactiveGraph<
|
|
|
310
309
|
thunk.previousResult = result
|
|
311
310
|
thunk.recomputations++
|
|
312
311
|
|
|
313
|
-
if (neededCurrentRefresh && localDebugRefresh) {
|
|
312
|
+
if (neededCurrentRefresh === true && localDebugRefresh !== undefined) {
|
|
314
313
|
// Use local reference which can't be corrupted by nested calls
|
|
315
314
|
const refreshedAtoms = localDebugRefresh.refreshedAtoms
|
|
316
315
|
const durationMs = performance.now() - localDebugRefresh.startMs
|
|
@@ -385,7 +384,7 @@ export class ReactiveGraph<
|
|
|
385
384
|
otelContext: otel.Context | undefined,
|
|
386
385
|
debugRefreshReason: DebugRefreshReason | undefined,
|
|
387
386
|
) => void,
|
|
388
|
-
options?: { label?: string }
|
|
387
|
+
options?: { label?: string } ,
|
|
389
388
|
): Effect<TDebugRefreshReason> {
|
|
390
389
|
const effect: Effect<TDebugRefreshReason> = {
|
|
391
390
|
_tag: 'effect',
|
|
@@ -429,7 +428,7 @@ export class ReactiveGraph<
|
|
|
429
428
|
debugRefreshReason?: TDebugRefreshReason
|
|
430
429
|
otelContext?: otel.Context
|
|
431
430
|
}
|
|
432
|
-
|
|
431
|
+
,
|
|
433
432
|
) {
|
|
434
433
|
this.setRefs([[ref, val]], options)
|
|
435
434
|
}
|
|
@@ -442,7 +441,7 @@ export class ReactiveGraph<
|
|
|
442
441
|
debugRefreshReason?: TDebugRefreshReason
|
|
443
442
|
otelContext?: otel.Context
|
|
444
443
|
}
|
|
445
|
-
|
|
444
|
+
,
|
|
446
445
|
) {
|
|
447
446
|
const effectsToRefresh = new Set<Effect<TDebugRefreshReason>>()
|
|
448
447
|
for (const [ref, val] of refs) {
|
|
@@ -452,7 +451,7 @@ export class ReactiveGraph<
|
|
|
452
451
|
markSuperCompDirtyRec(ref, effectsToRefresh)
|
|
453
452
|
}
|
|
454
453
|
|
|
455
|
-
if (options?.skipRefresh) {
|
|
454
|
+
if (options?.skipRefresh === true) {
|
|
456
455
|
for (const effect of effectsToRefresh) {
|
|
457
456
|
if (this.deferredEffects.has(effect) === false) {
|
|
458
457
|
this.deferredEffects.set(effect, new Set())
|
|
@@ -598,11 +597,11 @@ const compute = <T>(
|
|
|
598
597
|
debugRefreshReason: DebugRefreshReason | undefined,
|
|
599
598
|
): T => {
|
|
600
599
|
// const __getResult = atom._tag === 'thunk' ? atom.__getResult.toString() : ''
|
|
601
|
-
if (atom.isDestroyed) {
|
|
600
|
+
if (atom.isDestroyed === true) {
|
|
602
601
|
shouldNeverHappen(`LiveStore Error: Attempted to compute destroyed ${atom._tag} (${atom.id}): ${atom.label ?? ''}`)
|
|
603
602
|
}
|
|
604
603
|
|
|
605
|
-
if (atom.isDirty) {
|
|
604
|
+
if (atom.isDirty === true) {
|
|
606
605
|
// console.log('atom is dirty', atom.id, atom.label ?? '', atom._tag, __getResult)
|
|
607
606
|
const result = atom.computeResult(otelContext, debugRefreshReason)
|
|
608
607
|
atom.isDirty = false
|
|
@@ -641,7 +640,7 @@ const serializeAtom = (atom: Atom<any, unknown, any>, includeResult: boolean): S
|
|
|
641
640
|
super_.push(a.id)
|
|
642
641
|
}
|
|
643
642
|
|
|
644
|
-
const previousResult: EncodedOption<string> = includeResult
|
|
643
|
+
const previousResult: EncodedOption<string> = includeResult === true
|
|
645
644
|
? encodedOptionSome(
|
|
646
645
|
atom.previousResult === NOT_REFRESHED_YET ? '"SYMBOL_NOT_REFRESHED_YET"' : JSON.stringify(atom.previousResult),
|
|
647
646
|
)
|