@livestore/common 0.4.0-dev.7 → 0.4.0-dev.9

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.
Files changed (61) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/devtools/devtools-messages-client-session.d.ts +21 -21
  3. package/dist/devtools/devtools-messages-common.d.ts +6 -6
  4. package/dist/devtools/devtools-messages-leader.d.ts +24 -24
  5. package/dist/leader-thread/LeaderSyncProcessor.d.ts +4 -1
  6. package/dist/leader-thread/LeaderSyncProcessor.d.ts.map +1 -1
  7. package/dist/leader-thread/LeaderSyncProcessor.js +40 -14
  8. package/dist/leader-thread/LeaderSyncProcessor.js.map +1 -1
  9. package/dist/leader-thread/eventlog.js +1 -1
  10. package/dist/leader-thread/eventlog.js.map +1 -1
  11. package/dist/leader-thread/types.d.ts +1 -0
  12. package/dist/leader-thread/types.d.ts.map +1 -1
  13. package/dist/schema/state/sqlite/client-document-def.d.ts.map +1 -1
  14. package/dist/schema/state/sqlite/client-document-def.js +2 -2
  15. package/dist/schema/state/sqlite/client-document-def.js.map +1 -1
  16. package/dist/schema/state/sqlite/column-annotations.d.ts.map +1 -1
  17. package/dist/schema/state/sqlite/column-annotations.js +14 -6
  18. package/dist/schema/state/sqlite/column-annotations.js.map +1 -1
  19. package/dist/schema/state/sqlite/query-builder/impl.test.js +81 -0
  20. package/dist/schema/state/sqlite/query-builder/impl.test.js.map +1 -1
  21. package/dist/schema/state/sqlite/table-def.d.ts +4 -4
  22. package/dist/schema/state/sqlite/table-def.d.ts.map +1 -1
  23. package/dist/schema/state/sqlite/table-def.js +2 -2
  24. package/dist/schema/state/sqlite/table-def.js.map +1 -1
  25. package/dist/schema/state/sqlite/table-def.test.js +44 -0
  26. package/dist/schema/state/sqlite/table-def.test.js.map +1 -1
  27. package/dist/sync/ClientSessionSyncProcessor.d.ts.map +1 -1
  28. package/dist/sync/ClientSessionSyncProcessor.js +7 -3
  29. package/dist/sync/ClientSessionSyncProcessor.js.map +1 -1
  30. package/dist/sync/mock-sync-backend.d.ts +11 -2
  31. package/dist/sync/mock-sync-backend.d.ts.map +1 -1
  32. package/dist/sync/mock-sync-backend.js +59 -7
  33. package/dist/sync/mock-sync-backend.js.map +1 -1
  34. package/dist/testing/event-factory.d.ts +68 -0
  35. package/dist/testing/event-factory.d.ts.map +1 -0
  36. package/dist/testing/event-factory.js +80 -0
  37. package/dist/testing/event-factory.js.map +1 -0
  38. package/dist/testing/mod.d.ts +2 -0
  39. package/dist/testing/mod.d.ts.map +1 -0
  40. package/dist/testing/mod.js +2 -0
  41. package/dist/testing/mod.js.map +1 -0
  42. package/dist/version.d.ts +1 -1
  43. package/dist/version.js +1 -1
  44. package/package.json +6 -5
  45. package/src/leader-thread/LeaderSyncProcessor.ts +60 -17
  46. package/src/leader-thread/eventlog.ts +1 -1
  47. package/src/leader-thread/types.ts +1 -0
  48. package/src/schema/state/sqlite/client-document-def.ts +2 -2
  49. package/src/schema/state/sqlite/column-annotations.ts +16 -6
  50. package/src/schema/state/sqlite/query-builder/impl.test.ts +121 -0
  51. package/src/schema/state/sqlite/table-def.test.ts +53 -0
  52. package/src/schema/state/sqlite/table-def.ts +9 -8
  53. package/src/sync/ClientSessionSyncProcessor.ts +9 -3
  54. package/src/sync/mock-sync-backend.ts +104 -16
  55. package/src/testing/event-factory.ts +133 -0
  56. package/src/testing/mod.ts +1 -0
  57. package/src/version.ts +1 -1
  58. package/dist/schema-management/migrations.test.d.ts +0 -2
  59. package/dist/schema-management/migrations.test.d.ts.map +0 -1
  60. package/dist/schema-management/migrations.test.js +0 -52
  61. package/dist/schema-management/migrations.test.js.map +0 -1
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Helpers for synthesizing LiveStore events in tests while keeping track of
3
+ * sequence numbers, parent pointers, and authoring client identity. Inspired
4
+ * by the effect-based schema utilities, the factory exposes a namespaced API
5
+ * where each event definition maps to a helper with `next`, `advanceTo`, and
6
+ * `setParent` functions that share a single sequence stream.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * import { EventFactory } from '@livestore/common/testing'
11
+ * import { events } from './schema'
12
+ *
13
+ * const eventFactory = EventFactory.makeFactory(events)({
14
+ * client: EventFactory.clientIdentity('test-client'),
15
+ * startSeq: 1,
16
+ * initialParent: 'root',
17
+ * })
18
+ *
19
+ * const bootstrap = eventFactory.todoCreated.next({
20
+ * id: 'todo-1',
21
+ * text: 'write tests',
22
+ * completed: false,
23
+ * })
24
+ *
25
+ * eventFactory.todoCreated.advanceTo(42)
26
+ * const branched = eventFactory.todoUpdated.next({
27
+ * id: 'todo-1',
28
+ * text: 'ship feature',
29
+ * completed: true,
30
+ * })
31
+ * ```
32
+ */
33
+
34
+ import { Schema } from '@livestore/utils/effect'
35
+
36
+ import type { EventDef } from '../schema/EventDef.ts'
37
+ import * as EventSequenceNumber from '../schema/EventSequenceNumber.ts'
38
+ import * as LiveStoreEvent from '../schema/LiveStoreEvent.ts'
39
+
40
+ export interface ClientIdentity {
41
+ clientId: string
42
+ sessionId: string
43
+ }
44
+
45
+ export const clientIdentity = (label: string, session = `${label}-session`): ClientIdentity => ({
46
+ clientId: label,
47
+ sessionId: session,
48
+ })
49
+
50
+ export type SequenceValue = 'root' | number
51
+
52
+ type EventFactoriesArgs<TDefs extends Record<string, EventDef.Any>> = {
53
+ [K in keyof TDefs]: Parameters<TDefs[K]>[0]
54
+ }
55
+
56
+ type EventFactories<TDefs extends Record<string, EventDef.Any>, TResult> = {
57
+ [K in keyof TDefs]: {
58
+ next: (args: EventFactoriesArgs<TDefs>[K]) => TResult
59
+ advanceTo: (seq: number, parent?: SequenceValue) => void
60
+ setParent: (parent: SequenceValue) => void
61
+ current: () => { seq: number; parent: SequenceValue }
62
+ }
63
+ }
64
+
65
+ export interface EventFactoriesConfig {
66
+ client: ClientIdentity
67
+ /**
68
+ * @default 1
69
+ */
70
+ startSeq?: number
71
+ /**
72
+ * @default 0 (root)
73
+ */
74
+ initialParent?: SequenceValue
75
+ }
76
+
77
+ export const makeFactory =
78
+ <TDefs extends Record<string, EventDef.Any>>(eventDefs: TDefs) =>
79
+ ({
80
+ client,
81
+ startSeq = 1,
82
+ initialParent = 'root',
83
+ }: EventFactoriesConfig): EventFactories<TDefs, LiveStoreEvent.AnyEncodedGlobal> => {
84
+ let nextSeq = startSeq
85
+ let parentRef: SequenceValue = initialParent
86
+
87
+ const advanceTo = (seq: number, parent: SequenceValue = 'root') => {
88
+ nextSeq = seq
89
+ parentRef = parent
90
+ }
91
+
92
+ const setParent = (parent: SequenceValue) => {
93
+ parentRef = parent
94
+ }
95
+
96
+ const current = () => ({ seq: nextSeq, parent: parentRef })
97
+
98
+ const factories: Partial<EventFactories<TDefs, LiveStoreEvent.AnyEncodedGlobal>> = {}
99
+
100
+ for (const [name, eventDef] of Object.entries(eventDefs) as [keyof TDefs, TDefs[keyof TDefs]][]) {
101
+ const next = (args: EventFactoriesArgs<TDefs>[typeof name]) => {
102
+ const decoded = eventDef(args)
103
+ const encodedArgs = Schema.encodeSync(eventDef.schema)(decoded.args)
104
+ const encoded = eventDef.encoded(encodedArgs)
105
+
106
+ const event = LiveStoreEvent.AnyEncodedGlobal.make({
107
+ name: encoded.name,
108
+ args: encoded.args,
109
+ seqNum: EventSequenceNumber.globalEventSequenceNumber(nextSeq),
110
+ parentSeqNum:
111
+ parentRef === 'root'
112
+ ? EventSequenceNumber.ROOT.global
113
+ : EventSequenceNumber.globalEventSequenceNumber(parentRef),
114
+ clientId: client.clientId,
115
+ sessionId: client.sessionId,
116
+ })
117
+
118
+ parentRef = nextSeq
119
+ nextSeq = nextSeq + 1
120
+
121
+ return event
122
+ }
123
+
124
+ factories[name] = {
125
+ next,
126
+ advanceTo,
127
+ setParent,
128
+ current,
129
+ } as EventFactories<TDefs, LiveStoreEvent.AnyEncodedGlobal>[typeof name]
130
+ }
131
+
132
+ return factories as EventFactories<TDefs, LiveStoreEvent.AnyEncodedGlobal>
133
+ }
@@ -0,0 +1 @@
1
+ export * as EventFactory from './event-factory.ts'
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.7' as const
5
+ export const liveStoreVersion = '0.4.0-dev.9' as const
6
6
 
7
7
  /**
8
8
  * This version number is incremented whenever the internal storage format changes in a breaking way.
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=migrations.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"migrations.test.d.ts","sourceRoot":"","sources":["../../src/schema-management/migrations.test.ts"],"names":[],"mappings":""}
@@ -1,52 +0,0 @@
1
- import { Option, Schema } from '@livestore/utils/effect';
2
- import { describe, expect, it } from 'vitest';
3
- import { makeColumnSpec } from './migrations.js';
4
- const createColumn = (name, type, options = {}) => ({
5
- _tag: 'column',
6
- name,
7
- type: { _tag: type },
8
- nullable: options.nullable ?? true,
9
- primaryKey: options.primaryKey ?? false,
10
- default: Option.none(),
11
- schema: type === 'text' ? Schema.String : Schema.Number,
12
- });
13
- describe('makeColumnSpec', () => {
14
- it('should quote column names properly for reserved keywords', () => {
15
- const table = {
16
- _tag: 'table',
17
- name: 'blocks',
18
- columns: [createColumn('order', 'integer', { nullable: false }), createColumn('group', 'text')],
19
- indexes: [],
20
- };
21
- const result = makeColumnSpec(table);
22
- expect(result).toMatchInlineSnapshot(`"'order' integer not null , 'group' text "`);
23
- expect(result).toContain("'order'");
24
- expect(result).toContain("'group'");
25
- });
26
- it('should handle basic columns with primary keys', () => {
27
- const table = {
28
- _tag: 'table',
29
- name: 'users',
30
- columns: [createColumn('id', 'text', { nullable: false, primaryKey: true }), createColumn('name', 'text')],
31
- indexes: [],
32
- };
33
- const result = makeColumnSpec(table);
34
- expect(result).toMatchInlineSnapshot(`"'id' text not null , 'name' text , PRIMARY KEY ('id')"`);
35
- expect(result).toContain("PRIMARY KEY ('id')");
36
- });
37
- it('should handle multi-column primary keys', () => {
38
- const table = {
39
- _tag: 'table',
40
- name: 'composite',
41
- columns: [
42
- createColumn('tenant_id', 'text', { nullable: false, primaryKey: true }),
43
- createColumn('user_id', 'text', { nullable: false, primaryKey: true }),
44
- ],
45
- indexes: [],
46
- };
47
- const result = makeColumnSpec(table);
48
- expect(result).toMatchInlineSnapshot(`"'tenant_id' text not null , 'user_id' text not null , PRIMARY KEY ('tenant_id', 'user_id')"`);
49
- expect(result).toContain("PRIMARY KEY ('tenant_id', 'user_id')");
50
- });
51
- });
52
- //# sourceMappingURL=migrations.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"migrations.test.js","sourceRoot":"","sources":["../../src/schema-management/migrations.test.ts"],"names":[],"mappings":"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"}