@livestore/common 0.4.0-dev.15 → 0.4.0-dev.17
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/devtools/devtools-messages-client-session.d.ts +21 -21
- package/dist/devtools/devtools-messages-common.d.ts +6 -6
- package/dist/devtools/devtools-messages-leader.d.ts +24 -24
- package/dist/devtools/devtools-sessioninfo.d.ts +2 -2
- package/dist/devtools/devtools-sessioninfo.d.ts.map +1 -1
- package/dist/devtools/devtools-sessioninfo.js +1 -4
- package/dist/devtools/devtools-sessioninfo.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/leader-thread/leader-worker-devtools.js +22 -38
- package/dist/leader-thread/leader-worker-devtools.js.map +1 -1
- package/dist/logging.d.ts +40 -0
- package/dist/logging.d.ts.map +1 -0
- package/dist/logging.js +33 -0
- package/dist/logging.js.map +1 -0
- package/dist/schema/state/sqlite/column-annotations.test.js +1 -1
- package/dist/schema/state/sqlite/column-annotations.test.js.map +1 -1
- package/dist/schema/state/sqlite/column-def.test.js +24 -6
- package/dist/schema/state/sqlite/column-def.test.js.map +1 -1
- package/dist/schema/state/sqlite/column-spec.js +8 -4
- package/dist/schema/state/sqlite/column-spec.js.map +1 -1
- package/dist/schema/state/sqlite/column-spec.test.js +10 -0
- package/dist/schema/state/sqlite/column-spec.test.js.map +1 -1
- package/dist/schema/state/sqlite/db-schema/dsl/field-defs.d.ts +14 -8
- package/dist/schema/state/sqlite/db-schema/dsl/field-defs.d.ts.map +1 -1
- package/dist/schema/state/sqlite/db-schema/dsl/field-defs.js +5 -3
- package/dist/schema/state/sqlite/db-schema/dsl/field-defs.js.map +1 -1
- package/dist/schema/state/sqlite/schema-helpers.d.ts +2 -2
- package/dist/schema/state/sqlite/schema-helpers.d.ts.map +1 -1
- package/dist/schema/state/sqlite/schema-helpers.js +22 -12
- package/dist/schema/state/sqlite/schema-helpers.js.map +1 -1
- package/dist/schema/state/sqlite/schema-helpers.test.d.ts +2 -0
- package/dist/schema/state/sqlite/schema-helpers.test.d.ts.map +1 -0
- package/dist/schema/state/sqlite/schema-helpers.test.js +36 -0
- package/dist/schema/state/sqlite/schema-helpers.test.js.map +1 -0
- package/dist/sql-queries/sql-queries.d.ts.map +1 -1
- package/dist/sql-queries/sql-queries.js +11 -1
- package/dist/sql-queries/sql-queries.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +4 -4
- package/src/devtools/devtools-sessioninfo.ts +2 -5
- package/src/index.ts +1 -0
- package/src/leader-thread/leader-worker-devtools.ts +42 -50
- package/src/logging.ts +62 -0
- package/src/schema/state/sqlite/column-annotations.test.ts +1 -1
- package/src/schema/state/sqlite/column-def.test.ts +29 -6
- package/src/schema/state/sqlite/column-spec.test.ts +16 -0
- package/src/schema/state/sqlite/column-spec.ts +8 -3
- package/src/schema/state/sqlite/db-schema/dsl/field-defs.ts +29 -12
- package/src/schema/state/sqlite/schema-helpers.test.ts +44 -0
- package/src/schema/state/sqlite/schema-helpers.ts +28 -20
- package/src/sql-queries/sql-queries.ts +9 -1
- package/src/version.ts +1 -1
- package/dist/schema/state/sqlite/system-tables.d.ts +0 -976
- package/dist/schema/state/sqlite/system-tables.d.ts.map +0 -1
- package/dist/schema/state/sqlite/system-tables.js +0 -81
- package/dist/schema/state/sqlite/system-tables.js.map +0 -1
|
@@ -47,11 +47,16 @@ const toSqliteColumnSpec = (column: SqliteAst.Column, opts: { inlinePrimaryKey:
|
|
|
47
47
|
const defaultValueStr = (() => {
|
|
48
48
|
if (column.default._tag === 'None') return ''
|
|
49
49
|
|
|
50
|
-
|
|
51
|
-
if (SqliteDsl.
|
|
50
|
+
const defaultValue = column.default.value
|
|
51
|
+
if (SqliteDsl.isDefaultThunk(defaultValue)) return ''
|
|
52
|
+
|
|
53
|
+
const resolvedDefault = SqliteDsl.resolveColumnDefault(defaultValue)
|
|
54
|
+
|
|
55
|
+
if (resolvedDefault === null) return 'default null'
|
|
56
|
+
if (SqliteDsl.isSqlDefaultValue(resolvedDefault)) return `default ${resolvedDefault.sql}`
|
|
52
57
|
|
|
53
58
|
const encodeValue = Schema.encodeSync(column.schema)
|
|
54
|
-
const encodedDefaultValue = encodeValue(
|
|
59
|
+
const encodedDefaultValue = encodeValue(resolvedDefault)
|
|
55
60
|
|
|
56
61
|
if (columnTypeStr === 'text') return `default '${encodedDefaultValue}'`
|
|
57
62
|
return `default ${encodedDefaultValue}`
|
|
@@ -1,10 +1,27 @@
|
|
|
1
1
|
import { casesHandled } from '@livestore/utils'
|
|
2
2
|
import { Option, Schema } from '@livestore/utils/effect'
|
|
3
3
|
|
|
4
|
+
export type SqlDefaultValue = {
|
|
5
|
+
readonly sql: string
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const isSqlDefaultValue = (value: unknown): value is SqlDefaultValue => {
|
|
9
|
+
return typeof value === 'object' && value !== null && 'sql' in value && typeof (value as any).sql === 'string'
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export type ColumnDefaultThunk<T> = () => T
|
|
13
|
+
|
|
14
|
+
export const isDefaultThunk = (value: unknown): value is ColumnDefaultThunk<unknown> => typeof value === 'function'
|
|
15
|
+
|
|
16
|
+
export type ColumnDefaultValue<T> = T | null | ColumnDefaultThunk<T | null> | SqlDefaultValue
|
|
17
|
+
|
|
18
|
+
export const resolveColumnDefault = <T>(value: ColumnDefaultValue<T>): T | null | SqlDefaultValue =>
|
|
19
|
+
isDefaultThunk(value) ? (value as ColumnDefaultThunk<T | null>)() : value
|
|
20
|
+
|
|
4
21
|
export type ColumnDefinition<TEncoded, TDecoded> = {
|
|
5
22
|
readonly columnType: FieldColumnType
|
|
6
23
|
readonly schema: Schema.Schema<TDecoded, TEncoded>
|
|
7
|
-
readonly default: Option.Option<
|
|
24
|
+
readonly default: Option.Option<ColumnDefaultValue<TDecoded>>
|
|
8
25
|
/** @default false */
|
|
9
26
|
readonly nullable: boolean
|
|
10
27
|
/** @default false */
|
|
@@ -27,9 +44,17 @@ export const isColumnDefinition = (value: unknown): value is ColumnDefinition.An
|
|
|
27
44
|
)
|
|
28
45
|
}
|
|
29
46
|
|
|
47
|
+
type MaybeNull<T, TNullable extends boolean> = T | (TNullable extends true ? null : never)
|
|
48
|
+
|
|
49
|
+
type ColumnDefaultArg<T, TNullable extends boolean> =
|
|
50
|
+
| MaybeNull<T, TNullable>
|
|
51
|
+
| ColumnDefaultThunk<MaybeNull<T, TNullable>>
|
|
52
|
+
| SqlDefaultValue
|
|
53
|
+
| NoDefault
|
|
54
|
+
|
|
30
55
|
export type ColumnDefinitionInput = {
|
|
31
56
|
readonly schema?: Schema.Schema<unknown>
|
|
32
|
-
readonly default?: unknown
|
|
57
|
+
readonly default?: ColumnDefaultArg<unknown, boolean>
|
|
33
58
|
readonly nullable?: boolean
|
|
34
59
|
readonly primaryKey?: boolean
|
|
35
60
|
readonly autoIncrement?: boolean
|
|
@@ -38,14 +63,6 @@ export type ColumnDefinitionInput = {
|
|
|
38
63
|
export const NoDefault = Symbol.for('NoDefault')
|
|
39
64
|
export type NoDefault = typeof NoDefault
|
|
40
65
|
|
|
41
|
-
export type SqlDefaultValue = {
|
|
42
|
-
readonly sql: string
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export const isSqlDefaultValue = (value: unknown): value is SqlDefaultValue => {
|
|
46
|
-
return typeof value === 'object' && value !== null && 'sql' in value && typeof value.sql === 'string'
|
|
47
|
-
}
|
|
48
|
-
|
|
49
66
|
export type ColDefFn<TColumnType extends FieldColumnType> = {
|
|
50
67
|
(): {
|
|
51
68
|
columnType: TColumnType
|
|
@@ -59,7 +76,7 @@ export type ColDefFn<TColumnType extends FieldColumnType> = {
|
|
|
59
76
|
TEncoded extends DefaultEncodedForColumnType<TColumnType>,
|
|
60
77
|
TDecoded = DefaultEncodedForColumnType<TColumnType>,
|
|
61
78
|
const TNullable extends boolean = false,
|
|
62
|
-
const TDefault extends TDecoded
|
|
79
|
+
const TDefault extends ColumnDefaultArg<NoInfer<TDecoded>, TNullable> = NoDefault,
|
|
63
80
|
const TPrimaryKey extends boolean = false,
|
|
64
81
|
const TAutoIncrement extends boolean = false,
|
|
65
82
|
>(args: {
|
|
@@ -132,7 +149,7 @@ export type SpecializedColDefFn<
|
|
|
132
149
|
<
|
|
133
150
|
TDecoded = TBaseDecoded,
|
|
134
151
|
const TNullable extends boolean = false,
|
|
135
|
-
const TDefault extends TDecoded
|
|
152
|
+
const TDefault extends ColumnDefaultArg<NoInfer<TDecoded>, TNullable> = NoDefault,
|
|
136
153
|
const TPrimaryKey extends boolean = false,
|
|
137
154
|
const TAutoIncrement extends boolean = false,
|
|
138
155
|
>(
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
|
|
3
|
+
import * as State from '../mod.ts'
|
|
4
|
+
import { getDefaultValuesDecoded, getDefaultValuesEncoded } from './schema-helpers.ts'
|
|
5
|
+
|
|
6
|
+
describe('schema-helpers', () => {
|
|
7
|
+
it('resolves thunk defaults when decoding values', () => {
|
|
8
|
+
let counter = 0
|
|
9
|
+
const table = State.SQLite.table({
|
|
10
|
+
name: 'sessions',
|
|
11
|
+
columns: {
|
|
12
|
+
id: State.SQLite.text({ primaryKey: true }),
|
|
13
|
+
token: State.SQLite.text({ default: () => `token-${++counter}` }),
|
|
14
|
+
},
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
expect(counter).toBe(0)
|
|
18
|
+
|
|
19
|
+
const firstDefaults = getDefaultValuesDecoded(table)
|
|
20
|
+
const secondDefaults = getDefaultValuesDecoded(table)
|
|
21
|
+
|
|
22
|
+
expect(firstDefaults.token).toBe('token-1')
|
|
23
|
+
expect(secondDefaults.token).toBe('token-2')
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
it('resolves thunk defaults when encoding values', () => {
|
|
27
|
+
let counter = 0
|
|
28
|
+
const table = State.SQLite.table({
|
|
29
|
+
name: 'sessions_encoded',
|
|
30
|
+
columns: {
|
|
31
|
+
id: State.SQLite.text({ primaryKey: true }),
|
|
32
|
+
token: State.SQLite.text({ default: () => `encoded-${++counter}` }),
|
|
33
|
+
},
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
expect(counter).toBe(0)
|
|
37
|
+
|
|
38
|
+
const firstDefaults = getDefaultValuesEncoded(table)
|
|
39
|
+
const secondDefaults = getDefaultValuesEncoded(table)
|
|
40
|
+
|
|
41
|
+
expect(firstDefaults.token).toBe('encoded-1')
|
|
42
|
+
expect(secondDefaults.token).toBe('encoded-2')
|
|
43
|
+
})
|
|
44
|
+
})
|
|
@@ -2,9 +2,9 @@ import { shouldNeverHappen } from '@livestore/utils'
|
|
|
2
2
|
import { pipe, ReadonlyRecord, Schema } from '@livestore/utils/effect'
|
|
3
3
|
|
|
4
4
|
import { SqliteDsl } from './db-schema/mod.ts'
|
|
5
|
-
import type {
|
|
5
|
+
import type { TableDefBase } from './table-def.ts'
|
|
6
6
|
|
|
7
|
-
export const getDefaultValuesEncoded = <TTableDef extends
|
|
7
|
+
export const getDefaultValuesEncoded = <TTableDef extends TableDefBase>(
|
|
8
8
|
tableDef: TTableDef,
|
|
9
9
|
fallbackValues?: Record<string, any>,
|
|
10
10
|
) =>
|
|
@@ -15,15 +15,19 @@ export const getDefaultValuesEncoded = <TTableDef extends TableDef>(
|
|
|
15
15
|
if (key === 'id') return false
|
|
16
16
|
return col!.default._tag === 'None' || SqliteDsl.isSqlDefaultValue(col!.default.value) === false
|
|
17
17
|
}),
|
|
18
|
-
ReadonlyRecord.map((column, columnName) =>
|
|
19
|
-
fallbackValues?.[columnName]
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
18
|
+
ReadonlyRecord.map((column, columnName) => {
|
|
19
|
+
if (fallbackValues?.[columnName] !== undefined) return fallbackValues[columnName]
|
|
20
|
+
if (column!.default._tag === 'None') {
|
|
21
|
+
return column!.nullable === true
|
|
22
|
+
? null
|
|
23
|
+
: shouldNeverHappen(`Column ${columnName} has no default value and is not nullable`)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const defaultValue = column!.default.value
|
|
27
|
+
const resolvedDefault = SqliteDsl.resolveColumnDefault(defaultValue)
|
|
28
|
+
|
|
29
|
+
return Schema.encodeSync(column!.schema)(resolvedDefault)
|
|
30
|
+
}),
|
|
27
31
|
)
|
|
28
32
|
|
|
29
33
|
export const getDefaultValuesDecoded = <TTableDef extends TableDefBase>(
|
|
@@ -37,13 +41,17 @@ export const getDefaultValuesDecoded = <TTableDef extends TableDefBase>(
|
|
|
37
41
|
if (key === 'id') return false
|
|
38
42
|
return col!.default._tag === 'None' || SqliteDsl.isSqlDefaultValue(col!.default.value) === false
|
|
39
43
|
}),
|
|
40
|
-
ReadonlyRecord.map((column, columnName) =>
|
|
41
|
-
fallbackValues?.[columnName]
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
44
|
+
ReadonlyRecord.map((column, columnName) => {
|
|
45
|
+
if (fallbackValues?.[columnName] !== undefined) return fallbackValues[columnName]
|
|
46
|
+
if (column!.default._tag === 'None') {
|
|
47
|
+
return column!.nullable === true
|
|
48
|
+
? null
|
|
49
|
+
: shouldNeverHappen(`Column ${columnName} has no default value and is not nullable`)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const defaultValue = column!.default.value
|
|
53
|
+
const resolvedDefault = SqliteDsl.resolveColumnDefault(defaultValue)
|
|
54
|
+
|
|
55
|
+
return Schema.validateSync(column!.schema)(resolvedDefault)
|
|
56
|
+
}),
|
|
49
57
|
)
|
|
@@ -247,7 +247,15 @@ export const createTable = ({
|
|
|
247
247
|
.map(([columnName, _]) => columnName)
|
|
248
248
|
const columnDefStrs = Object.entries(table.columns).map(([columnName, columnDef]) => {
|
|
249
249
|
const nullModifier = columnDef.nullable === true ? '' : 'NOT NULL'
|
|
250
|
-
const defaultModifier =
|
|
250
|
+
const defaultModifier = (() => {
|
|
251
|
+
if (columnDef.default._tag === 'None') return ''
|
|
252
|
+
const defaultValue = columnDef.default.value
|
|
253
|
+
if (typeof defaultValue === 'function') return ''
|
|
254
|
+
if (defaultValue && typeof defaultValue === 'object' && 'sql' in defaultValue) {
|
|
255
|
+
return `DEFAULT ${defaultValue.sql}`
|
|
256
|
+
}
|
|
257
|
+
return `DEFAULT ${defaultValue}`
|
|
258
|
+
})()
|
|
251
259
|
return sql`${columnName} ${columnDef.columnType} ${nullModifier} ${defaultModifier}`
|
|
252
260
|
})
|
|
253
261
|
|
package/src/version.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// import packageJson from '../package.json' with { type: 'json' }
|
|
3
3
|
// export const liveStoreVersion = packageJson.version
|
|
4
4
|
|
|
5
|
-
export const liveStoreVersion = '0.4.0-dev.
|
|
5
|
+
export const liveStoreVersion = '0.4.0-dev.17' as const
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* CRITICAL: Increment this version whenever you modify client-side EVENTLOG table schemas.
|