@livestore/livestore 0.0.39-dev.3 → 0.0.40
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 +15 -24
- package/dist/.tsbuildinfo +1 -1
- package/dist/__tests__/react/fixture.d.ts +210 -35
- package/dist/__tests__/react/fixture.d.ts.map +1 -1
- package/dist/__tests__/react/fixture.js +10 -29
- package/dist/__tests__/react/fixture.js.map +1 -1
- package/dist/cud.d.ts +28 -0
- package/dist/cud.d.ts.map +1 -0
- package/dist/cud.js +50 -0
- package/dist/cud.js.map +1 -0
- package/dist/cud.test.d.ts +2 -0
- package/dist/cud.test.d.ts.map +1 -0
- package/dist/cud.test.js +47 -0
- package/dist/cud.test.js.map +1 -0
- package/dist/inMemoryDatabase.d.ts +1 -1
- package/dist/inMemoryDatabase.d.ts.map +1 -1
- package/dist/inMemoryDatabase.js +1 -4
- package/dist/inMemoryDatabase.js.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js +11 -7
- package/dist/migrations.js.map +1 -1
- package/dist/query-info.d.ts +49 -0
- package/dist/query-info.d.ts.map +1 -0
- package/dist/{update-path.js → query-info.js} +4 -3
- 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/useQuery.test.d.ts.map +1 -0
- package/dist/{__tests__/react → react}/useQuery.test.js +8 -11
- package/dist/react/useQuery.test.js.map +1 -0
- 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/useRow.test.d.ts.map +1 -0
- package/dist/{__tests__/react → react}/useRow.test.js +14 -38
- package/dist/react/useRow.test.js.map +1 -0
- package/dist/react/useTemporaryQuery.d.ts +2 -2
- package/dist/react/useTemporaryQuery.d.ts.map +1 -1
- package/dist/reactive.d.ts +2 -2
- package/dist/reactive.d.ts.map +1 -1
- package/dist/reactive.js +50 -15
- package/dist/reactive.js.map +1 -1
- package/dist/reactive.test.d.ts.map +1 -0
- package/dist/{__tests__/reactive.test.js → reactive.test.js} +1 -1
- package/dist/reactive.test.js.map +1 -0
- package/dist/reactiveQueries/base-class.d.ts +16 -8
- package/dist/reactiveQueries/base-class.d.ts.map +1 -1
- package/dist/reactiveQueries/base-class.js +2 -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 +29 -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 +5 -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 +7 -6
- package/dist/reactiveQueries/sql.js.map +1 -1
- package/dist/reactiveQueries/sql.test.d.ts.map +1 -0
- package/dist/{__tests__/reactiveQueries → reactiveQueries}/sql.test.js +44 -34
- package/dist/reactiveQueries/sql.test.js.map +1 -0
- package/dist/row-query.d.ts +5 -5
- package/dist/row-query.d.ts.map +1 -1
- package/dist/row-query.js +11 -9
- package/dist/row-query.js.map +1 -1
- package/dist/schema/index.d.ts +20 -7
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +18 -3
- package/dist/schema/index.js.map +1 -1
- package/dist/schema/mutations.d.ts +81 -0
- package/dist/schema/mutations.d.ts.map +1 -0
- package/dist/schema/mutations.js +29 -0
- package/dist/schema/mutations.js.map +1 -0
- package/dist/schema/parse-utils.d.ts +3 -6
- package/dist/schema/parse-utils.d.ts.map +1 -1
- package/dist/schema/parse-utils.js +2 -27
- 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 +6 -6
- package/dist/schema/table-def.d.ts.map +1 -1
- package/dist/schema/table-def.js +2 -2
- package/dist/schema/table-def.js.map +1 -1
- package/dist/storage/in-memory/index.d.ts +4 -0
- package/dist/storage/in-memory/index.d.ts.map +1 -1
- package/dist/storage/in-memory/index.js +3 -0
- package/dist/storage/in-memory/index.js.map +1 -1
- package/dist/storage/index.d.ts +4 -0
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/storage/tauri/index.d.ts +4 -0
- package/dist/storage/tauri/index.d.ts.map +1 -1
- package/dist/storage/tauri/index.js +6 -0
- package/dist/storage/tauri/index.js.map +1 -1
- package/dist/storage/utils/idb.d.ts +1 -0
- package/dist/storage/utils/idb.d.ts.map +1 -1
- package/dist/storage/utils/idb.js +11 -0
- package/dist/storage/utils/idb.js.map +1 -1
- package/dist/storage/web-worker/common.d.ts +11 -0
- package/dist/storage/web-worker/common.d.ts.map +1 -0
- package/dist/storage/web-worker/common.js +2 -0
- package/dist/storage/web-worker/common.js.map +1 -0
- package/dist/storage/web-worker/index.d.ts +14 -7
- package/dist/storage/web-worker/index.d.ts.map +1 -1
- package/dist/storage/web-worker/index.js +70 -14
- package/dist/storage/web-worker/index.js.map +1 -1
- package/dist/storage/web-worker/make-worker.d.ts +20 -0
- package/dist/storage/web-worker/make-worker.d.ts.map +1 -0
- package/dist/storage/web-worker/make-worker.js +155 -0
- package/dist/storage/web-worker/make-worker.js.map +1 -0
- package/dist/storage/web-worker/vite-dev-polyfill.d.ts +2 -0
- package/dist/storage/web-worker/vite-dev-polyfill.d.ts.map +1 -0
- package/dist/storage/web-worker/vite-dev-polyfill.js +35 -0
- package/dist/storage/web-worker/vite-dev-polyfill.js.map +1 -0
- package/dist/store.d.ts +32 -42
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +82 -131
- package/dist/store.js.map +1 -1
- package/dist/utils/dev.d.ts +3 -0
- package/dist/utils/dev.d.ts.map +1 -0
- package/dist/utils/dev.js +16 -0
- package/dist/utils/dev.js.map +1 -0
- package/dist/utils/util.d.ts +2 -0
- package/dist/utils/util.d.ts.map +1 -1
- package/dist/utils/util.js +2 -0
- package/dist/utils/util.js.map +1 -1
- package/package.json +26 -14
- package/src/__tests__/react/fixture.tsx +12 -30
- package/src/cud.test.ts +52 -0
- package/src/cud.ts +92 -0
- package/src/inMemoryDatabase.ts +2 -7
- package/src/index.ts +14 -8
- package/src/migrations.ts +10 -7
- package/src/{update-path.ts → query-info.ts} +18 -21
- package/src/react/LiveStoreContext.ts +0 -9
- package/src/react/useAtom.ts +6 -6
- package/src/{__tests__/react → react}/useQuery.test.tsx +11 -11
- package/src/react/useQuery.ts +1 -1
- package/src/{__tests__/react → react}/useRow.test.tsx +21 -39
- package/src/react/useRow.ts +10 -10
- package/src/{__tests__/reactive.test.ts → reactive.test.ts} +1 -1
- package/src/reactive.ts +60 -19
- package/src/reactiveQueries/base-class.ts +23 -9
- package/src/reactiveQueries/graphql.ts +49 -13
- package/src/reactiveQueries/js.ts +15 -13
- package/src/{__tests__/reactiveQueries → reactiveQueries}/sql.test.ts +44 -34
- package/src/reactiveQueries/sql.ts +24 -22
- package/src/row-query.ts +24 -22
- package/src/schema/index.ts +47 -11
- package/src/schema/mutations.ts +129 -0
- package/src/schema/parse-utils.ts +3 -45
- package/src/schema/table-def.ts +9 -2
- package/src/storage/in-memory/index.ts +7 -0
- package/src/storage/index.ts +8 -0
- package/src/storage/tauri/index.ts +10 -0
- package/src/storage/utils/idb.ts +14 -0
- package/src/storage/web-worker/common.ts +6 -0
- package/src/storage/web-worker/index.ts +86 -17
- package/src/storage/web-worker/make-worker.ts +214 -0
- package/src/storage/web-worker/vite-dev-polyfill.ts +33 -0
- package/src/store.ts +142 -212
- package/src/utils/dev.ts +23 -0
- package/src/utils/util.ts +4 -0
- package/dist/__tests__/mutations.test.d.ts +0 -2
- package/dist/__tests__/mutations.test.d.ts.map +0 -1
- package/dist/__tests__/mutations.test.js +0 -40
- package/dist/__tests__/mutations.test.js.map +0 -1
- package/dist/__tests__/react/useQuery.test.d.ts.map +0 -1
- package/dist/__tests__/react/useQuery.test.js.map +0 -1
- package/dist/__tests__/react/useRow.test.d.ts.map +0 -1
- package/dist/__tests__/react/useRow.test.js.map +0 -1
- package/dist/__tests__/reactive.test.d.ts.map +0 -1
- package/dist/__tests__/reactive.test.js.map +0 -1
- package/dist/__tests__/reactiveQueries/sql.test.d.ts.map +0 -1
- package/dist/__tests__/reactiveQueries/sql.test.js.map +0 -1
- package/dist/events.d.ts +0 -7
- package/dist/events.d.ts.map +0 -1
- package/dist/events.js +0 -2
- package/dist/events.js.map +0 -1
- package/dist/mutations.d.ts +0 -33
- package/dist/mutations.d.ts.map +0 -1
- package/dist/mutations.js +0 -38
- package/dist/mutations.js.map +0 -1
- package/dist/schema/action.d.ts +0 -30
- package/dist/schema/action.d.ts.map +0 -1
- package/dist/schema/action.js +0 -3
- package/dist/schema/action.js.map +0 -1
- package/dist/storage/web-worker/worker.d.ts +0 -13
- package/dist/storage/web-worker/worker.d.ts.map +0 -1
- package/dist/storage/web-worker/worker.js +0 -110
- package/dist/storage/web-worker/worker.js.map +0 -1
- package/dist/update-path.d.ts +0 -52
- package/dist/update-path.d.ts.map +0 -1
- package/dist/update-path.js.map +0 -1
- package/src/__tests__/mutations.test.ts +0 -43
- package/src/events.ts +0 -8
- package/src/mutations.ts +0 -79
- package/src/schema/action.ts +0 -41
- package/src/storage/web-worker/worker.ts +0 -141
- /package/dist/{__tests__/react → react}/useQuery.test.d.ts +0 -0
- /package/dist/{__tests__/react → react}/useRow.test.d.ts +0 -0
- /package/dist/{__tests__/reactive.test.d.ts → reactive.test.d.ts} +0 -0
- /package/dist/{__tests__/reactiveQueries → reactiveQueries}/sql.test.d.ts +0 -0
|
@@ -3,9 +3,9 @@ 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,18 +90,18 @@ 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
|
|
96
|
+
? (rows: any) => rows as TResult
|
|
97
97
|
: Schema.isSchema(map)
|
|
98
98
|
? (rows: any) => {
|
|
99
|
-
const parseResult = Schema.
|
|
99
|
+
const parseResult = Schema.decodeEither(map as Schema.Schema<never, ReadonlyArray<any>, TResult>)(rows)
|
|
100
100
|
if (parseResult._tag === 'Left') {
|
|
101
101
|
console.error(`Error parsing SQL query result: ${TreeFormatter.formatError(parseResult.left)}`)
|
|
102
102
|
return shouldNeverHappen(`Error parsing SQL query result: ${parseResult.left}`)
|
|
103
103
|
} else {
|
|
104
|
-
return parseResult.right as
|
|
104
|
+
return parseResult.right as TResult
|
|
105
105
|
}
|
|
106
106
|
}
|
|
107
107
|
: typeof map === 'function'
|
|
@@ -130,7 +130,7 @@ export class LiveStoreSQLQuery<
|
|
|
130
130
|
|
|
131
131
|
const queriedTablesRef = { current: queriedTables }
|
|
132
132
|
|
|
133
|
-
const results$ = this.dbGraph.makeThunk<
|
|
133
|
+
const results$ = this.dbGraph.makeThunk<TResult>(
|
|
134
134
|
(get, setDebugInfo, { store, otelTracer, rootOtelContext }, otelContext) =>
|
|
135
135
|
otelTracer.startActiveSpan(
|
|
136
136
|
'sql:...', // NOTE span name will be overridden further down
|
|
@@ -173,6 +173,8 @@ export class LiveStoreSQLQuery<
|
|
|
173
173
|
|
|
174
174
|
const durationMs = getDurationMsFromSpan(span)
|
|
175
175
|
|
|
176
|
+
this.executionTimes.push(durationMs)
|
|
177
|
+
|
|
176
178
|
setDebugInfo({ _tag: 'sql', label, query: sqlString, durationMs })
|
|
177
179
|
|
|
178
180
|
return result
|
|
@@ -197,7 +199,7 @@ export class LiveStoreSQLQuery<
|
|
|
197
199
|
// label: `${this.label}:js`,
|
|
198
200
|
// onDestroy: () => this.destroy(),
|
|
199
201
|
// dbGraph: this.dbGraph,
|
|
200
|
-
//
|
|
202
|
+
// queryInfo: undefined,
|
|
201
203
|
// })
|
|
202
204
|
|
|
203
205
|
/** 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
|
}
|
|
@@ -138,20 +138,22 @@ const insertRowWithDefaultValuesOrIgnore = ({
|
|
|
138
138
|
otelContext: otel.Context
|
|
139
139
|
defaultValues: Partial<RowResult<TableDef>> | undefined
|
|
140
140
|
}) => {
|
|
141
|
-
const columnNames = Object.keys(table.sqliteDef.columns)
|
|
142
|
-
const columnValues = columnNames.map((name) => `$${name}`).join(', ')
|
|
143
|
-
|
|
144
|
-
const tableName = table.sqliteDef.name
|
|
145
|
-
const insertQuery = sql`insert into ${tableName} (${columnNames.join(
|
|
146
|
-
', ',
|
|
147
|
-
)}) select ${columnValues} where not exists(select 1 from ${tableName} where id = '${id}')`
|
|
148
|
-
|
|
149
141
|
const defaultValues = pipe(
|
|
150
142
|
getDefaultValuesEncoded(table),
|
|
151
143
|
ReadonlyRecord.map((val, columnName) => explicitDefaultValues?.[columnName] ?? val),
|
|
152
144
|
)
|
|
153
145
|
|
|
154
|
-
|
|
146
|
+
const defaultColumnNames = [...Object.keys(defaultValues), 'id']
|
|
147
|
+
const columnValues = defaultColumnNames.map((name) => `$${name}`).join(', ')
|
|
148
|
+
|
|
149
|
+
const tableName = table.sqliteDef.name
|
|
150
|
+
const insertQuery = sql`insert into ${tableName} (${defaultColumnNames.join(
|
|
151
|
+
', ',
|
|
152
|
+
)}) select ${columnValues} where not exists(select 1 from ${tableName} where id = '${id}')`
|
|
153
|
+
|
|
154
|
+
db.execute(insertQuery, prepareBindValues({ ...defaultValues, id }, insertQuery), new Set([tableName]), {
|
|
155
|
+
otelContext,
|
|
156
|
+
})
|
|
155
157
|
}
|
|
156
158
|
|
|
157
159
|
const makeExecBeforeFirstRun =
|
package/src/schema/index.ts
CHANGED
|
@@ -1,33 +1,47 @@
|
|
|
1
|
+
import type { ReadonlyArray } from '@livestore/utils/effect'
|
|
1
2
|
import type { SqliteDsl } from 'effect-db-schema'
|
|
2
3
|
|
|
3
|
-
import
|
|
4
|
+
import { isReadonlyArray } from '../utils/util.js'
|
|
5
|
+
import {
|
|
6
|
+
type MutationDef,
|
|
7
|
+
type MutationDefMap,
|
|
8
|
+
type MutationDefRecord,
|
|
9
|
+
type RawSqlMutation,
|
|
10
|
+
rawSqlMutation,
|
|
11
|
+
} from './mutations.js'
|
|
4
12
|
import { systemTables } from './system-tables.js'
|
|
5
13
|
import type { TableDef } from './table-def.js'
|
|
6
14
|
|
|
7
|
-
export * from './action.js'
|
|
8
15
|
export * from './system-tables.js'
|
|
9
16
|
export * as DbSchema from './table-def.js'
|
|
10
17
|
export * as ParseUtils from './parse-utils.js'
|
|
18
|
+
export * from './mutations.js'
|
|
11
19
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
20
|
+
export type LiveStoreSchema<
|
|
21
|
+
TDbSchema extends SqliteDsl.DbSchema = SqliteDsl.DbSchema,
|
|
22
|
+
TMutationsDefRecord extends MutationDefRecord = MutationDefRecord,
|
|
23
|
+
> = {
|
|
15
24
|
/** Only used on type-level */
|
|
16
25
|
readonly _DbSchemaType: TDbSchema
|
|
26
|
+
/** Only used on type-level */
|
|
27
|
+
readonly _MutationDefMapType: TMutationsDefRecord
|
|
17
28
|
|
|
18
29
|
readonly tables: Map<string, TableDef>
|
|
19
|
-
readonly
|
|
30
|
+
readonly mutations: MutationDefMap
|
|
20
31
|
}
|
|
21
32
|
|
|
22
33
|
export type InputSchema = {
|
|
23
|
-
tables: Record<string, TableDef> | ReadonlyArray<TableDef>
|
|
24
|
-
|
|
34
|
+
readonly tables: Record<string, TableDef> | ReadonlyArray<TableDef>
|
|
35
|
+
readonly mutations?: ReadonlyArray<MutationDef.Any> | Record<string, MutationDef.Any>
|
|
25
36
|
}
|
|
26
37
|
|
|
27
38
|
export const makeSchema = <TInputSchema extends InputSchema>(
|
|
28
|
-
/** Note when using the object-notation for tables, the object keys are ignored and not used as table names */
|
|
39
|
+
/** Note when using the object-notation for tables/mutations, the object keys are ignored and not used as table/mutation names */
|
|
29
40
|
schema: TInputSchema,
|
|
30
|
-
): LiveStoreSchema<
|
|
41
|
+
): LiveStoreSchema<
|
|
42
|
+
DbSchemaFromInputSchemaTables<TInputSchema['tables']>,
|
|
43
|
+
MutationDefRecordFromInputSchemaMutations<TInputSchema['mutations']>
|
|
44
|
+
> => {
|
|
31
45
|
const inputTables: ReadonlyArray<TableDef> = Array.isArray(schema.tables)
|
|
32
46
|
? schema.tables
|
|
33
47
|
: // TODO validate that table names are unique in this case
|
|
@@ -44,10 +58,25 @@ export const makeSchema = <TInputSchema extends InputSchema>(
|
|
|
44
58
|
tables.set(tableDef.sqliteDef.name, tableDef)
|
|
45
59
|
}
|
|
46
60
|
|
|
61
|
+
const mutations: MutationDefMap = new Map()
|
|
62
|
+
|
|
63
|
+
if (isReadonlyArray(schema.mutations)) {
|
|
64
|
+
for (const mutation of schema.mutations) {
|
|
65
|
+
mutations.set(mutation.name, mutation)
|
|
66
|
+
}
|
|
67
|
+
} else {
|
|
68
|
+
for (const [name, mutation] of Object.entries(schema.mutations ?? {})) {
|
|
69
|
+
mutations.set(name, mutation)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
mutations.set('livestore.RawSql', rawSqlMutation)
|
|
74
|
+
|
|
47
75
|
return {
|
|
48
76
|
_DbSchemaType: Symbol('livestore.DbSchemaType') as any,
|
|
77
|
+
_MutationDefMapType: Symbol('livestore.MutationDefMapType') as any,
|
|
49
78
|
tables,
|
|
50
|
-
|
|
79
|
+
mutations,
|
|
51
80
|
} satisfies LiveStoreSchema
|
|
52
81
|
}
|
|
53
82
|
|
|
@@ -62,3 +91,10 @@ export type DbSchemaFromInputSchemaTables<TTables extends InputSchema['tables']>
|
|
|
62
91
|
: TTables extends Record<string, TableDef>
|
|
63
92
|
? { [K in keyof TTables as TTables[K]['sqliteDef']['name']]: TTables[K]['sqliteDef'] }
|
|
64
93
|
: never
|
|
94
|
+
|
|
95
|
+
export type MutationDefRecordFromInputSchemaMutations<TMutations extends InputSchema['mutations']> =
|
|
96
|
+
TMutations extends ReadonlyArray<MutationDef.Any>
|
|
97
|
+
? { [K in TMutations[number] as K['name']]: K } & { 'livestore.RawSql': RawSqlMutation }
|
|
98
|
+
: TMutations extends { [name: string]: MutationDef.Any }
|
|
99
|
+
? { [K in keyof TMutations as TMutations[K]['name']]: TMutations[K] } & { 'livestore.RawSql': RawSqlMutation }
|
|
100
|
+
: never
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import type { BindValues } from '@livestore/sql-queries'
|
|
2
|
+
import { cuid } from '@livestore/utils/cuid'
|
|
3
|
+
import { Schema } from '@livestore/utils/effect'
|
|
4
|
+
|
|
5
|
+
import type { LiveStoreSchema } from './index.js'
|
|
6
|
+
|
|
7
|
+
export type MutationDefMap = Map<string | 'livestore.RawSql', MutationDef.Any>
|
|
8
|
+
export type MutationDefRecord = {
|
|
9
|
+
'livestore.RawSql': RawSqlMutation
|
|
10
|
+
[name: string]: MutationDef.Any
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export type InternalMutationSchema<TRecord extends MutationDefRecord = MutationDefRecord> = {
|
|
14
|
+
_DefRecord: TRecord
|
|
15
|
+
|
|
16
|
+
map: Map<keyof TRecord, TRecord[keyof TRecord]>
|
|
17
|
+
schemaHashMap: Map<keyof TRecord, number>
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export type MutationDef<TName extends string, TFrom, TTo> = {
|
|
21
|
+
name: TName
|
|
22
|
+
schema: Schema.Schema<never, TFrom, TTo>
|
|
23
|
+
sql:
|
|
24
|
+
| string
|
|
25
|
+
| ((args: TTo) =>
|
|
26
|
+
| string
|
|
27
|
+
| {
|
|
28
|
+
sql: string
|
|
29
|
+
/** Note args need to be manually encoded to `BindValues` when returning this argument */
|
|
30
|
+
bindValues: BindValues
|
|
31
|
+
writeTables?: ReadonlySet<string>
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
/** Helper function to construct mutation event */
|
|
35
|
+
(args: TTo): { mutation: TName; args: TTo; id: string }
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export namespace MutationDef {
|
|
39
|
+
export type Any = MutationDef<string, any, any>
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// TODO possibly also allow for mutation event subsumption behaviour
|
|
43
|
+
export const defineMutation = <TName extends string, TFrom, TTo>(
|
|
44
|
+
name: TName,
|
|
45
|
+
schema: Schema.Schema<never, TFrom, TTo>,
|
|
46
|
+
sql: string | ((args: TTo) => string | { sql: string; bindValues: BindValues; writeTables?: ReadonlySet<string> }),
|
|
47
|
+
): MutationDef<TName, TFrom, TTo> => {
|
|
48
|
+
const makeEvent = (args: TTo) => ({ mutation: name, args, id: cuid() })
|
|
49
|
+
|
|
50
|
+
Object.defineProperty(makeEvent, 'name', { value: name })
|
|
51
|
+
Object.defineProperty(makeEvent, 'schema', { value: schema })
|
|
52
|
+
Object.defineProperty(makeEvent, 'sql', { value: sql })
|
|
53
|
+
|
|
54
|
+
return makeEvent as MutationDef<TName, TFrom, TTo>
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export const makeMutationDefRecord = <TInputRecord extends Record<string, MutationDef.Any>>(
|
|
58
|
+
inputRecord: TInputRecord,
|
|
59
|
+
): {
|
|
60
|
+
[K in TInputRecord[keyof TInputRecord]['name']]: Extract<TInputRecord[keyof TInputRecord], { name: K }>
|
|
61
|
+
} => {
|
|
62
|
+
const result: any = {}
|
|
63
|
+
|
|
64
|
+
for (const [name, def] of Object.entries(inputRecord)) {
|
|
65
|
+
result[name] = def
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
result['livestore.RawSql'] = rawSqlMutation
|
|
69
|
+
|
|
70
|
+
return result
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export const rawSqlMutation = defineMutation(
|
|
74
|
+
'livestore.RawSql',
|
|
75
|
+
Schema.struct({
|
|
76
|
+
sql: Schema.string,
|
|
77
|
+
bindValues: Schema.optional(Schema.record(Schema.string, Schema.any)),
|
|
78
|
+
writeTables: Schema.optional(Schema.readonlySet(Schema.string)),
|
|
79
|
+
}),
|
|
80
|
+
({ sql, bindValues, writeTables }) => ({ sql, bindValues: bindValues ?? {}, writeTables }),
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
export type RawSqlMutation = typeof rawSqlMutation
|
|
84
|
+
export type RawSqlMutationEvent = ReturnType<typeof rawSqlMutation>
|
|
85
|
+
|
|
86
|
+
export type MutationEvent<TMutationsDef extends MutationDef.Any> = {
|
|
87
|
+
mutation: TMutationsDef['name']
|
|
88
|
+
args: Schema.Schema.To<TMutationsDef['schema']>
|
|
89
|
+
id: string
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export namespace MutationEvent {
|
|
93
|
+
export type Any = MutationEvent<MutationDef.Any>
|
|
94
|
+
|
|
95
|
+
export type ForSchema<TSchema extends LiveStoreSchema> = {
|
|
96
|
+
[K in keyof TSchema['_MutationDefMapType']]: MutationEvent<TSchema['_MutationDefMapType'][K]>
|
|
97
|
+
}[keyof TSchema['_MutationDefMapType']]
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export type MutationEventSchema<TMutationsDefRecord extends MutationDefRecord> = Schema.Schema<
|
|
101
|
+
never,
|
|
102
|
+
{
|
|
103
|
+
[K in keyof TMutationsDefRecord]: {
|
|
104
|
+
mutation: K
|
|
105
|
+
args: Schema.Schema.From<TMutationsDefRecord[K]['schema']>
|
|
106
|
+
id: string
|
|
107
|
+
}
|
|
108
|
+
}[keyof TMutationsDefRecord],
|
|
109
|
+
{
|
|
110
|
+
[K in keyof TMutationsDefRecord]: {
|
|
111
|
+
mutation: K
|
|
112
|
+
args: Schema.Schema.To<TMutationsDefRecord[K]['schema']>
|
|
113
|
+
id: string
|
|
114
|
+
}
|
|
115
|
+
}[keyof TMutationsDefRecord]
|
|
116
|
+
>
|
|
117
|
+
|
|
118
|
+
export const makeMutationEventSchema = <TMutationsDefRecord extends MutationDefRecord>(
|
|
119
|
+
mutationDefRecord: TMutationsDefRecord,
|
|
120
|
+
): MutationEventSchema<TMutationsDefRecord> =>
|
|
121
|
+
Schema.union(
|
|
122
|
+
...Object.values(mutationDefRecord).map((def) =>
|
|
123
|
+
Schema.struct({
|
|
124
|
+
mutation: Schema.literal(def.name),
|
|
125
|
+
args: def.schema,
|
|
126
|
+
id: Schema.string,
|
|
127
|
+
}),
|
|
128
|
+
),
|
|
129
|
+
) as any
|
|
@@ -1,56 +1,14 @@
|
|
|
1
1
|
import { shouldNeverHappen } from '@livestore/utils'
|
|
2
2
|
import type { ReadonlyArray } from '@livestore/utils/effect'
|
|
3
3
|
import { pipe, ReadonlyRecord, Schema, TreeFormatter } from '@livestore/utils/effect'
|
|
4
|
-
import { SqliteDsl
|
|
4
|
+
import { SqliteDsl } from 'effect-db-schema' // eslint-disable-line
|
|
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<From, To>) =>
|
|
9
|
-
Schema.transform(
|
|
10
|
-
Schema.array(schema),
|
|
11
|
-
Schema.to(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
|
@@ -5,7 +5,7 @@ import { SqliteAst, SqliteDsl } from 'effect-db-schema'
|
|
|
5
5
|
|
|
6
6
|
export const { blob, boolean, column, datetime, integer, isColumnDefinition, json, real, text } = SqliteDsl
|
|
7
7
|
|
|
8
|
-
export { type SqliteDsl
|
|
8
|
+
export { type SqliteDsl } from 'effect-db-schema'
|
|
9
9
|
|
|
10
10
|
import { dynamicallyRegisteredTables } from '../global-state.js'
|
|
11
11
|
|
|
@@ -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']> }
|
|
@@ -159,6 +160,9 @@ export const getDefaultValuesEncoded = <TTableDef extends TableDef>(tableDef: TT
|
|
|
159
160
|
pipe(
|
|
160
161
|
tableDef.sqliteDef.columns,
|
|
161
162
|
ReadonlyRecord.filter((_, key) => key !== 'id'),
|
|
163
|
+
ReadonlyRecord.filter(
|
|
164
|
+
(col) => col!.default._tag === 'None' || SqliteDsl.isSqlDefaultValue(col!.default.value) === false,
|
|
165
|
+
),
|
|
162
166
|
ReadonlyRecord.map((column, columnName) =>
|
|
163
167
|
column!.default._tag === 'None'
|
|
164
168
|
? column!.nullable === true
|
|
@@ -172,6 +176,9 @@ export const getDefaultValuesDecoded = <TTableDef extends TableDef>(tableDef: TT
|
|
|
172
176
|
pipe(
|
|
173
177
|
tableDef.sqliteDef.columns,
|
|
174
178
|
ReadonlyRecord.filter((_, key) => key !== 'id'),
|
|
179
|
+
ReadonlyRecord.filter(
|
|
180
|
+
(col) => col!.default._tag === 'None' || SqliteDsl.isSqlDefaultValue(col!.default.value) === false,
|
|
181
|
+
),
|
|
175
182
|
ReadonlyRecord.map((column, columnName) =>
|
|
176
183
|
column!.default._tag === 'None'
|
|
177
184
|
? column!.nullable === true
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type * as otel from '@opentelemetry/api'
|
|
2
2
|
|
|
3
|
+
import type { MutationEvent } from '../../index.js'
|
|
3
4
|
import type { PreparedBindValues } from '../../utils/util.js'
|
|
4
5
|
import type { Storage, StorageOtelProps } from '../index.js'
|
|
5
6
|
|
|
@@ -17,5 +18,11 @@ export class InMemoryStorage implements Storage {
|
|
|
17
18
|
|
|
18
19
|
execute = (_query: string, _bindValues?: PreparedBindValues): void => {}
|
|
19
20
|
|
|
21
|
+
mutate = (_mutationEventEncoded: MutationEvent.Any, _parentSpan?: otel.Span | undefined) => {}
|
|
22
|
+
|
|
20
23
|
getPersistedData = async (): Promise<Uint8Array> => new Uint8Array()
|
|
24
|
+
|
|
25
|
+
getMutationLogData = async (): Promise<Uint8Array> => new Uint8Array()
|
|
26
|
+
|
|
27
|
+
dangerouslyReset = async () => {}
|
|
21
28
|
}
|
package/src/storage/index.ts
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
import type * as otel from '@opentelemetry/api'
|
|
10
10
|
|
|
11
|
+
import type { MutationEvent } from '../index.js'
|
|
11
12
|
import type { PreparedBindValues } from '../utils/util.js'
|
|
12
13
|
|
|
13
14
|
export type StorageInit = (otelProps: StorageOtelProps) => Promise<Storage> | Storage
|
|
@@ -16,8 +17,15 @@ export interface Storage {
|
|
|
16
17
|
// TODO consider transferables for `bindValues` (e.g. Uint8Array values)
|
|
17
18
|
execute(query: string, bindValues?: PreparedBindValues, parentSpan?: otel.Span): void
|
|
18
19
|
|
|
20
|
+
// TODO consider transferables for `bindValues` (e.g. Uint8Array values)
|
|
21
|
+
mutate(mutationEventEncoded: MutationEvent.Any, parentSpan?: otel.Span): void
|
|
22
|
+
|
|
19
23
|
/** Return a snapshot of persisted data from the storage */
|
|
20
24
|
getPersistedData(parentSpan?: otel.Span): Promise<Uint8Array>
|
|
25
|
+
|
|
26
|
+
getMutationLogData(parentSpan?: otel.Span): Promise<Uint8Array>
|
|
27
|
+
|
|
28
|
+
dangerouslyReset(): Promise<void>
|
|
21
29
|
}
|
|
22
30
|
|
|
23
31
|
export type StorageType = 'tauri' | 'web' | 'web-in-memory'
|
|
@@ -2,6 +2,7 @@ import { getTraceParentHeader } from '@livestore/utils'
|
|
|
2
2
|
import type * as otel from '@opentelemetry/api'
|
|
3
3
|
import { invoke } from '@tauri-apps/api'
|
|
4
4
|
|
|
5
|
+
import type { MutationEvent } from '../../schema/mutations.js'
|
|
5
6
|
import type { PreparedBindValues } from '../../utils/util.js'
|
|
6
7
|
import { prepareBindValues } from '../../utils/util.js'
|
|
7
8
|
import type { Storage, StorageOtelProps } from '../index.js'
|
|
@@ -38,6 +39,8 @@ export class TauriStorage implements Storage {
|
|
|
38
39
|
})
|
|
39
40
|
}
|
|
40
41
|
|
|
42
|
+
mutate = (_mutationEventEncoded: MutationEvent.Any, _parentSpan?: otel.Span | undefined) => {}
|
|
43
|
+
|
|
41
44
|
getPersistedData = async (parentSpan?: otel.Span): Promise<Uint8Array> => {
|
|
42
45
|
const headers = new Headers()
|
|
43
46
|
headers.set('traceparent', getTraceParentHeader(parentSpan ?? this.parentSpan))
|
|
@@ -47,6 +50,13 @@ export class TauriStorage implements Storage {
|
|
|
47
50
|
)
|
|
48
51
|
}
|
|
49
52
|
|
|
53
|
+
// TODO
|
|
54
|
+
getMutationLogData = async (): Promise<Uint8Array> => new Uint8Array()
|
|
55
|
+
|
|
56
|
+
dangerouslyReset = async () => {
|
|
57
|
+
// TODO
|
|
58
|
+
}
|
|
59
|
+
|
|
50
60
|
private getOtelData = (parentSpan?: otel.Span) => getOtelData_(parentSpan ?? this.parentSpan)!
|
|
51
61
|
}
|
|
52
62
|
|