@livestore/common 0.3.2-dev.10 → 0.3.2-dev.11
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/adapter-types.d.ts +3 -3
- package/dist/adapter-types.d.ts.map +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/leader-thread/LeaderSyncProcessor.js +3 -1
- package/dist/leader-thread/LeaderSyncProcessor.js.map +1 -1
- package/dist/leader-thread/make-leader-thread-layer.d.ts.map +1 -1
- package/dist/leader-thread/make-leader-thread-layer.js +21 -4
- package/dist/leader-thread/make-leader-thread-layer.js.map +1 -1
- package/dist/leader-thread/shutdown-channel.d.ts +2 -2
- package/dist/leader-thread/shutdown-channel.d.ts.map +1 -1
- package/dist/leader-thread/shutdown-channel.js +2 -2
- package/dist/leader-thread/shutdown-channel.js.map +1 -1
- package/dist/materializer-helper.d.ts +3 -3
- package/dist/materializer-helper.d.ts.map +1 -1
- package/dist/materializer-helper.js +2 -2
- package/dist/materializer-helper.js.map +1 -1
- package/dist/rematerialize-from-eventlog.js +1 -1
- package/dist/rematerialize-from-eventlog.js.map +1 -1
- package/dist/schema/EventDef.d.ts +104 -178
- package/dist/schema/EventSequenceNumber.d.ts +5 -0
- package/dist/schema/EventSequenceNumber.d.ts.map +1 -1
- package/dist/schema/EventSequenceNumber.js +7 -2
- package/dist/schema/EventSequenceNumber.js.map +1 -1
- package/dist/schema/EventSequenceNumber.test.js +2 -2
- package/dist/schema/LiveStoreEvent.d.ts +1 -0
- package/dist/schema/LiveStoreEvent.d.ts.map +1 -1
- package/dist/schema/LiveStoreEvent.js +5 -0
- package/dist/schema/LiveStoreEvent.js.map +1 -1
- package/dist/schema/schema.d.ts +3 -0
- package/dist/schema/schema.d.ts.map +1 -1
- package/dist/schema/schema.js.map +1 -1
- package/dist/schema/state/sqlite/client-document-def.d.ts +1 -0
- package/dist/schema/state/sqlite/client-document-def.d.ts.map +1 -1
- package/dist/schema/state/sqlite/client-document-def.js +4 -2
- package/dist/schema/state/sqlite/client-document-def.js.map +1 -1
- package/dist/schema/state/sqlite/client-document-def.test.js +76 -1
- package/dist/schema/state/sqlite/client-document-def.test.js.map +1 -1
- package/dist/schema/state/sqlite/db-schema/dsl/mod.d.ts +65 -165
- package/dist/schema/state/sqlite/query-builder/api.d.ts +309 -560
- package/dist/schema/state/sqlite/query-builder/api.d.ts.map +1 -1
- package/dist/schema/state/sqlite/query-builder/astToSql.d.ts +1 -0
- package/dist/schema/state/sqlite/query-builder/astToSql.d.ts.map +1 -1
- package/dist/schema/state/sqlite/query-builder/astToSql.js +8 -6
- package/dist/schema/state/sqlite/query-builder/astToSql.js.map +1 -1
- package/dist/schema/state/sqlite/table-def.d.ts +70 -152
- package/dist/schema-management/common.d.ts +1 -1
- package/dist/schema-management/common.d.ts.map +1 -1
- package/dist/schema-management/common.js +11 -2
- package/dist/schema-management/common.js.map +1 -1
- package/dist/schema-management/migrations.js +1 -1
- package/dist/schema-management/migrations.js.map +1 -1
- package/dist/schema-management/migrations.test.d.ts +2 -0
- package/dist/schema-management/migrations.test.d.ts.map +1 -0
- package/dist/schema-management/migrations.test.js +52 -0
- package/dist/schema-management/migrations.test.js.map +1 -0
- package/dist/sql-queries/types.d.ts +37 -133
- package/dist/sync/ClientSessionSyncProcessor.d.ts.map +1 -1
- package/dist/sync/ClientSessionSyncProcessor.js +8 -7
- package/dist/sync/ClientSessionSyncProcessor.js.map +1 -1
- package/dist/sync/sync.d.ts.map +1 -1
- package/dist/sync/sync.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +4 -4
- package/src/adapter-types.ts +3 -3
- package/src/leader-thread/LeaderSyncProcessor.ts +3 -1
- package/src/leader-thread/make-leader-thread-layer.ts +26 -7
- package/src/leader-thread/shutdown-channel.ts +2 -2
- package/src/materializer-helper.ts +5 -11
- package/src/rematerialize-from-eventlog.ts +2 -2
- package/src/schema/EventSequenceNumber.test.ts +2 -2
- package/src/schema/EventSequenceNumber.ts +8 -2
- package/src/schema/LiveStoreEvent.ts +6 -0
- package/src/schema/schema.ts +4 -0
- package/src/schema/state/sqlite/client-document-def.test.ts +89 -1
- package/src/schema/state/sqlite/client-document-def.ts +5 -2
- package/src/schema/state/sqlite/query-builder/api.ts +4 -3
- package/src/schema/state/sqlite/query-builder/astToSql.ts +9 -7
- package/src/schema-management/common.ts +10 -3
- package/src/schema-management/migrations.test.ts +65 -0
- package/src/schema-management/migrations.ts +1 -1
- package/src/sync/ClientSessionSyncProcessor.ts +8 -6
- package/src/sync/sync.ts +2 -0
- package/src/version.ts +1 -1
@@ -3,7 +3,7 @@ import { describe, expect, test } from 'vitest'
|
|
3
3
|
|
4
4
|
import { tables } from '../../../__tests__/fixture.ts'
|
5
5
|
import type * as LiveStoreEvent from '../../LiveStoreEvent.ts'
|
6
|
-
import { ClientDocumentTableDefSymbol, clientDocument } from './client-document-def.ts'
|
6
|
+
import { ClientDocumentTableDefSymbol, clientDocument, mergeDefaultValues } from './client-document-def.ts'
|
7
7
|
|
8
8
|
describe('client document table', () => {
|
9
9
|
test('set event', () => {
|
@@ -238,3 +238,91 @@ const patchId = (muationEvent: LiveStoreEvent.PartialAnyDecoded) => {
|
|
238
238
|
const id = `00000000-0000-0000-0000-000000000000`
|
239
239
|
return { ...muationEvent, id }
|
240
240
|
}
|
241
|
+
|
242
|
+
describe('mergeDefaultValues', () => {
|
243
|
+
test('merges values from both objects', () => {
|
244
|
+
const defaults = { a: 1, b: 2 }
|
245
|
+
const explicit = { a: 10, b: 20 }
|
246
|
+
const result = mergeDefaultValues(defaults, explicit)
|
247
|
+
|
248
|
+
expect(result).toEqual({ a: 10, b: 20 })
|
249
|
+
})
|
250
|
+
|
251
|
+
test('uses default values when explicit values are undefined', () => {
|
252
|
+
const defaults = { a: 1, b: 2 }
|
253
|
+
const explicit = { a: undefined, b: 20 } as any
|
254
|
+
const result = mergeDefaultValues(defaults, explicit)
|
255
|
+
|
256
|
+
expect(result).toEqual({ a: 1, b: 20 })
|
257
|
+
})
|
258
|
+
|
259
|
+
test('should preserve properties that are not in default values', () => {
|
260
|
+
const defaults = { a: 1, b: 2 }
|
261
|
+
const explicit = { a: 10, b: 20, c: 30 }
|
262
|
+
const result = mergeDefaultValues(defaults, explicit)
|
263
|
+
|
264
|
+
// Should include ALL properties from explicit, not just those in defaults
|
265
|
+
expect(result).toEqual({ a: 10, b: 20, c: 30 })
|
266
|
+
expect('c' in result).toBe(true)
|
267
|
+
})
|
268
|
+
|
269
|
+
test('issue #487 - should preserve optional fields not in defaults', () => {
|
270
|
+
const defaults = {
|
271
|
+
newTodoText: '',
|
272
|
+
filter: 'all' as const,
|
273
|
+
}
|
274
|
+
const userSet = {
|
275
|
+
newTodoText: '',
|
276
|
+
description: 'First attempt', // Optional field not in defaults
|
277
|
+
filter: 'all' as const,
|
278
|
+
}
|
279
|
+
const result = mergeDefaultValues(defaults, userSet)
|
280
|
+
|
281
|
+
// Should include the description field even though it's not in defaults
|
282
|
+
expect(result).toEqual({
|
283
|
+
newTodoText: '',
|
284
|
+
description: 'First attempt',
|
285
|
+
filter: 'all',
|
286
|
+
})
|
287
|
+
expect('description' in result).toBe(true)
|
288
|
+
})
|
289
|
+
|
290
|
+
test('handles non-object values', () => {
|
291
|
+
expect(mergeDefaultValues('default', 'explicit')).toBe('explicit')
|
292
|
+
expect(mergeDefaultValues(42, 100)).toBe(100)
|
293
|
+
expect(mergeDefaultValues(null, { a: 1 })).toEqual({ a: 1 })
|
294
|
+
expect(mergeDefaultValues({ a: 1 }, null)).toBe(null)
|
295
|
+
})
|
296
|
+
|
297
|
+
test('handles nested objects (current implementation does not deep merge)', () => {
|
298
|
+
const defaults = { a: { x: 1, y: 2 }, b: 3 }
|
299
|
+
const explicit = { a: { x: 10 }, b: 30 } as any
|
300
|
+
const result = mergeDefaultValues(defaults, explicit)
|
301
|
+
|
302
|
+
// Current implementation replaces entire nested object
|
303
|
+
expect(result).toEqual({ a: { x: 10 }, b: 30 })
|
304
|
+
// Note: 'y' is lost because the entire 'a' object is replaced
|
305
|
+
})
|
306
|
+
|
307
|
+
test('should handle mix of default and new properties', () => {
|
308
|
+
const defaults = {
|
309
|
+
required1: 'default1',
|
310
|
+
required2: 'default2',
|
311
|
+
}
|
312
|
+
const userSet = {
|
313
|
+
required1: 'user1', // Override default
|
314
|
+
required2: 'default2', // Keep default
|
315
|
+
optional1: 'new1', // New field
|
316
|
+
optional2: 'new2', // New field
|
317
|
+
}
|
318
|
+
const result = mergeDefaultValues(defaults, userSet)
|
319
|
+
|
320
|
+
expect(result).toEqual({
|
321
|
+
required1: 'user1',
|
322
|
+
required2: 'default2',
|
323
|
+
optional1: 'new1',
|
324
|
+
optional2: 'new2',
|
325
|
+
})
|
326
|
+
expect(Object.keys(result).sort()).toEqual(['optional1', 'optional2', 'required1', 'required2'])
|
327
|
+
})
|
328
|
+
})
|
@@ -121,7 +121,7 @@ export const clientDocument = <
|
|
121
121
|
return clientDocumentTableDef
|
122
122
|
}
|
123
123
|
|
124
|
-
const mergeDefaultValues = <T>(defaultValues: T, explicitDefaultValues: T): T => {
|
124
|
+
export const mergeDefaultValues = <T>(defaultValues: T, explicitDefaultValues: T): T => {
|
125
125
|
if (
|
126
126
|
typeof defaultValues !== 'object' ||
|
127
127
|
typeof explicitDefaultValues !== 'object' ||
|
@@ -131,7 +131,10 @@ const mergeDefaultValues = <T>(defaultValues: T, explicitDefaultValues: T): T =>
|
|
131
131
|
return explicitDefaultValues
|
132
132
|
}
|
133
133
|
|
134
|
-
|
134
|
+
// Get all unique keys from both objects
|
135
|
+
const allKeys = new Set([...Object.keys(defaultValues as any), ...Object.keys(explicitDefaultValues as any)])
|
136
|
+
|
137
|
+
return Array.from(allKeys).reduce((acc, key) => {
|
135
138
|
acc[key] = (explicitDefaultValues as any)[key] ?? (defaultValues as any)[key]
|
136
139
|
return acc
|
137
140
|
}, {} as any)
|
@@ -122,7 +122,7 @@ export type QueryBuilder<
|
|
122
122
|
readonly [QueryBuilderTypeId]: QueryBuilderTypeId
|
123
123
|
readonly [QueryBuilderAstSymbol]: QueryBuilderAst
|
124
124
|
readonly ResultType: TResult
|
125
|
-
readonly asSql: () => { query: string; bindValues: SqlValue[] }
|
125
|
+
readonly asSql: () => { query: string; bindValues: SqlValue[]; usedTables: Set<string> }
|
126
126
|
readonly toString: () => string
|
127
127
|
} & Omit<QueryBuilder.ApiFull<TResult, TTableDef, TWithout>, TWithout>
|
128
128
|
|
@@ -264,14 +264,15 @@ export namespace QueryBuilder {
|
|
264
264
|
* Example:
|
265
265
|
* ```ts
|
266
266
|
* db.todos.orderBy('createdAt', 'desc')
|
267
|
+
* db.todos.orderBy([{ col: 'createdAt', direction: 'desc' }])
|
267
268
|
* ```
|
268
269
|
*/
|
269
270
|
readonly orderBy: {
|
270
|
-
<TColName extends keyof TTableDef['sqliteDef']['columns'] & string>(
|
271
|
+
<const TColName extends keyof TTableDef['sqliteDef']['columns'] & string>(
|
271
272
|
col: TColName,
|
272
273
|
direction: 'asc' | 'desc',
|
273
274
|
): QueryBuilder<TResult, TTableDef, TWithout | 'returning' | 'onConflict'>
|
274
|
-
<TParams extends QueryBuilder.OrderByParams<TTableDef>>(
|
275
|
+
<const TParams extends QueryBuilder.OrderByParams<TTableDef>>(
|
275
276
|
params: TParams,
|
276
277
|
): QueryBuilder<TResult, TTableDef, TWithout | 'returning' | 'onConflict'>
|
277
278
|
}
|
@@ -65,8 +65,9 @@ const formatReturningClause = (returning?: string[]): string => {
|
|
65
65
|
return ` RETURNING ${returning.join(', ')}`
|
66
66
|
}
|
67
67
|
|
68
|
-
export const astToSql = (ast: QueryBuilderAst): { query: string; bindValues: SqlValue[] } => {
|
68
|
+
export const astToSql = (ast: QueryBuilderAst): { query: string; bindValues: SqlValue[]; usedTables: Set<string> } => {
|
69
69
|
const bindValues: SqlValue[] = []
|
70
|
+
const usedTables = new Set<string>([ast.tableDef.sqliteDef.name])
|
70
71
|
|
71
72
|
// INSERT query
|
72
73
|
if (ast._tag === 'InsertQuery') {
|
@@ -134,7 +135,7 @@ export const astToSql = (ast: QueryBuilderAst): { query: string; bindValues: Sql
|
|
134
135
|
query += conflictClause
|
135
136
|
|
136
137
|
query += formatReturningClause(ast.returning)
|
137
|
-
return { query, bindValues }
|
138
|
+
return { query, bindValues, usedTables }
|
138
139
|
}
|
139
140
|
|
140
141
|
// UPDATE query
|
@@ -145,7 +146,7 @@ export const astToSql = (ast: QueryBuilderAst): { query: string; bindValues: Sql
|
|
145
146
|
console.warn(
|
146
147
|
`UPDATE query requires at least one column to set (for table ${ast.tableDef.sqliteDef.name}). Running no-op query instead to skip this update query.`,
|
147
148
|
)
|
148
|
-
return { query: 'SELECT 1', bindValues: [] }
|
149
|
+
return { query: 'SELECT 1', bindValues: [], usedTables }
|
149
150
|
// return shouldNeverHappen('UPDATE query requires at least one column to set.')
|
150
151
|
}
|
151
152
|
|
@@ -162,7 +163,7 @@ export const astToSql = (ast: QueryBuilderAst): { query: string; bindValues: Sql
|
|
162
163
|
if (whereClause) query += ` ${whereClause}`
|
163
164
|
|
164
165
|
query += formatReturningClause(ast.returning)
|
165
|
-
return { query, bindValues }
|
166
|
+
return { query, bindValues, usedTables }
|
166
167
|
}
|
167
168
|
|
168
169
|
// DELETE query
|
@@ -173,7 +174,7 @@ export const astToSql = (ast: QueryBuilderAst): { query: string; bindValues: Sql
|
|
173
174
|
if (whereClause) query += ` ${whereClause}`
|
174
175
|
|
175
176
|
query += formatReturningClause(ast.returning)
|
176
|
-
return { query, bindValues }
|
177
|
+
return { query, bindValues, usedTables }
|
177
178
|
}
|
178
179
|
|
179
180
|
// COUNT query
|
@@ -185,7 +186,7 @@ export const astToSql = (ast: QueryBuilderAst): { query: string; bindValues: Sql
|
|
185
186
|
.filter((clause) => clause.length > 0)
|
186
187
|
.join(' ')
|
187
188
|
|
188
|
-
return { query, bindValues }
|
189
|
+
return { query, bindValues, usedTables }
|
189
190
|
}
|
190
191
|
|
191
192
|
// ROW query
|
@@ -202,6 +203,7 @@ export const astToSql = (ast: QueryBuilderAst): { query: string; bindValues: Sql
|
|
202
203
|
return {
|
203
204
|
query: `SELECT * FROM '${ast.tableDef.sqliteDef.name}' WHERE id = ?`,
|
204
205
|
bindValues: [encodedId as SqlValue],
|
206
|
+
usedTables,
|
205
207
|
}
|
206
208
|
}
|
207
209
|
|
@@ -228,5 +230,5 @@ export const astToSql = (ast: QueryBuilderAst): { query: string; bindValues: Sql
|
|
228
230
|
.filter((clause) => clause.length > 0)
|
229
231
|
.join(' ')
|
230
232
|
|
231
|
-
return { query, bindValues }
|
233
|
+
return { query, bindValues, usedTables }
|
232
234
|
}
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import type
|
1
|
+
import { type SqliteDb, SqliteError } from '../adapter-types.ts'
|
2
2
|
import type { ParamsObject } from '../util.ts'
|
3
3
|
import { prepareBindValues } from '../util.ts'
|
4
4
|
|
@@ -15,9 +15,16 @@ export const dbExecute = (db: SqliteDb, queryStr: string, bindValues?: ParamsObj
|
|
15
15
|
|
16
16
|
const preparedBindValues = bindValues ? prepareBindValues(bindValues, queryStr) : undefined
|
17
17
|
|
18
|
-
|
18
|
+
try {
|
19
|
+
stmt.execute(preparedBindValues)
|
19
20
|
|
20
|
-
|
21
|
+
stmt.finalize()
|
22
|
+
} catch (cause) {
|
23
|
+
throw new SqliteError({
|
24
|
+
cause,
|
25
|
+
query: { sql: queryStr, bindValues: preparedBindValues ?? {} },
|
26
|
+
})
|
27
|
+
}
|
21
28
|
}
|
22
29
|
|
23
30
|
export const dbSelect = <T>(db: SqliteDb, queryStr: string, bindValues?: ParamsObject) => {
|
@@ -0,0 +1,65 @@
|
|
1
|
+
import { Option, Schema } from '@livestore/utils/effect'
|
2
|
+
import { describe, expect, it } from 'vitest'
|
3
|
+
import type { SqliteAst } from '../schema/state/sqlite/db-schema/mod.ts'
|
4
|
+
import { makeColumnSpec } from './migrations.js'
|
5
|
+
|
6
|
+
const createColumn = (
|
7
|
+
name: string,
|
8
|
+
type: 'text' | 'integer',
|
9
|
+
options: { nullable?: boolean; primaryKey?: boolean } = {},
|
10
|
+
) => ({
|
11
|
+
_tag: 'column' as const,
|
12
|
+
name,
|
13
|
+
type: { _tag: type },
|
14
|
+
nullable: options.nullable ?? true,
|
15
|
+
primaryKey: options.primaryKey ?? false,
|
16
|
+
default: Option.none(),
|
17
|
+
schema: type === 'text' ? Schema.String : Schema.Number,
|
18
|
+
})
|
19
|
+
|
20
|
+
describe('makeColumnSpec', () => {
|
21
|
+
it('should quote column names properly for reserved keywords', () => {
|
22
|
+
const table: SqliteAst.Table = {
|
23
|
+
_tag: 'table',
|
24
|
+
name: 'blocks',
|
25
|
+
columns: [createColumn('order', 'integer', { nullable: false }), createColumn('group', 'text')],
|
26
|
+
indexes: [],
|
27
|
+
}
|
28
|
+
|
29
|
+
const result = makeColumnSpec(table)
|
30
|
+
expect(result).toMatchInlineSnapshot(`"'order' integer not null , 'group' text "`)
|
31
|
+
expect(result).toContain("'order'")
|
32
|
+
expect(result).toContain("'group'")
|
33
|
+
})
|
34
|
+
|
35
|
+
it('should handle basic columns with primary keys', () => {
|
36
|
+
const table: SqliteAst.Table = {
|
37
|
+
_tag: 'table',
|
38
|
+
name: 'users',
|
39
|
+
columns: [createColumn('id', 'text', { nullable: false, primaryKey: true }), createColumn('name', 'text')],
|
40
|
+
indexes: [],
|
41
|
+
}
|
42
|
+
|
43
|
+
const result = makeColumnSpec(table)
|
44
|
+
expect(result).toMatchInlineSnapshot(`"'id' text not null , 'name' text , PRIMARY KEY ('id')"`)
|
45
|
+
expect(result).toContain("PRIMARY KEY ('id')")
|
46
|
+
})
|
47
|
+
|
48
|
+
it('should handle multi-column primary keys', () => {
|
49
|
+
const table: SqliteAst.Table = {
|
50
|
+
_tag: 'table',
|
51
|
+
name: 'composite',
|
52
|
+
columns: [
|
53
|
+
createColumn('tenant_id', 'text', { nullable: false, primaryKey: true }),
|
54
|
+
createColumn('user_id', 'text', { nullable: false, primaryKey: true }),
|
55
|
+
],
|
56
|
+
indexes: [],
|
57
|
+
}
|
58
|
+
|
59
|
+
const result = makeColumnSpec(table)
|
60
|
+
expect(result).toMatchInlineSnapshot(
|
61
|
+
`"'tenant_id' text not null , 'user_id' text not null , PRIMARY KEY ('tenant_id', 'user_id')"`,
|
62
|
+
)
|
63
|
+
expect(result).toContain("PRIMARY KEY ('tenant_id', 'user_id')")
|
64
|
+
})
|
65
|
+
})
|
@@ -169,7 +169,7 @@ export const migrateTable = ({
|
|
169
169
|
|
170
170
|
const createIndexFromDefinition = (tableName: string, index: SqliteAst.Index) => {
|
171
171
|
const uniqueStr = index.unique ? 'UNIQUE' : ''
|
172
|
-
return sql`create ${uniqueStr} index if not exists '${index.name}' on '${tableName}' (${index.columns.join(', ')})`
|
172
|
+
return sql`create ${uniqueStr} index if not exists '${index.name}' on '${tableName}' (${index.columns.map((col) => `'${col}'`).join(', ')})`
|
173
173
|
}
|
174
174
|
|
175
175
|
export const makeColumnSpec = (tableAst: SqliteAst.Table) => {
|
@@ -3,6 +3,7 @@ import { LS_DEV, shouldNeverHappen, TRACE_VERBOSE } from '@livestore/utils'
|
|
3
3
|
import {
|
4
4
|
BucketQueue,
|
5
5
|
Effect,
|
6
|
+
Exit,
|
6
7
|
FiberHandle,
|
7
8
|
Option,
|
8
9
|
Queue,
|
@@ -316,7 +317,7 @@ export const makeClientSessionSyncProcessor = ({
|
|
316
317
|
refreshTables(writeTables)
|
317
318
|
}).pipe(
|
318
319
|
Effect.tapCauseLogPretty,
|
319
|
-
Effect.catchAllCause((cause) => clientSession.shutdown(cause)),
|
320
|
+
Effect.catchAllCause((cause) => clientSession.shutdown(Exit.failCause(cause))),
|
320
321
|
),
|
321
322
|
),
|
322
323
|
Stream.runDrain,
|
@@ -381,13 +382,14 @@ export interface ClientSessionSyncProcessor {
|
|
381
382
|
// TODO turn this into a build-time "macro" so all simulation snippets are removed for production builds
|
382
383
|
const SIMULATION_ENABLED = true
|
383
384
|
|
385
|
+
// Warning: High values for the simulation params can lead to very long test runs since those get multiplied with the number of events
|
384
386
|
export const ClientSessionSyncProcessorSimulationParams = Schema.Struct({
|
385
387
|
pull: Schema.Struct({
|
386
|
-
'1_before_leader_push_fiber_interrupt': Schema.Int.pipe(Schema.between(0,
|
387
|
-
'2_before_leader_push_queue_clear': Schema.Int.pipe(Schema.between(0,
|
388
|
-
'3_before_rebase_rollback': Schema.Int.pipe(Schema.between(0,
|
389
|
-
'4_before_leader_push_queue_offer': Schema.Int.pipe(Schema.between(0,
|
390
|
-
'5_before_leader_push_fiber_run': Schema.Int.pipe(Schema.between(0,
|
388
|
+
'1_before_leader_push_fiber_interrupt': Schema.Int.pipe(Schema.between(0, 25)),
|
389
|
+
'2_before_leader_push_queue_clear': Schema.Int.pipe(Schema.between(0, 25)),
|
390
|
+
'3_before_rebase_rollback': Schema.Int.pipe(Schema.between(0, 25)),
|
391
|
+
'4_before_leader_push_queue_offer': Schema.Int.pipe(Schema.between(0, 25)),
|
392
|
+
'5_before_leader_push_fiber_run': Schema.Int.pipe(Schema.between(0, 25)),
|
391
393
|
}),
|
392
394
|
})
|
393
395
|
type ClientSessionSyncProcessorSimulationParams = typeof ClientSessionSyncProcessorSimulationParams.Type
|
package/src/sync/sync.ts
CHANGED
@@ -31,6 +31,7 @@ export type SyncOptions = {
|
|
31
31
|
onSyncError?: 'shutdown' | 'ignore'
|
32
32
|
}
|
33
33
|
|
34
|
+
// TODO rename to `SyncProviderClientConstructor`
|
34
35
|
export type SyncBackendConstructor<TSyncMetadata = Schema.JsonValue> = (
|
35
36
|
args: MakeBackendArgs,
|
36
37
|
) => Effect.Effect<SyncBackend<TSyncMetadata>, UnexpectedError, Scope.Scope | HttpClient.HttpClient>
|
@@ -41,6 +42,7 @@ export type SyncBackendConstructor<TSyncMetadata = Schema.JsonValue> = (
|
|
41
42
|
// - dynamic sync backend data;
|
42
43
|
// - data center location (e.g. colo on CF workers)
|
43
44
|
|
45
|
+
// TODO rename to `SyncProviderClient`
|
44
46
|
export type SyncBackend<TSyncMetadata = Schema.JsonValue> = {
|
45
47
|
/**
|
46
48
|
* Can be implemented to prepare a connection to the sync backend to speed up the first pull/push.
|
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.3.2-dev.
|
5
|
+
export const liveStoreVersion = '0.3.2-dev.11' as const
|
6
6
|
|
7
7
|
/**
|
8
8
|
* This version number is incremented whenever the internal storage format changes in a breaking way.
|