@livestore/common 0.4.0-dev.10 → 0.4.0-dev.12
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/ClientSessionLeaderThreadProxy.d.ts +1 -1
- package/dist/ClientSessionLeaderThreadProxy.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.d.ts.map +1 -1
- package/dist/leader-thread/LeaderSyncProcessor.js +18 -8
- package/dist/leader-thread/LeaderSyncProcessor.js.map +1 -1
- package/dist/schema/EventSequenceNumber.d.ts +4 -1
- package/dist/schema/EventSequenceNumber.d.ts.map +1 -1
- package/dist/schema/EventSequenceNumber.js +4 -1
- package/dist/schema/EventSequenceNumber.js.map +1 -1
- package/dist/schema/EventSequenceNumber.test.js +2 -2
- package/dist/schema/state/sqlite/column-def.js +9 -3
- package/dist/schema/state/sqlite/column-def.js.map +1 -1
- package/dist/schema/state/sqlite/table-def.test.js +36 -0
- package/dist/schema/state/sqlite/table-def.test.js.map +1 -1
- package/dist/sync/ClientSessionSyncProcessor.d.ts.map +1 -1
- package/dist/sync/ClientSessionSyncProcessor.js +1 -0
- package/dist/sync/ClientSessionSyncProcessor.js.map +1 -1
- package/dist/sync/syncstate.test.js +16 -15
- package/dist/sync/syncstate.test.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +4 -4
- package/src/ClientSessionLeaderThreadProxy.ts +1 -1
- package/src/leader-thread/LeaderSyncProcessor.ts +31 -12
- package/src/schema/EventSequenceNumber.test.ts +2 -2
- package/src/schema/EventSequenceNumber.ts +5 -2
- package/src/schema/state/sqlite/column-def.ts +11 -3
- package/src/schema/state/sqlite/table-def.test.ts +48 -0
- package/src/sync/ClientSessionSyncProcessor.ts +1 -0
- package/src/sync/syncstate.test.ts +17 -15
- package/src/version.ts +1 -1
|
@@ -23,7 +23,7 @@ Vitest.describe('EventSequenceNumber', () => {
|
|
|
23
23
|
expect(EventSequenceNumber.nextPair({ seqNum: e_0_0, isClient: false, rebaseGeneration: 1 }).seqNum).toStrictEqual({
|
|
24
24
|
global: 1,
|
|
25
25
|
client: 0,
|
|
26
|
-
rebaseGeneration:
|
|
26
|
+
rebaseGeneration: 1,
|
|
27
27
|
})
|
|
28
28
|
expect(EventSequenceNumber.nextPair({ seqNum: e_0_0, isClient: true, rebaseGeneration: 1 }).seqNum).toStrictEqual({
|
|
29
29
|
global: 0,
|
|
@@ -35,7 +35,7 @@ Vitest.describe('EventSequenceNumber', () => {
|
|
|
35
35
|
expect(EventSequenceNumber.nextPair({ seqNum: e_0_0_g1, isClient: false }).seqNum).toStrictEqual({
|
|
36
36
|
global: 1,
|
|
37
37
|
client: 0,
|
|
38
|
-
rebaseGeneration:
|
|
38
|
+
rebaseGeneration: 2,
|
|
39
39
|
})
|
|
40
40
|
})
|
|
41
41
|
|
|
@@ -23,7 +23,7 @@ export type EventSequenceNumber = {
|
|
|
23
23
|
client: ClientEventSequenceNumber
|
|
24
24
|
/**
|
|
25
25
|
* Generation integer that is incremented whenever the client rebased.
|
|
26
|
-
*
|
|
26
|
+
* Remains constant for all subsequent events until another rebase occurs.
|
|
27
27
|
*/
|
|
28
28
|
rebaseGeneration: number
|
|
29
29
|
}
|
|
@@ -167,6 +167,9 @@ export const make = (seqNum: EventSequenceNumberInput): EventSequenceNumber => {
|
|
|
167
167
|
})
|
|
168
168
|
}
|
|
169
169
|
|
|
170
|
+
/**
|
|
171
|
+
* Computes the next event sequence/parent pair.
|
|
172
|
+
*/
|
|
170
173
|
export const nextPair = ({
|
|
171
174
|
seqNum,
|
|
172
175
|
isClient,
|
|
@@ -191,7 +194,7 @@ export const nextPair = ({
|
|
|
191
194
|
seqNum: {
|
|
192
195
|
global: (seqNum.global + 1) as any as GlobalEventSequenceNumber,
|
|
193
196
|
client: clientDefault,
|
|
194
|
-
rebaseGeneration:
|
|
197
|
+
rebaseGeneration: rebaseGeneration ?? seqNum.rebaseGeneration,
|
|
195
198
|
},
|
|
196
199
|
// NOTE we always point to `client: 0` for non-clientOnly events
|
|
197
200
|
parentSeqNum: { global: seqNum.global, client: clientDefault, rebaseGeneration: seqNum.rebaseGeneration },
|
|
@@ -206,10 +206,18 @@ const getColumnForSchema = (schema: Schema.Schema.AnyNoContext, nullable = false
|
|
|
206
206
|
const stripNullable = (ast: SchemaAST.AST): SchemaAST.AST => {
|
|
207
207
|
if (!SchemaAST.isUnion(ast)) return ast
|
|
208
208
|
|
|
209
|
-
//
|
|
210
|
-
const
|
|
209
|
+
// Filter out null/undefined members while preserving any annotations on the union
|
|
210
|
+
const coreTypes = ast.types.filter(
|
|
211
211
|
(type) => !(SchemaAST.isLiteral(type) && type.literal === null) && !SchemaAST.isUndefinedKeyword(type),
|
|
212
212
|
)
|
|
213
213
|
|
|
214
|
-
|
|
214
|
+
if (coreTypes.length === 0 || coreTypes.length === ast.types.length) {
|
|
215
|
+
return ast
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
if (coreTypes.length === 1) {
|
|
219
|
+
return coreTypes[0]!
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
return SchemaAST.Union.make(coreTypes, ast.annotations)
|
|
215
223
|
}
|
|
@@ -300,4 +300,52 @@ describe('table function overloads', () => {
|
|
|
300
300
|
expect(userTable.sqliteDef.columns.metadata.columnType).toBe('text')
|
|
301
301
|
expect(userTable.sqliteDef.columns.metadata.nullable).toBe(true)
|
|
302
302
|
})
|
|
303
|
+
|
|
304
|
+
it('supports discriminated unions with parsed JSON payloads', () => {
|
|
305
|
+
const CircleDataSchema = Schema.Struct({
|
|
306
|
+
radius: Schema.Number,
|
|
307
|
+
})
|
|
308
|
+
const CircleSchema = Schema.Struct({
|
|
309
|
+
kind: Schema.Literal('circle'),
|
|
310
|
+
data: Schema.parseJson(CircleDataSchema),
|
|
311
|
+
})
|
|
312
|
+
|
|
313
|
+
const SquareDataSchema = Schema.Struct({
|
|
314
|
+
sideLength: Schema.Number,
|
|
315
|
+
})
|
|
316
|
+
const SquareSchema = Schema.Struct({
|
|
317
|
+
kind: Schema.Literal('square'),
|
|
318
|
+
data: Schema.parseJson(SquareDataSchema),
|
|
319
|
+
})
|
|
320
|
+
|
|
321
|
+
const ShapeSchema = Schema.Union(CircleSchema, SquareSchema)
|
|
322
|
+
|
|
323
|
+
const shapes = State.SQLite.table({
|
|
324
|
+
name: 'shapes',
|
|
325
|
+
schema: ShapeSchema,
|
|
326
|
+
})
|
|
327
|
+
|
|
328
|
+
expect(shapes.sqliteDef.columns.kind.columnType).toBe('text')
|
|
329
|
+
|
|
330
|
+
const kindSchema = shapes.sqliteDef.columns.kind.schema.toString()
|
|
331
|
+
expect(kindSchema).toContain('"circle" | "square"')
|
|
332
|
+
|
|
333
|
+
expect(() =>
|
|
334
|
+
shapes
|
|
335
|
+
.insert({
|
|
336
|
+
kind: 'square',
|
|
337
|
+
data: { sideLength: 10 },
|
|
338
|
+
})
|
|
339
|
+
.asSql(),
|
|
340
|
+
).not.toThrow()
|
|
341
|
+
|
|
342
|
+
expect(() =>
|
|
343
|
+
shapes
|
|
344
|
+
.insert({
|
|
345
|
+
kind: 'circle',
|
|
346
|
+
data: { radius: 5 },
|
|
347
|
+
})
|
|
348
|
+
.asSql(),
|
|
349
|
+
).not.toThrow()
|
|
350
|
+
})
|
|
303
351
|
})
|
|
@@ -115,6 +115,7 @@ export const makeClientSessionSyncProcessor = ({
|
|
|
115
115
|
const nextNumPair = EventSequenceNumber.nextPair({
|
|
116
116
|
seqNum: baseEventSequenceNumber,
|
|
117
117
|
isClient: eventDef.options.clientOnly,
|
|
118
|
+
rebaseGeneration: baseEventSequenceNumber.rebaseGeneration,
|
|
118
119
|
})
|
|
119
120
|
baseEventSequenceNumber = nextNumPair.seqNum
|
|
120
121
|
return new LiveStoreEvent.EncodedWithMeta(
|
|
@@ -5,15 +5,16 @@ import * as LiveStoreEvent from '../schema/LiveStoreEvent.ts'
|
|
|
5
5
|
import * as SyncState from './syncstate.ts'
|
|
6
6
|
|
|
7
7
|
class TestEvent extends LiveStoreEvent.EncodedWithMeta {
|
|
8
|
-
public
|
|
9
|
-
public
|
|
10
|
-
|
|
8
|
+
public payload = 'uninitialized'
|
|
9
|
+
public isClient = false
|
|
10
|
+
|
|
11
|
+
static new = (
|
|
11
12
|
seqNum: EventSequenceNumber.EventSequenceNumberInput,
|
|
12
13
|
parentSeqNum: EventSequenceNumber.EventSequenceNumberInput,
|
|
13
14
|
payload: string,
|
|
14
15
|
isClient: boolean,
|
|
15
|
-
) {
|
|
16
|
-
|
|
16
|
+
) => {
|
|
17
|
+
const event = new TestEvent({
|
|
17
18
|
seqNum: EventSequenceNumber.make(seqNum),
|
|
18
19
|
parentSeqNum: EventSequenceNumber.make(parentSeqNum),
|
|
19
20
|
name: 'a',
|
|
@@ -21,8 +22,9 @@ class TestEvent extends LiveStoreEvent.EncodedWithMeta {
|
|
|
21
22
|
clientId: 'static-local-id',
|
|
22
23
|
sessionId: 'static-session-id',
|
|
23
24
|
})
|
|
24
|
-
|
|
25
|
-
|
|
25
|
+
event.payload = payload
|
|
26
|
+
event.isClient = isClient
|
|
27
|
+
return event
|
|
26
28
|
}
|
|
27
29
|
|
|
28
30
|
rebase_ = (parentSeqNum: EventSequenceNumber.EventSequenceNumber, rebaseGeneration: number) => {
|
|
@@ -34,13 +36,13 @@ class TestEvent extends LiveStoreEvent.EncodedWithMeta {
|
|
|
34
36
|
// toString = () => this.toJSON()
|
|
35
37
|
}
|
|
36
38
|
|
|
37
|
-
const e0_1 = new
|
|
38
|
-
const e1_0 = new
|
|
39
|
-
const e1_1 = new
|
|
40
|
-
const e1_2 = new
|
|
41
|
-
const e1_3 = new
|
|
42
|
-
const e2_0 = new
|
|
43
|
-
const e2_1 = new
|
|
39
|
+
const e0_1 = TestEvent.new({ global: 0, client: 1 }, EventSequenceNumber.ROOT, 'a', true)
|
|
40
|
+
const e1_0 = TestEvent.new({ global: 1, client: 0 }, EventSequenceNumber.ROOT, 'a', false)
|
|
41
|
+
const e1_1 = TestEvent.new({ global: 1, client: 1 }, e1_0.seqNum, 'a', true)
|
|
42
|
+
const e1_2 = TestEvent.new({ global: 1, client: 2 }, e1_1.seqNum, 'a', true)
|
|
43
|
+
const e1_3 = TestEvent.new({ global: 1, client: 3 }, e1_2.seqNum, 'a', true)
|
|
44
|
+
const e2_0 = TestEvent.new({ global: 2, client: 0 }, e1_0.seqNum, 'a', false)
|
|
45
|
+
const e2_1 = TestEvent.new({ global: 2, client: 1 }, e2_0.seqNum, 'a', true)
|
|
44
46
|
|
|
45
47
|
const isEqualEvent = LiveStoreEvent.isEqualEncoded
|
|
46
48
|
|
|
@@ -340,7 +342,7 @@ describe('syncstate', () => {
|
|
|
340
342
|
})
|
|
341
343
|
|
|
342
344
|
it('should rebase different event with same id', () => {
|
|
343
|
-
const e2_0_b = new
|
|
345
|
+
const e2_0_b = TestEvent.new({ global: 1, client: 0 }, e1_0.seqNum, '1_0_b', false)
|
|
344
346
|
const syncState = new SyncState.SyncState({
|
|
345
347
|
pending: [e2_0_b],
|
|
346
348
|
upstreamHead: EventSequenceNumber.ROOT,
|
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.12' as const
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* This version number is incremented whenever the internal storage format changes in a breaking way.
|