@livestore/livestore 0.0.39-dev.2 → 0.0.39
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/__tests__/mutations.test.js +1 -1
- package/dist/__tests__/react/fixture.d.ts +18 -18
- package/dist/mutations.d.ts +1 -1
- package/dist/mutations.d.ts.map +1 -1
- package/dist/mutations.js +5 -1
- package/dist/mutations.js.map +1 -1
- package/dist/{update-path.d.ts → query-info.d.ts} +12 -12
- package/dist/query-info.d.ts.map +1 -0
- package/dist/{update-path.js → query-info.js} +2 -2
- package/dist/query-info.js.map +1 -0
- package/dist/react/LiveStoreContext.d.ts +0 -6
- package/dist/react/LiveStoreContext.d.ts.map +1 -1
- package/dist/react/LiveStoreContext.js.map +1 -1
- package/dist/react/useAtom.d.ts +2 -2
- package/dist/react/useAtom.d.ts.map +1 -1
- package/dist/react/useAtom.js +3 -3
- package/dist/react/useAtom.js.map +1 -1
- package/dist/react/useQuery.d.ts.map +1 -1
- package/dist/react/useRow.d.ts +2 -2
- package/dist/react/useRow.d.ts.map +1 -1
- package/dist/react/useRow.js +5 -5
- package/dist/react/useRow.js.map +1 -1
- package/dist/react/useTemporaryQuery.d.ts +2 -2
- package/dist/react/useTemporaryQuery.d.ts.map +1 -1
- package/dist/reactiveQueries/base-class.d.ts +15 -8
- package/dist/reactiveQueries/base-class.d.ts.map +1 -1
- package/dist/reactiveQueries/base-class.js +1 -1
- package/dist/reactiveQueries/base-class.js.map +1 -1
- package/dist/reactiveQueries/graphql.d.ts +15 -9
- package/dist/reactiveQueries/graphql.d.ts.map +1 -1
- package/dist/reactiveQueries/graphql.js +28 -8
- package/dist/reactiveQueries/graphql.js.map +1 -1
- package/dist/reactiveQueries/js.d.ts +8 -8
- package/dist/reactiveQueries/js.d.ts.map +1 -1
- package/dist/reactiveQueries/js.js +4 -4
- package/dist/reactiveQueries/js.js.map +1 -1
- package/dist/reactiveQueries/sql.d.ts +11 -11
- package/dist/reactiveQueries/sql.d.ts.map +1 -1
- package/dist/reactiveQueries/sql.js +20 -9
- package/dist/reactiveQueries/sql.js.map +1 -1
- package/dist/row-query.d.ts +5 -5
- package/dist/row-query.d.ts.map +1 -1
- package/dist/row-query.js +4 -4
- package/dist/row-query.js.map +1 -1
- package/dist/schema/parse-utils.d.ts.map +1 -1
- package/dist/schema/parse-utils.js +2 -39
- package/dist/schema/parse-utils.js.map +1 -1
- package/dist/schema/system-tables.d.ts +8 -8
- package/dist/schema/table-def.d.ts +5 -5
- package/dist/schema/table-def.d.ts.map +1 -1
- package/dist/schema/table-def.js.map +1 -1
- package/package.json +10 -10
- package/src/__tests__/mutations.test.ts +1 -1
- package/src/mutations.ts +9 -2
- package/src/{update-path.ts → query-info.ts} +15 -15
- package/src/react/LiveStoreContext.ts +0 -9
- package/src/react/useAtom.ts +6 -6
- package/src/react/useQuery.ts +1 -1
- package/src/react/useRow.ts +10 -10
- package/src/reactiveQueries/base-class.ts +21 -9
- package/src/reactiveQueries/graphql.ts +47 -13
- package/src/reactiveQueries/js.ts +13 -13
- package/src/reactiveQueries/sql.ts +34 -24
- package/src/row-query.ts +13 -13
- package/src/schema/parse-utils.ts +2 -44
- package/src/schema/table-def.ts +2 -1
- package/dist/update-path.d.ts.map +0 -1
- package/dist/update-path.js.map +0 -1
|
@@ -1,34 +1,43 @@
|
|
|
1
1
|
import type { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'
|
|
2
|
-
import {
|
|
2
|
+
import { shouldNeverHappen } from '@livestore/utils'
|
|
3
|
+
import { Schema, TreeFormatter } from '@livestore/utils/effect'
|
|
3
4
|
import * as otel from '@opentelemetry/api'
|
|
4
5
|
import * as graphql from 'graphql'
|
|
5
6
|
|
|
6
7
|
import { globalDbGraph } from '../global-state.js'
|
|
8
|
+
import type { QueryInfoNone } from '../query-info.js'
|
|
7
9
|
import type { Thunk } from '../reactive.js'
|
|
8
10
|
import type { BaseGraphQLContext, RefreshReason, Store } from '../store.js'
|
|
9
|
-
import type { UpdatePathDescNone } from '../update-path.js'
|
|
10
11
|
import { getDurationMsFromSpan } from '../utils/otel.js'
|
|
11
12
|
import type { DbContext, DbGraph, GetAtomResult, LiveQuery } from './base-class.js'
|
|
12
13
|
import { LiveStoreQueryBase, makeGetAtomResult } from './base-class.js'
|
|
13
14
|
|
|
14
|
-
export
|
|
15
|
+
export type MapResult<To, From> = ((res: From, get: GetAtomResult) => To) | Schema.Schema<never, From, To>
|
|
16
|
+
|
|
17
|
+
export const queryGraphQL = <
|
|
18
|
+
TResult extends Record<string, any>,
|
|
19
|
+
TVariableValues extends Record<string, any>,
|
|
20
|
+
TResultMapped extends Record<string, any> = TResult,
|
|
21
|
+
>(
|
|
15
22
|
document: DocumentNode<TResult, TVariableValues>,
|
|
16
23
|
genVariableValues: TVariableValues | ((get: GetAtomResult) => TVariableValues),
|
|
17
|
-
{ label, dbGraph }: { label?: string; dbGraph?: DbGraph } = {},
|
|
18
|
-
): LiveQuery<
|
|
24
|
+
{ label, dbGraph, map }: { label?: string; dbGraph?: DbGraph; map?: MapResult<TResultMapped, TResult> } = {},
|
|
25
|
+
): LiveQuery<TResultMapped, QueryInfoNone> =>
|
|
26
|
+
new LiveStoreGraphQLQuery({ document, genVariableValues, label, dbGraph, map })
|
|
19
27
|
|
|
20
28
|
export class LiveStoreGraphQLQuery<
|
|
21
29
|
TResult extends Record<string, any>,
|
|
22
30
|
TVariableValues extends Record<string, any>,
|
|
23
31
|
TContext extends BaseGraphQLContext,
|
|
24
|
-
|
|
32
|
+
TResultMapped extends Record<string, any> = TResult,
|
|
33
|
+
> extends LiveStoreQueryBase<TResultMapped, QueryInfoNone> {
|
|
25
34
|
_tag: 'graphql' = 'graphql'
|
|
26
35
|
|
|
27
36
|
/** The abstract GraphQL query */
|
|
28
37
|
document: DocumentNode<TResult, TVariableValues>
|
|
29
38
|
|
|
30
39
|
/** A reactive thunk representing the query results */
|
|
31
|
-
results$: Thunk<
|
|
40
|
+
results$: Thunk<TResultMapped, DbContext, RefreshReason>
|
|
32
41
|
|
|
33
42
|
variableValues$: Thunk<TVariableValues, DbContext, RefreshReason>
|
|
34
43
|
|
|
@@ -36,18 +45,22 @@ export class LiveStoreGraphQLQuery<
|
|
|
36
45
|
|
|
37
46
|
protected dbGraph: DbGraph
|
|
38
47
|
|
|
39
|
-
|
|
48
|
+
queryInfo: QueryInfoNone = { _tag: 'None' }
|
|
49
|
+
|
|
50
|
+
private mapResult
|
|
40
51
|
|
|
41
52
|
constructor({
|
|
42
53
|
document,
|
|
43
54
|
label,
|
|
44
55
|
genVariableValues,
|
|
45
56
|
dbGraph,
|
|
57
|
+
map,
|
|
46
58
|
}: {
|
|
47
59
|
document: DocumentNode<TResult, TVariableValues>
|
|
48
60
|
genVariableValues: TVariableValues | ((get: GetAtomResult) => TVariableValues)
|
|
49
61
|
label?: string
|
|
50
62
|
dbGraph?: DbGraph
|
|
63
|
+
map?: MapResult<TResultMapped, TResult>
|
|
51
64
|
}) {
|
|
52
65
|
super()
|
|
53
66
|
|
|
@@ -58,6 +71,23 @@ export class LiveStoreGraphQLQuery<
|
|
|
58
71
|
|
|
59
72
|
this.dbGraph = dbGraph ?? globalDbGraph
|
|
60
73
|
|
|
74
|
+
this.mapResult =
|
|
75
|
+
map === undefined
|
|
76
|
+
? (res: TResult) => res as any as TResultMapped
|
|
77
|
+
: Schema.isSchema(map)
|
|
78
|
+
? (res: TResult) => {
|
|
79
|
+
const parseResult = Schema.decodeEither(map as Schema.Schema<never, TResult, TResultMapped>)(res)
|
|
80
|
+
if (parseResult._tag === 'Left') {
|
|
81
|
+
console.error(`Error parsing GraphQL query result: ${TreeFormatter.formatError(parseResult.left)}`)
|
|
82
|
+
return shouldNeverHappen(`Error parsing SQL query result: ${parseResult.left}`)
|
|
83
|
+
} else {
|
|
84
|
+
return parseResult.right as TResultMapped
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
: typeof map === 'function'
|
|
88
|
+
? map
|
|
89
|
+
: shouldNeverHappen(`Invalid map function ${map}`)
|
|
90
|
+
|
|
61
91
|
// TODO don't even create a thunk if variables are static
|
|
62
92
|
const variableValues$ = this.dbGraph.makeThunk(
|
|
63
93
|
(get, _setDebugInfo, { rootOtelContext }, otelContext) => {
|
|
@@ -73,7 +103,7 @@ export class LiveStoreGraphQLQuery<
|
|
|
73
103
|
this.variableValues$ = variableValues$
|
|
74
104
|
|
|
75
105
|
const resultsLabel = `${labelWithDefault}:results`
|
|
76
|
-
this.results$ = this.dbGraph.makeThunk<
|
|
106
|
+
this.results$ = this.dbGraph.makeThunk<TResultMapped>(
|
|
77
107
|
(get, setDebugInfo, { store, otelTracer, rootOtelContext }, otelContext) => {
|
|
78
108
|
const variableValues = get(variableValues$)
|
|
79
109
|
const { result, queriedTables, durationMs } = this.queryOnce({
|
|
@@ -82,13 +112,13 @@ export class LiveStoreGraphQLQuery<
|
|
|
82
112
|
otelContext: otelContext ?? rootOtelContext,
|
|
83
113
|
otelTracer,
|
|
84
114
|
store: store as Store<TContext>,
|
|
115
|
+
get: makeGetAtomResult(get, otelContext ?? rootOtelContext),
|
|
85
116
|
})
|
|
86
117
|
|
|
87
118
|
// Add dependencies on any tables that were used
|
|
88
119
|
for (const tableName of queriedTables) {
|
|
89
|
-
const tableRef = store.tableRefs[tableName]
|
|
90
|
-
|
|
91
|
-
get(tableRef!)
|
|
120
|
+
const tableRef = store.tableRefs[tableName] ?? shouldNeverHappen(`No table ref found for ${tableName}`)
|
|
121
|
+
get(tableRef)
|
|
92
122
|
}
|
|
93
123
|
|
|
94
124
|
setDebugInfo({ _tag: 'graphql', label: resultsLabel, query: graphql.print(document), durationMs })
|
|
@@ -121,12 +151,14 @@ export class LiveStoreGraphQLQuery<
|
|
|
121
151
|
otelTracer,
|
|
122
152
|
variableValues,
|
|
123
153
|
store,
|
|
154
|
+
get,
|
|
124
155
|
}: {
|
|
125
156
|
document: graphql.DocumentNode
|
|
126
157
|
otelContext: otel.Context
|
|
127
158
|
otelTracer: otel.Tracer
|
|
128
159
|
variableValues: TVariableValues
|
|
129
160
|
store: Store<TContext>
|
|
161
|
+
get: GetAtomResult
|
|
130
162
|
}) => {
|
|
131
163
|
const schema =
|
|
132
164
|
store.graphQLSchema ?? shouldNeverHappen("Can't run a GraphQL query on a store without GraphQL schema")
|
|
@@ -161,10 +193,12 @@ export class LiveStoreGraphQLQuery<
|
|
|
161
193
|
|
|
162
194
|
span.end()
|
|
163
195
|
|
|
196
|
+
const result = this.mapResult(res.data as unknown as TResult, get)
|
|
197
|
+
|
|
164
198
|
const durationMs = getDurationMsFromSpan(span)
|
|
165
199
|
|
|
166
200
|
return {
|
|
167
|
-
result
|
|
201
|
+
result,
|
|
168
202
|
queriedTables: Array.from(context.queriedTables.values()),
|
|
169
203
|
durationMs,
|
|
170
204
|
}
|
|
@@ -1,32 +1,32 @@
|
|
|
1
1
|
import * as otel from '@opentelemetry/api'
|
|
2
2
|
|
|
3
3
|
import { globalDbGraph } from '../global-state.js'
|
|
4
|
+
import type { QueryInfo, QueryInfoNone } from '../query-info.js'
|
|
4
5
|
import type { Thunk } from '../reactive.js'
|
|
5
6
|
import type { RefreshReason } from '../store.js'
|
|
6
|
-
import type { UpdatePathDesc, UpdatePathDescNone } from '../update-path.js'
|
|
7
7
|
import { getDurationMsFromSpan } from '../utils/otel.js'
|
|
8
8
|
import type { DbContext, DbGraph, GetAtomResult, LiveQuery } from './base-class.js'
|
|
9
9
|
import { LiveStoreQueryBase, makeGetAtomResult } from './base-class.js'
|
|
10
10
|
|
|
11
|
-
export const computed = <TResult,
|
|
11
|
+
export const computed = <TResult, TQueryInfo extends QueryInfo = QueryInfoNone>(
|
|
12
12
|
fn: (get: GetAtomResult) => TResult,
|
|
13
13
|
options?: {
|
|
14
14
|
label: string
|
|
15
15
|
dbGraph?: DbGraph
|
|
16
|
-
|
|
16
|
+
queryInfo?: TQueryInfo
|
|
17
17
|
},
|
|
18
|
-
): LiveQuery<TResult,
|
|
19
|
-
new LiveStoreJSQuery<TResult,
|
|
18
|
+
): LiveQuery<TResult, TQueryInfo> =>
|
|
19
|
+
new LiveStoreJSQuery<TResult, TQueryInfo>({
|
|
20
20
|
fn,
|
|
21
21
|
label: options?.label ?? fn.toString(),
|
|
22
22
|
dbGraph: options?.dbGraph,
|
|
23
|
-
|
|
23
|
+
queryInfo: options?.queryInfo,
|
|
24
24
|
})
|
|
25
25
|
|
|
26
|
-
export class LiveStoreJSQuery<
|
|
26
|
+
export class LiveStoreJSQuery<TResult, TQueryInfo extends QueryInfo = QueryInfoNone> extends LiveStoreQueryBase<
|
|
27
27
|
TResult,
|
|
28
|
-
|
|
29
|
-
>
|
|
28
|
+
TQueryInfo
|
|
29
|
+
> {
|
|
30
30
|
_tag: 'js' = 'js'
|
|
31
31
|
|
|
32
32
|
/** A reactive thunk representing the query results */
|
|
@@ -36,7 +36,7 @@ export class LiveStoreJSQuery<
|
|
|
36
36
|
|
|
37
37
|
protected dbGraph: DbGraph
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
queryInfo: TQueryInfo
|
|
40
40
|
|
|
41
41
|
/**
|
|
42
42
|
* Currently only used for "nested destruction" of piped queries
|
|
@@ -51,14 +51,14 @@ export class LiveStoreJSQuery<
|
|
|
51
51
|
label,
|
|
52
52
|
onDestroy,
|
|
53
53
|
dbGraph,
|
|
54
|
-
|
|
54
|
+
queryInfo,
|
|
55
55
|
}: {
|
|
56
56
|
label: string
|
|
57
57
|
fn: (get: GetAtomResult) => TResult
|
|
58
58
|
/** Currently only used for "nested destruction" of piped queries */
|
|
59
59
|
onDestroy?: () => void
|
|
60
60
|
dbGraph?: DbGraph
|
|
61
|
-
|
|
61
|
+
queryInfo?: TQueryInfo
|
|
62
62
|
}) {
|
|
63
63
|
super()
|
|
64
64
|
|
|
@@ -66,7 +66,7 @@ export class LiveStoreJSQuery<
|
|
|
66
66
|
this.label = label
|
|
67
67
|
|
|
68
68
|
this.dbGraph = dbGraph ?? globalDbGraph
|
|
69
|
-
this.
|
|
69
|
+
this.queryInfo = queryInfo ?? ({ _tag: 'None' } as TQueryInfo)
|
|
70
70
|
|
|
71
71
|
const queryLabel = `${label}:results`
|
|
72
72
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { shouldNeverHappen } from '@livestore/utils'
|
|
2
|
-
import { Schema } from '@livestore/utils/effect'
|
|
2
|
+
import { Schema, TreeFormatter } from '@livestore/utils/effect'
|
|
3
3
|
import * as otel from '@opentelemetry/api'
|
|
4
4
|
|
|
5
5
|
import { globalDbGraph } from '../global-state.js'
|
|
6
|
+
import type { QueryInfo, QueryInfoNone } from '../query-info.js'
|
|
6
7
|
import type { Thunk } from '../reactive.js'
|
|
7
8
|
import type { RefreshReason } from '../store.js'
|
|
8
|
-
import type { UpdatePathDesc, UpdatePathDescNone } from '../update-path.js'
|
|
9
9
|
import { getDurationMsFromSpan } from '../utils/otel.js'
|
|
10
10
|
import type { Bindable } from '../utils/util.js'
|
|
11
11
|
import { prepareBindValues } from '../utils/util.js'
|
|
@@ -14,12 +14,12 @@ import { LiveStoreQueryBase, makeGetAtomResult } from './base-class.js'
|
|
|
14
14
|
|
|
15
15
|
export type MapRows<TResult, TRaw = any> =
|
|
16
16
|
| ((rows: ReadonlyArray<TRaw>) => TResult)
|
|
17
|
-
| Schema.Schema<ReadonlyArray<TRaw>, TResult>
|
|
17
|
+
| Schema.Schema<never, ReadonlyArray<TRaw>, TResult>
|
|
18
18
|
|
|
19
|
-
export const querySQL = <
|
|
19
|
+
export const querySQL = <TResult, TRaw = any>(
|
|
20
20
|
query: string | ((get: GetAtomResult) => string),
|
|
21
21
|
options?: {
|
|
22
|
-
map?: MapRows<
|
|
22
|
+
map?: MapRows<TResult, TRaw>
|
|
23
23
|
/**
|
|
24
24
|
* Can be provided explicitly to slightly speed up initial query performance
|
|
25
25
|
*
|
|
@@ -30,29 +30,29 @@ export const querySQL = <Result, TRaw = any>(
|
|
|
30
30
|
label?: string
|
|
31
31
|
dbGraph?: DbGraph
|
|
32
32
|
},
|
|
33
|
-
): LiveQuery<
|
|
34
|
-
new LiveStoreSQLQuery<
|
|
33
|
+
): LiveQuery<TResult, QueryInfoNone> =>
|
|
34
|
+
new LiveStoreSQLQuery<TResult, QueryInfoNone>({
|
|
35
35
|
label: options?.label,
|
|
36
36
|
genQueryString: query,
|
|
37
37
|
queriedTables: options?.queriedTables,
|
|
38
38
|
bindValues: options?.bindValues,
|
|
39
39
|
dbGraph: options?.dbGraph,
|
|
40
40
|
map: options?.map,
|
|
41
|
-
|
|
41
|
+
queryInfo: { _tag: 'None' },
|
|
42
42
|
})
|
|
43
43
|
|
|
44
44
|
/* An object encapsulating a reactive SQL query */
|
|
45
|
-
export class LiveStoreSQLQuery<
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
>
|
|
45
|
+
export class LiveStoreSQLQuery<TResult, TQueryInfo extends QueryInfo = QueryInfoNone> extends LiveStoreQueryBase<
|
|
46
|
+
TResult,
|
|
47
|
+
TQueryInfo
|
|
48
|
+
> {
|
|
49
49
|
_tag: 'sql' = 'sql'
|
|
50
50
|
|
|
51
51
|
/** A reactive thunk representing the query text */
|
|
52
52
|
queryString$: Thunk<string, DbContext, RefreshReason>
|
|
53
53
|
|
|
54
54
|
/** A reactive thunk representing the query results */
|
|
55
|
-
results$: Thunk<
|
|
55
|
+
results$: Thunk<TResult, DbContext, RefreshReason>
|
|
56
56
|
|
|
57
57
|
label: string
|
|
58
58
|
|
|
@@ -63,7 +63,7 @@ export class LiveStoreSQLQuery<
|
|
|
63
63
|
|
|
64
64
|
private mapRows
|
|
65
65
|
|
|
66
|
-
|
|
66
|
+
queryInfo: TQueryInfo
|
|
67
67
|
|
|
68
68
|
constructor({
|
|
69
69
|
genQueryString,
|
|
@@ -73,16 +73,16 @@ export class LiveStoreSQLQuery<
|
|
|
73
73
|
dbGraph,
|
|
74
74
|
map,
|
|
75
75
|
execBeforeFirstRun,
|
|
76
|
-
|
|
76
|
+
queryInfo,
|
|
77
77
|
}: {
|
|
78
78
|
label?: string
|
|
79
79
|
genQueryString: string | ((get: GetAtomResult) => string)
|
|
80
80
|
queriedTables?: Set<string>
|
|
81
81
|
bindValues?: Bindable
|
|
82
82
|
dbGraph?: DbGraph
|
|
83
|
-
map?: MapRows<
|
|
83
|
+
map?: MapRows<TResult>
|
|
84
84
|
execBeforeFirstRun?: (ctx: DbContext) => void
|
|
85
|
-
|
|
85
|
+
queryInfo?: TQueryInfo
|
|
86
86
|
}) {
|
|
87
87
|
super()
|
|
88
88
|
|
|
@@ -90,13 +90,23 @@ export class LiveStoreSQLQuery<
|
|
|
90
90
|
this.label = `sql(${label})`
|
|
91
91
|
this.dbGraph = dbGraph ?? globalDbGraph
|
|
92
92
|
this.execBeforeFirstRun = execBeforeFirstRun
|
|
93
|
-
this.
|
|
93
|
+
this.queryInfo = queryInfo ?? ({ _tag: 'None' } as TQueryInfo)
|
|
94
94
|
this.mapRows =
|
|
95
95
|
map === undefined
|
|
96
|
-
? (rows: any) => rows as
|
|
97
|
-
:
|
|
98
|
-
?
|
|
99
|
-
|
|
96
|
+
? (rows: any) => rows as TResult
|
|
97
|
+
: Schema.isSchema(map)
|
|
98
|
+
? (rows: any) => {
|
|
99
|
+
const parseResult = Schema.decodeEither(map as Schema.Schema<never, ReadonlyArray<any>, TResult>)(rows)
|
|
100
|
+
if (parseResult._tag === 'Left') {
|
|
101
|
+
console.error(`Error parsing SQL query result: ${TreeFormatter.formatError(parseResult.left)}`)
|
|
102
|
+
return shouldNeverHappen(`Error parsing SQL query result: ${parseResult.left}`)
|
|
103
|
+
} else {
|
|
104
|
+
return parseResult.right as TResult
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
: typeof map === 'function'
|
|
108
|
+
? map
|
|
109
|
+
: shouldNeverHappen(`Invalid map function ${map}`)
|
|
100
110
|
|
|
101
111
|
// TODO don't even create a thunk if query string is static
|
|
102
112
|
const queryString$ = this.dbGraph.makeThunk(
|
|
@@ -120,7 +130,7 @@ export class LiveStoreSQLQuery<
|
|
|
120
130
|
|
|
121
131
|
const queriedTablesRef = { current: queriedTables }
|
|
122
132
|
|
|
123
|
-
const results$ = this.dbGraph.makeThunk<
|
|
133
|
+
const results$ = this.dbGraph.makeThunk<TResult>(
|
|
124
134
|
(get, setDebugInfo, { store, otelTracer, rootOtelContext }, otelContext) =>
|
|
125
135
|
otelTracer.startActiveSpan(
|
|
126
136
|
'sql:...', // NOTE span name will be overridden further down
|
|
@@ -187,7 +197,7 @@ export class LiveStoreSQLQuery<
|
|
|
187
197
|
// label: `${this.label}:js`,
|
|
188
198
|
// onDestroy: () => this.destroy(),
|
|
189
199
|
// dbGraph: this.dbGraph,
|
|
190
|
-
//
|
|
200
|
+
// queryInfo: undefined,
|
|
191
201
|
// })
|
|
192
202
|
|
|
193
203
|
/** Returns a reactive query */
|
package/src/row-query.ts
CHANGED
|
@@ -6,8 +6,9 @@ import { SqliteAst, SqliteDsl } from 'effect-db-schema'
|
|
|
6
6
|
import { computed } from './index.js'
|
|
7
7
|
import type { InMemoryDatabase } from './inMemoryDatabase.js'
|
|
8
8
|
import { migrateTable } from './migrations.js'
|
|
9
|
+
import type { QueryInfoCol, QueryInfoNone, QueryInfoRow } from './query-info.js'
|
|
9
10
|
import type { Ref } from './reactive.js'
|
|
10
|
-
import type { DbContext, DbGraph,
|
|
11
|
+
import type { DbContext, DbGraph, LiveQuery, LiveQueryAny } from './reactiveQueries/base-class.js'
|
|
11
12
|
// import type { LiveStoreJSQuery } from './reactiveQueries/js.js'
|
|
12
13
|
import { LiveStoreSQLQuery } from './reactiveQueries/sql.js'
|
|
13
14
|
import { SCHEMA_META_TABLE } from './schema/index.js'
|
|
@@ -18,7 +19,6 @@ import {
|
|
|
18
19
|
type TableOptions,
|
|
19
20
|
} from './schema/table-def.js'
|
|
20
21
|
import type { RefreshReason } from './store.js'
|
|
21
|
-
import type { UpdatePathDesc, UpdatePathDescCol, UpdatePathDescNone, UpdatePathDescRow } from './update-path.js'
|
|
22
22
|
import type { GetValForKey } from './utils/util.js'
|
|
23
23
|
import { prepareBindValues, sql } from './utils/util.js'
|
|
24
24
|
|
|
@@ -36,13 +36,13 @@ export type MakeRowQuery = {
|
|
|
36
36
|
<TTableDef extends TableDef<DefaultSqliteTableDef, boolean, TableOptions & { isSingleton: true }>>(
|
|
37
37
|
table: TTableDef,
|
|
38
38
|
options?: RowQueryOptions,
|
|
39
|
-
): LiveQuery<RowResult<TTableDef>,
|
|
39
|
+
): LiveQuery<RowResult<TTableDef>, QueryInfoRow<TTableDef>>
|
|
40
40
|
<TTableDef extends TableDef<DefaultSqliteTableDef, boolean, TableOptions & { isSingleton: false }>>(
|
|
41
41
|
table: TTableDef,
|
|
42
42
|
// TODO adjust so it works with arbitrary primary keys or unique constraints
|
|
43
43
|
id: string,
|
|
44
44
|
options?: RowQueryOptions & RowQueryOptionsDefaulValues<TTableDef>,
|
|
45
|
-
): LiveQuery<RowResult<TTableDef>,
|
|
45
|
+
): LiveQuery<RowResult<TTableDef>, QueryInfoRow<TTableDef>>
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
// TODO also allow other where clauses and multiple rows
|
|
@@ -85,7 +85,7 @@ export const rowQuery: MakeRowQuery = <TTableDef extends TableDef>(
|
|
|
85
85
|
if (results.length === 0) return shouldNeverHappen(`No results for query ${queryStr}`)
|
|
86
86
|
|
|
87
87
|
const componentStateEffectSchema = SqliteDsl.structSchemaForTable(stateSchema)
|
|
88
|
-
const parseResult = Schema.
|
|
88
|
+
const parseResult = Schema.decodeEither(componentStateEffectSchema)(results[0]!)
|
|
89
89
|
|
|
90
90
|
if (parseResult._tag === 'Left') {
|
|
91
91
|
console.error('decode error', TreeFormatter.formatError(parseResult.left), 'results', results)
|
|
@@ -94,7 +94,7 @@ export const rowQuery: MakeRowQuery = <TTableDef extends TableDef>(
|
|
|
94
94
|
|
|
95
95
|
return table.isSingleColumn === true ? parseResult.right.value : parseResult.right
|
|
96
96
|
},
|
|
97
|
-
|
|
97
|
+
queryInfo: { _tag: 'Row', table, id: id ?? 'singleton' },
|
|
98
98
|
})
|
|
99
99
|
}
|
|
100
100
|
|
|
@@ -107,20 +107,20 @@ export type RowResultEncoded<TTableDef extends TableDef> = TTableDef['isSingleCo
|
|
|
107
107
|
: SqliteDsl.FromColumns.RowEncoded<TTableDef['sqliteDef']['columns']>
|
|
108
108
|
|
|
109
109
|
export const deriveColQuery: {
|
|
110
|
-
<TQuery extends LiveQuery<any,
|
|
110
|
+
<TQuery extends LiveQuery<any, QueryInfoNone>, TCol extends keyof TQuery['__result!'] & string>(
|
|
111
111
|
query$: TQuery,
|
|
112
112
|
colName: TCol,
|
|
113
|
-
): LiveQuery<TQuery['
|
|
114
|
-
<TQuery extends LiveQuery<any,
|
|
113
|
+
): LiveQuery<TQuery['__result!'][TCol], QueryInfoNone>
|
|
114
|
+
<TQuery extends LiveQuery<any, QueryInfoRow<any>>, TCol extends keyof TQuery['__result!'] & string>(
|
|
115
115
|
query$: TQuery,
|
|
116
116
|
colName: TCol,
|
|
117
|
-
): LiveQuery<TQuery['
|
|
117
|
+
): LiveQuery<TQuery['__result!'][TCol], QueryInfoCol<TQuery['queryInfo']['table'], TCol>>
|
|
118
118
|
} = (query$: LiveQueryAny, colName: string) => {
|
|
119
119
|
return computed((get) => get(query$)[colName], {
|
|
120
120
|
label: `deriveColQuery:${query$.label}:${colName}`,
|
|
121
|
-
|
|
122
|
-
query$.
|
|
123
|
-
? { _tag: 'Col', table: query$.
|
|
121
|
+
queryInfo:
|
|
122
|
+
query$.queryInfo._tag === 'Row'
|
|
123
|
+
? { _tag: 'Col', table: query$.queryInfo.table, column: colName, id: query$.queryInfo.id }
|
|
124
124
|
: undefined,
|
|
125
125
|
}) as any
|
|
126
126
|
}
|
|
@@ -5,52 +5,10 @@ import { SqliteDsl as __SqliteDsl } from 'effect-db-schema'
|
|
|
5
5
|
|
|
6
6
|
import { type FromColumns, type FromTable, getDefaultValuesDecoded, type TableDef } from './table-def.js'
|
|
7
7
|
|
|
8
|
-
// export const headUnsafe = <From, To>(schema: Schema.Schema<ReadonlyArray<From>, ReadonlyArray<To>>) =>
|
|
9
|
-
// Schema.transform(
|
|
10
|
-
// schema,
|
|
11
|
-
// Schema.xxx(schema),
|
|
12
|
-
// (rows) => rows[0]!,
|
|
13
|
-
// (row) => [row],
|
|
14
|
-
// )
|
|
15
|
-
|
|
16
|
-
// export const head = <From, To>(schema: Schema.Schema<From, To>) =>
|
|
17
|
-
// Schema.transform(
|
|
18
|
-
// Schema.array(schema),
|
|
19
|
-
// Schema.optionFromSelf(Schema.to(schema)),
|
|
20
|
-
// (rows) => Option.fromNullable(rows[0]),
|
|
21
|
-
// (row) => (row._tag === 'None' ? [] : [row.value]),
|
|
22
|
-
// )
|
|
23
|
-
|
|
24
|
-
// export const headOr = <From, To>(schema: Schema.Schema<From, To>, fallback: To) =>
|
|
25
|
-
// Schema.transform(
|
|
26
|
-
// Schema.array(schema),
|
|
27
|
-
// Schema.to(schema),
|
|
28
|
-
// (rows) => rows[0] ?? fallback,
|
|
29
|
-
// (row) => [row],
|
|
30
|
-
// )
|
|
31
|
-
|
|
32
|
-
// export const pluck = <From extends {}, To, K extends keyof From & keyof To & string>(
|
|
33
|
-
// schema: Schema.Schema<From, To>,
|
|
34
|
-
// prop: K,
|
|
35
|
-
// ): Schema.Schema<From, To[K]> => {
|
|
36
|
-
// const toSchema = Schema.make(SchemaAST.getPropertySignatures(schema.ast).find((s) => s.name === prop)!.type) as any
|
|
37
|
-
// return Schema.transform(
|
|
38
|
-
// schema,
|
|
39
|
-
// toSchema,
|
|
40
|
-
// (row) => (row as any)[prop],
|
|
41
|
-
// (val) => ({ [prop]: val }) as any,
|
|
42
|
-
// )
|
|
43
|
-
// }
|
|
44
|
-
|
|
45
|
-
// export const schemaFor = <TTableDef extends TableDef>(
|
|
46
|
-
// table: TTableDef,
|
|
47
|
-
// ): Schema.Schema<FromTable.RowEncoded<TTableDef>, FromTable.RowDecoded<TTableDef>> =>
|
|
48
|
-
// SqliteDsl.structSchemaForTable(table.sqliteDef) as any
|
|
49
|
-
|
|
50
8
|
export const many = <TTableDef extends TableDef>(
|
|
51
9
|
table: TTableDef,
|
|
52
10
|
): ((rawRows: ReadonlyArray<any>) => ReadonlyArray<FromTable.RowDecoded<TTableDef>>) => {
|
|
53
|
-
return Schema.
|
|
11
|
+
return Schema.decodeSync(Schema.array(table.schema)) as TODO
|
|
54
12
|
}
|
|
55
13
|
|
|
56
14
|
export const first =
|
|
@@ -59,7 +17,7 @@ export const first =
|
|
|
59
17
|
fallback?: FromColumns.InsertRowDecoded<TTableDef['sqliteDef']['columns']>,
|
|
60
18
|
) =>
|
|
61
19
|
(rawRows: ReadonlyArray<any>) => {
|
|
62
|
-
const rows = Schema.
|
|
20
|
+
const rows = Schema.decodeSync(Schema.array(table.schema))(rawRows)
|
|
63
21
|
|
|
64
22
|
if (rows.length === 0) {
|
|
65
23
|
const schemaDefaultValues = getDefaultValuesDecoded(table)
|
package/src/schema/table-def.ts
CHANGED
|
@@ -18,7 +18,7 @@ export type DefaultSqliteTableDefConstrained = SqliteDsl.TableDefinition<string,
|
|
|
18
18
|
// TSqliteDef extends DefaultSqliteTableDef = DefaultSqliteTableDef,
|
|
19
19
|
// TIsSingleColumn extends boolean = boolean,
|
|
20
20
|
// TOptions extends TableOptions = TableOptions,
|
|
21
|
-
// > = TableDefBase<TSqliteDef, TIsSingleColumn, TOptions> & { schema: Schema.Schema<any, any> }
|
|
21
|
+
// > = TableDefBase<TSqliteDef, TIsSingleColumn, TOptions> & { schema: Schema.Schema<never, any, any> }
|
|
22
22
|
|
|
23
23
|
// /**
|
|
24
24
|
// * NOTE in the past we used to have a single `TableDef` but there are some TS issues when indroducing
|
|
@@ -44,6 +44,7 @@ export type TableDef<
|
|
|
44
44
|
// NOTE we're not using `SqliteDsl.StructSchemaForColumns<TSqliteDef['columns']>`
|
|
45
45
|
// as we don't want the alias type for users to show up
|
|
46
46
|
TSchema = Schema.Schema<
|
|
47
|
+
never,
|
|
47
48
|
SqliteDsl.AnyIfConstained<
|
|
48
49
|
TSqliteDef['columns'],
|
|
49
50
|
{ readonly [K in keyof TSqliteDef['columns']]: Schema.Schema.From<TSqliteDef['columns'][K]['schema']> }
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"update-path.d.ts","sourceRoot":"","sources":["../src/update-path.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAEhD,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AAEhE;;;;;GAKG;AACH,MAAM,MAAM,cAAc,CAAC,SAAS,SAAS,QAAQ,GAAG,QAAQ,IAC5D,kBAAkB,GAClB,iBAAiB,CAAC,SAAS,CAAC,GAC5B,0BAA0B,CAAC,SAAS,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC,GAC/D,iBAAiB,CAAC,SAAS,EAAE,MAAM,SAAS,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,CAAC,CAAA;AAEzE,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED,MAAM,MAAM,iBAAiB,CAAC,SAAS,SAAS,QAAQ,IAAI;IAC1D,IAAI,EAAE,KAAK,CAAA;IACX,KAAK,EAAE,SAAS,CAAA;IAChB,EAAE,EAAE,MAAM,CAAA;CACX,CAAA;AAED,MAAM,MAAM,iBAAiB,CAAC,SAAS,SAAS,QAAQ,EAAE,QAAQ,SAAS,MAAM,SAAS,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,IAAI;IACpH,IAAI,EAAE,KAAK,CAAA;IACX,KAAK,EAAE,SAAS,CAAA;IAChB,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,QAAQ,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,0BAA0B,CAAC,SAAS,SAAS,QAAQ,EAAE,QAAQ,SAAS,aAAa,CAAC,SAAS,CAAC,IAAI;IAC9G,IAAI,EAAE,cAAc,CAAA;IACpB,KAAK,EAAE,SAAS,CAAA;IAChB,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,QAAQ,CAAA;IAChB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,KAAK,aAAa,CAAC,SAAS,SAAS,QAAQ,IAAI,MAAM;KACpD,OAAO,IAAI,MAAM,SAAS,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,IAAI,SAAS,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,SAAS,MAAM,GAC1H,OAAO,GACP,KAAK,GAAG,EAAE;CACf,CAAA;AAID,MAAM,MAAM,kBAAkB,CAAC,KAAK,SAAS,cAAc,IAAI,KAAK,SAAS;IAAE,IAAI,EAAE,KAAK,CAAA;CAAE,GACxF,OAAO,CAAC,SAAS,CAAC,aAAa,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,GAChD,KAAK,SAAS;IAAE,IAAI,EAAE,KAAK,CAAA;CAAE,GAC3B,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,GACnF,KAAK,SAAS;IAAE,IAAI,EAAE,cAAc,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,IAAI,CAAA;CAAE,GACd,KAAK,CAAA;AAEb,eAAO,MAAM,uBAAuB,mGAGjC,UAmCF,CAAA;AAED,KAAK,UAAU,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,GAAG,CAAA;CAAE,CAAA"}
|
package/dist/update-path.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"update-path.js","sourceRoot":"","sources":["../src/update-path.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AACvE,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AA4DhD,MAAM,CAAC,MAAM,uBAAuB,GAAG,CACrC,UAAiB,EACjB,KAAgC,EACpB,EAAE;IACd,IAAI,UAAU,CAAC,IAAI,KAAK,cAAc,IAAI,UAAU,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QACrE,OAAO,iBAAiB,CAAC,MAAM,CAAC,CAAA;IAClC,CAAC;IAED,MAAM,cAAc,GAAG,UAAU,CAAC,KAAK,CAAC,SAAS,CAAA;IACjD,MAAM,EAAE,GAAG,UAAU,CAAC,EAAE,CAAA;IAExB,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,GAAG,CAAC,GAAG,EAAE;QACxC,IAAI,UAAU,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;YAC9B,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;YAEtC,MAAM,mBAAmB,GAAG,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,CAAC,CAAA;YAErF,yCAAyC;YACzC,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC,mBAAmB,CAAC,CAAC,KAAK,CAAC,CAAA;YAChE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,CAAA;QACpC,CAAC;aAAM,IAAI,UAAU,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;YACrC,MAAM,UAAU,GAAG,UAAU,CAAC,MAAM,CAAA;YACpC,MAAM,YAAY,GAChB,cAAc,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,MAAM,IAAI,iBAAiB,CAAC,UAAU,UAAU,YAAY,CAAC,CAAA;YACnG,MAAM,UAAU,GAAG,EAAE,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,KAAK,CAAC,EAAE,CAAA;YAC3E,OAAO,EAAE,WAAW,EAAE,CAAC,UAAU,CAAC,EAAE,UAAU,EAAE,CAAA;QAClD,CAAC;aAAM,CAAC;YACN,OAAO,iBAAiB,EAAE,CAAA;QAC5B,CAAC;IACH,CAAC,CAAC,EAAE,CAAA;IAEJ,MAAM,YAAY,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,GAAG,UAAU,OAAO,UAAU,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAEjG,MAAM,WAAW,GAAG,eAAe,EAAE,GAAG,CAAA;IACxC,MAAM,GAAG,GAAG,UAAU,cAAc,CAAC,IAAI,QAAQ,YAAY,IAAI,WAAW,EAAE,CAAA;IAC9E,MAAM,WAAW,GAAG,IAAI,GAAG,CAAS,CAAC,UAAU,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAA;IAEtE,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,UAAU,EAAE,WAAW,EAAE,EAAE,CAAA;AAClF,CAAC,CAAA"}
|