@livestore/common 0.3.0-dev.12 → 0.3.0-dev.14
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/__tests__/fixture.d.ts +21 -21
- package/dist/db-schema/ast/sqlite.d.ts +69 -0
- package/dist/db-schema/ast/sqlite.d.ts.map +1 -0
- package/dist/db-schema/ast/sqlite.js +71 -0
- package/dist/db-schema/ast/sqlite.js.map +1 -0
- package/dist/db-schema/ast/validate.d.ts +3 -0
- package/dist/db-schema/ast/validate.d.ts.map +1 -0
- package/dist/db-schema/ast/validate.js +12 -0
- package/dist/db-schema/ast/validate.js.map +1 -0
- package/dist/db-schema/dsl/field-defs.d.ts +90 -0
- package/dist/db-schema/dsl/field-defs.d.ts.map +1 -0
- package/dist/db-schema/dsl/field-defs.js +87 -0
- package/dist/db-schema/dsl/field-defs.js.map +1 -0
- package/dist/db-schema/dsl/field-defs.test.d.ts +2 -0
- package/dist/db-schema/dsl/field-defs.test.d.ts.map +1 -0
- package/dist/db-schema/dsl/field-defs.test.js +29 -0
- package/dist/db-schema/dsl/field-defs.test.js.map +1 -0
- package/dist/db-schema/dsl/index.d.ts +88 -0
- package/dist/db-schema/dsl/index.d.ts.map +1 -0
- package/dist/db-schema/dsl/index.js +35 -0
- package/dist/db-schema/dsl/index.js.map +1 -0
- package/dist/db-schema/dsl/mod.d.ts +90 -0
- package/dist/db-schema/dsl/mod.d.ts.map +1 -0
- package/dist/db-schema/dsl/mod.js +35 -0
- package/dist/db-schema/dsl/mod.js.map +1 -0
- package/dist/db-schema/dsl/sqlite/field-defs.d.ts +90 -0
- package/dist/db-schema/dsl/sqlite/field-defs.d.ts.map +1 -0
- package/dist/db-schema/dsl/sqlite/field-defs.js +86 -0
- package/dist/db-schema/dsl/sqlite/field-defs.js.map +1 -0
- package/dist/db-schema/dsl/sqlite/field-defs.test.d.ts +2 -0
- package/dist/db-schema/dsl/sqlite/field-defs.test.d.ts.map +1 -0
- package/dist/db-schema/dsl/sqlite/field-defs.test.js +29 -0
- package/dist/db-schema/dsl/sqlite/field-defs.test.js.map +1 -0
- package/dist/db-schema/dsl/sqlite/index.d.ts +88 -0
- package/dist/db-schema/dsl/sqlite/index.d.ts.map +1 -0
- package/dist/db-schema/dsl/sqlite/index.js +35 -0
- package/dist/db-schema/dsl/sqlite/index.js.map +1 -0
- package/dist/db-schema/hash.d.ts +2 -0
- package/dist/db-schema/hash.d.ts.map +1 -0
- package/dist/db-schema/hash.js +14 -0
- package/dist/db-schema/hash.js.map +1 -0
- package/dist/db-schema/index.d.ts +4 -0
- package/dist/db-schema/index.d.ts.map +1 -0
- package/dist/db-schema/index.js +6 -0
- package/dist/db-schema/index.js.map +1 -0
- package/dist/db-schema/mod.d.ts +3 -0
- package/dist/db-schema/mod.d.ts.map +1 -0
- package/dist/db-schema/mod.js +3 -0
- package/dist/db-schema/mod.js.map +1 -0
- package/dist/derived-mutations.d.ts +1 -1
- package/dist/derived-mutations.d.ts.map +1 -1
- package/dist/derived-mutations.js +3 -3
- package/dist/derived-mutations.js.map +1 -1
- package/dist/devtools/devtools-messages-client-session.d.ts +23 -23
- package/dist/devtools/devtools-messages-common.d.ts +6 -6
- package/dist/devtools/devtools-messages-leader.d.ts +41 -53
- package/dist/devtools/devtools-messages-leader.d.ts.map +1 -1
- package/dist/devtools/devtools-messages-leader.js +5 -4
- package/dist/devtools/devtools-messages-leader.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/leader-thread/LeaderSyncProcessor.d.ts.map +1 -1
- package/dist/leader-thread/LeaderSyncProcessor.js +24 -22
- package/dist/leader-thread/LeaderSyncProcessor.js.map +1 -1
- package/dist/leader-thread/apply-mutation.d.ts.map +1 -1
- package/dist/leader-thread/apply-mutation.js +8 -6
- package/dist/leader-thread/apply-mutation.js.map +1 -1
- package/dist/leader-thread/leader-worker-devtools.d.ts.map +1 -1
- package/dist/leader-thread/leader-worker-devtools.js +6 -12
- package/dist/leader-thread/leader-worker-devtools.js.map +1 -1
- package/dist/leader-thread/make-leader-thread-layer.js +6 -1
- package/dist/leader-thread/make-leader-thread-layer.js.map +1 -1
- package/dist/leader-thread/mutationlog.d.ts +1 -1
- package/dist/leader-thread/mutationlog.d.ts.map +1 -1
- package/dist/leader-thread/mutationlog.js +7 -5
- package/dist/leader-thread/mutationlog.js.map +1 -1
- package/dist/leader-thread/pull-queue-set.d.ts.map +1 -1
- package/dist/leader-thread/types.d.ts +7 -3
- package/dist/leader-thread/types.d.ts.map +1 -1
- package/dist/leader-thread/types.js +1 -1
- package/dist/leader-thread/types.js.map +1 -1
- package/dist/query-builder/api.d.ts +1 -1
- package/dist/query-builder/api.d.ts.map +1 -1
- package/dist/rehydrate-from-mutationlog.d.ts.map +1 -1
- package/dist/rehydrate-from-mutationlog.js +8 -6
- package/dist/rehydrate-from-mutationlog.js.map +1 -1
- package/dist/schema/EventId.d.ts +9 -9
- package/dist/schema/EventId.d.ts.map +1 -1
- package/dist/schema/EventId.js +12 -12
- package/dist/schema/EventId.js.map +1 -1
- package/dist/schema/EventId.test.js +3 -3
- package/dist/schema/EventId.test.js.map +1 -1
- package/dist/schema/MutationEvent.d.ts +37 -12
- package/dist/schema/MutationEvent.d.ts.map +1 -1
- package/dist/schema/MutationEvent.js +20 -4
- package/dist/schema/MutationEvent.js.map +1 -1
- package/dist/schema/db-schema/ast/sqlite.d.ts +69 -0
- package/dist/schema/db-schema/ast/sqlite.d.ts.map +1 -0
- package/dist/schema/db-schema/ast/sqlite.js +71 -0
- package/dist/schema/db-schema/ast/sqlite.js.map +1 -0
- package/dist/schema/db-schema/ast/validate.d.ts +3 -0
- package/dist/schema/db-schema/ast/validate.d.ts.map +1 -0
- package/dist/schema/db-schema/ast/validate.js +12 -0
- package/dist/schema/db-schema/ast/validate.js.map +1 -0
- package/dist/schema/db-schema/dsl/field-defs.d.ts +90 -0
- package/dist/schema/db-schema/dsl/field-defs.d.ts.map +1 -0
- package/dist/schema/db-schema/dsl/field-defs.js +87 -0
- package/dist/schema/db-schema/dsl/field-defs.js.map +1 -0
- package/dist/schema/db-schema/dsl/field-defs.test.d.ts +2 -0
- package/dist/schema/db-schema/dsl/field-defs.test.d.ts.map +1 -0
- package/dist/schema/db-schema/dsl/field-defs.test.js +29 -0
- package/dist/schema/db-schema/dsl/field-defs.test.js.map +1 -0
- package/dist/schema/db-schema/dsl/mod.d.ts +88 -0
- package/dist/schema/db-schema/dsl/mod.d.ts.map +1 -0
- package/dist/schema/db-schema/dsl/mod.js +35 -0
- package/dist/schema/db-schema/dsl/mod.js.map +1 -0
- package/dist/schema/db-schema/hash.d.ts +2 -0
- package/dist/schema/db-schema/hash.d.ts.map +1 -0
- package/dist/schema/db-schema/hash.js +14 -0
- package/dist/schema/db-schema/hash.js.map +1 -0
- package/dist/schema/db-schema/mod.d.ts +3 -0
- package/dist/schema/db-schema/mod.d.ts.map +1 -0
- package/dist/schema/db-schema/mod.js +3 -0
- package/dist/schema/db-schema/mod.js.map +1 -0
- package/dist/schema/mod.d.ts +1 -0
- package/dist/schema/mod.d.ts.map +1 -1
- package/dist/schema/mod.js +1 -0
- package/dist/schema/mod.js.map +1 -1
- package/dist/schema/mutations.d.ts +5 -9
- package/dist/schema/mutations.d.ts.map +1 -1
- package/dist/schema/mutations.js +2 -2
- package/dist/schema/mutations.js.map +1 -1
- package/dist/schema/schema-helpers.js +1 -1
- package/dist/schema/schema-helpers.js.map +1 -1
- package/dist/schema/schema.d.ts +1 -1
- package/dist/schema/schema.d.ts.map +1 -1
- package/dist/schema/schema.js +1 -1
- package/dist/schema/schema.js.map +1 -1
- package/dist/schema/system-tables.d.ts +47 -29
- package/dist/schema/system-tables.d.ts.map +1 -1
- package/dist/schema/system-tables.js +10 -7
- package/dist/schema/system-tables.js.map +1 -1
- package/dist/schema/table-def.d.ts +18 -14
- package/dist/schema/table-def.d.ts.map +1 -1
- package/dist/schema/table-def.js +3 -4
- package/dist/schema/table-def.js.map +1 -1
- package/dist/schema-management/migrations.d.ts +1 -1
- package/dist/schema-management/migrations.d.ts.map +1 -1
- package/dist/schema-management/migrations.js +1 -1
- package/dist/schema-management/migrations.js.map +1 -1
- package/dist/sql-queries/sql-queries.d.ts +1 -1
- package/dist/sql-queries/sql-queries.d.ts.map +1 -1
- package/dist/sql-queries/sql-queries.js.map +1 -1
- package/dist/sql-queries/sql-query-builder.d.ts +1 -1
- package/dist/sql-queries/sql-query-builder.d.ts.map +1 -1
- package/dist/sql-queries/sql-query-builder.js.map +1 -1
- package/dist/sql-queries/types.d.ts +2 -1
- package/dist/sql-queries/types.d.ts.map +1 -1
- package/dist/sql-queries/types.js.map +1 -1
- package/dist/sync/ClientSessionSyncProcessor.d.ts.map +1 -1
- package/dist/sync/ClientSessionSyncProcessor.js +18 -3
- package/dist/sync/ClientSessionSyncProcessor.js.map +1 -1
- package/dist/sync/next/facts.js +1 -1
- package/dist/sync/next/facts.js.map +1 -1
- package/dist/sync/next/history-dag-common.d.ts +2 -0
- package/dist/sync/next/history-dag-common.d.ts.map +1 -1
- package/dist/sync/next/history-dag-common.js +3 -1
- package/dist/sync/next/history-dag-common.js.map +1 -1
- package/dist/sync/next/history-dag.d.ts.map +1 -1
- package/dist/sync/next/history-dag.js +1 -1
- package/dist/sync/next/history-dag.js.map +1 -1
- package/dist/sync/next/rebase-events.d.ts +3 -1
- package/dist/sync/next/rebase-events.d.ts.map +1 -1
- package/dist/sync/next/rebase-events.js +5 -3
- package/dist/sync/next/rebase-events.js.map +1 -1
- package/dist/sync/next/test/compact-events.calculator.test.js +12 -12
- package/dist/sync/next/test/compact-events.calculator.test.js.map +1 -1
- package/dist/sync/next/test/compact-events.test.js +43 -43
- package/dist/sync/next/test/compact-events.test.js.map +1 -1
- package/dist/sync/next/test/mutation-fixtures.d.ts +11 -11
- package/dist/sync/next/test/mutation-fixtures.d.ts.map +1 -1
- package/dist/sync/next/test/mutation-fixtures.js +12 -10
- package/dist/sync/next/test/mutation-fixtures.js.map +1 -1
- package/dist/sync/sync.d.ts +2 -2
- package/dist/sync/syncstate.d.ts +9 -9
- package/dist/sync/syncstate.js +6 -6
- package/dist/sync/syncstate.js.map +1 -1
- package/dist/sync/syncstate.test.js +18 -16
- 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 +2 -3
- package/src/derived-mutations.ts +4 -4
- package/src/devtools/devtools-messages-leader.ts +5 -4
- package/src/index.ts +1 -1
- package/src/leader-thread/LeaderSyncProcessor.ts +28 -22
- package/src/leader-thread/apply-mutation.ts +15 -5
- package/src/leader-thread/leader-worker-devtools.ts +6 -13
- package/src/leader-thread/make-leader-thread-layer.ts +9 -1
- package/src/leader-thread/mutationlog.ts +8 -6
- package/src/leader-thread/types.ts +6 -2
- package/src/query-builder/api.ts +1 -1
- package/src/rehydrate-from-mutationlog.ts +8 -6
- package/src/schema/EventId.test.ts +3 -3
- package/src/schema/EventId.ts +17 -17
- package/src/schema/MutationEvent.ts +31 -6
- package/src/schema/db-schema/ast/sqlite.ts +142 -0
- package/src/schema/db-schema/ast/validate.ts +13 -0
- package/src/schema/db-schema/dsl/__snapshots__/field-defs.test.ts.snap +206 -0
- package/src/schema/db-schema/dsl/field-defs.test.ts +35 -0
- package/src/schema/db-schema/dsl/field-defs.ts +242 -0
- package/src/schema/db-schema/dsl/mod.ts +195 -0
- package/src/schema/db-schema/hash.ts +14 -0
- package/src/schema/db-schema/mod.ts +2 -0
- package/src/schema/mod.ts +1 -0
- package/src/schema/mutations.ts +6 -19
- package/src/schema/schema-helpers.ts +1 -1
- package/src/schema/schema.ts +2 -2
- package/src/schema/system-tables.ts +10 -7
- package/src/schema/table-def.ts +17 -16
- package/src/schema-management/migrations.ts +1 -1
- package/src/sql-queries/sql-queries.ts +1 -1
- package/src/sql-queries/sql-query-builder.ts +1 -2
- package/src/sql-queries/types.ts +3 -1
- package/src/sync/ClientSessionSyncProcessor.ts +23 -4
- package/src/sync/next/facts.ts +1 -1
- package/src/sync/next/history-dag-common.ts +5 -1
- package/src/sync/next/history-dag.ts +1 -1
- package/src/sync/next/rebase-events.ts +8 -2
- package/src/sync/next/test/compact-events.calculator.test.ts +12 -12
- package/src/sync/next/test/compact-events.test.ts +43 -43
- package/src/sync/next/test/mutation-fixtures.ts +16 -12
- package/src/sync/syncstate.test.ts +19 -17
- package/src/sync/syncstate.ts +6 -6
- package/src/version.ts +1 -1
- package/tsconfig.json +1 -1
@@ -37,7 +37,7 @@ const customStringify = (value: any): string => {
|
|
37
37
|
const valStr =
|
38
38
|
key === 'facts'
|
39
39
|
? `"${factsToString(val)}"`
|
40
|
-
: (key === 'id' || key === 'parentId') && Object.keys(val).length === 2 && val.
|
40
|
+
: (key === 'id' || key === 'parentId') && Object.keys(val).length === 2 && val.client === 0
|
41
41
|
? val.global
|
42
42
|
: customStringify(val)
|
43
43
|
|
@@ -71,7 +71,7 @@ export const customSerializer = {
|
|
71
71
|
expect.addSnapshotSerializer(customSerializer)
|
72
72
|
|
73
73
|
const compact = (events: any[]) => {
|
74
|
-
const dag = historyDagFromNodes(toEventNodes(events, mutations))
|
74
|
+
const dag = historyDagFromNodes(toEventNodes(events, mutations, 'client-id', 'session-id'))
|
75
75
|
const compacted = compactEvents(dag)
|
76
76
|
|
77
77
|
return Array.from(compacted.dag.nodeEntries())
|
@@ -81,17 +81,17 @@ const compact = (events: any[]) => {
|
|
81
81
|
}
|
82
82
|
|
83
83
|
describe('compactEvents todo app', () => {
|
84
|
-
it('
|
84
|
+
it('todoCompleted', () => {
|
85
85
|
const expected = compact([
|
86
86
|
mutations.createTodo({ id: 'A', text: 'buy milk' }), // 0
|
87
|
-
mutations.
|
88
|
-
mutations.
|
87
|
+
mutations.todoCompleted({ id: 'A' }), // 1
|
88
|
+
mutations.todoCompleted({ id: 'A' }), // 2
|
89
89
|
])
|
90
90
|
|
91
91
|
expect(expected).toMatchInlineSnapshot(`
|
92
92
|
[
|
93
|
-
{ id: 0, parentId: -1, mutation: "createTodo", args: { id: "A", text: "buy milk" }, facts: "+todo-exists-A +todo-is-writeable-A=true +todo-completed-A=false" }
|
94
|
-
{ id: 2, parentId: 0, mutation: "
|
93
|
+
{ id: 0, parentId: -1, mutation: "createTodo", args: { id: "A", text: "buy milk" }, clientId: "client-id", sessionId: "session-id", facts: "+todo-exists-A +todo-is-writeable-A=true +todo-completed-A=false" }
|
94
|
+
{ id: 2, parentId: 0, mutation: "todoCompleted", args: { id: "A" }, clientId: "client-id", sessionId: "session-id", facts: "↖todo-exists-A ↖todo-is-writeable-A=true +todo-completed-A=true" }
|
95
95
|
]
|
96
96
|
`)
|
97
97
|
})
|
@@ -106,29 +106,29 @@ describe('compactEvents todo app', () => {
|
|
106
106
|
|
107
107
|
expect(expected).toMatchInlineSnapshot(`
|
108
108
|
[
|
109
|
-
{ id: 0, parentId: -1, mutation: "createTodo", args: { id: "A", text: "buy milk" }, facts: "+todo-exists-A +todo-is-writeable-A=true +todo-completed-A=false" }
|
110
|
-
{ id: 1, parentId: 0, mutation: "toggleTodo", args: { id: "A" }, facts: "↖todo-exists-A ↖todo-is-writeable-A=true ?todo-completed-A +todo-completed-A=true" }
|
111
|
-
{ id: 2, parentId: 1, mutation: "toggleTodo", args: { id: "A" }, facts: "↖todo-exists-A ↖todo-is-writeable-A=true ?todo-completed-A +todo-completed-A=false" }
|
112
|
-
{ id: 3, parentId: 2, mutation: "toggleTodo", args: { id: "A" }, facts: "↖todo-exists-A ↖todo-is-writeable-A=true ?todo-completed-A +todo-completed-A=true" }
|
109
|
+
{ id: 0, parentId: -1, mutation: "createTodo", args: { id: "A", text: "buy milk" }, clientId: "client-id", sessionId: "session-id", facts: "+todo-exists-A +todo-is-writeable-A=true +todo-completed-A=false" }
|
110
|
+
{ id: 1, parentId: 0, mutation: "toggleTodo", args: { id: "A" }, clientId: "client-id", sessionId: "session-id", facts: "↖todo-exists-A ↖todo-is-writeable-A=true ?todo-completed-A +todo-completed-A=true" }
|
111
|
+
{ id: 2, parentId: 1, mutation: "toggleTodo", args: { id: "A" }, clientId: "client-id", sessionId: "session-id", facts: "↖todo-exists-A ↖todo-is-writeable-A=true ?todo-completed-A +todo-completed-A=false" }
|
112
|
+
{ id: 3, parentId: 2, mutation: "toggleTodo", args: { id: "A" }, clientId: "client-id", sessionId: "session-id", facts: "↖todo-exists-A ↖todo-is-writeable-A=true ?todo-completed-A +todo-completed-A=true" }
|
113
113
|
]
|
114
114
|
`)
|
115
115
|
})
|
116
116
|
|
117
|
-
it('
|
117
|
+
it('todoCompleted / toggleTodo', () => {
|
118
118
|
const expected = compact([
|
119
119
|
mutations.createTodo({ id: 'A', text: 'buy milk' }), // 0
|
120
120
|
mutations.toggleTodo({ id: 'A' }), // 1
|
121
121
|
mutations.toggleTodo({ id: 'A' }), // 2
|
122
|
-
mutations.
|
123
|
-
mutations.
|
122
|
+
mutations.todoCompleted({ id: 'A' }), // 3
|
123
|
+
mutations.todoCompleted({ id: 'A' }), // 4
|
124
124
|
mutations.toggleTodo({ id: 'A' }), // 5
|
125
125
|
])
|
126
126
|
|
127
127
|
expect(expected).toMatchInlineSnapshot(`
|
128
128
|
[
|
129
|
-
{ id: 0, parentId: -1, mutation: "createTodo", args: { id: "A", text: "buy milk" }, facts: "+todo-exists-A +todo-is-writeable-A=true +todo-completed-A=false" }
|
130
|
-
{ id: 4, parentId: 0, mutation: "
|
131
|
-
{ id: 5, parentId: 4, mutation: "toggleTodo", args: { id: "A" }, facts: "↖todo-exists-A ↖todo-is-writeable-A=true ?todo-completed-A +todo-completed-A=false" }
|
129
|
+
{ id: 0, parentId: -1, mutation: "createTodo", args: { id: "A", text: "buy milk" }, clientId: "client-id", sessionId: "session-id", facts: "+todo-exists-A +todo-is-writeable-A=true +todo-completed-A=false" }
|
130
|
+
{ id: 4, parentId: 0, mutation: "todoCompleted", args: { id: "A" }, clientId: "client-id", sessionId: "session-id", facts: "↖todo-exists-A ↖todo-is-writeable-A=true +todo-completed-A=true" }
|
131
|
+
{ id: 5, parentId: 4, mutation: "toggleTodo", args: { id: "A" }, clientId: "client-id", sessionId: "session-id", facts: "↖todo-exists-A ↖todo-is-writeable-A=true ?todo-completed-A +todo-completed-A=false" }
|
132
132
|
]
|
133
133
|
`)
|
134
134
|
})
|
@@ -143,10 +143,10 @@ describe('compactEvents todo app', () => {
|
|
143
143
|
|
144
144
|
expect(expected).toMatchInlineSnapshot(`
|
145
145
|
[
|
146
|
-
{ id: 0, parentId: -1, mutation: "createTodo", args: { id: "A", text: "buy milk" }, facts: "+todo-exists-A +todo-is-writeable-A=true +todo-completed-A=false" }
|
147
|
-
{ id: 1, parentId: 0, mutation: "setReadonlyTodo", args: { id: "A", readonly: false }, facts: "↖todo-exists-A +todo-is-writeable-A=true" }
|
148
|
-
{ id: 2, parentId: 1, mutation: "setTextTodo", args: { id: "A", text: "buy soy milk" }, facts: "↖todo-exists-A ↖todo-is-writeable-A=true +todo-text-updated-A" }
|
149
|
-
{ id: 3, parentId: 2, mutation: "setReadonlyTodo", args: { id: "A", readonly: true }, facts: "↖todo-exists-A +todo-is-writeable-A=false" }
|
146
|
+
{ id: 0, parentId: -1, mutation: "createTodo", args: { id: "A", text: "buy milk" }, clientId: "client-id", sessionId: "session-id", facts: "+todo-exists-A +todo-is-writeable-A=true +todo-completed-A=false" }
|
147
|
+
{ id: 1, parentId: 0, mutation: "setReadonlyTodo", args: { id: "A", readonly: false }, clientId: "client-id", sessionId: "session-id", facts: "↖todo-exists-A +todo-is-writeable-A=true" }
|
148
|
+
{ id: 2, parentId: 1, mutation: "setTextTodo", args: { id: "A", text: "buy soy milk" }, clientId: "client-id", sessionId: "session-id", facts: "↖todo-exists-A ↖todo-is-writeable-A=true +todo-text-updated-A" }
|
149
|
+
{ id: 3, parentId: 2, mutation: "setReadonlyTodo", args: { id: "A", readonly: true }, clientId: "client-id", sessionId: "session-id", facts: "↖todo-exists-A +todo-is-writeable-A=false" }
|
150
150
|
]
|
151
151
|
`)
|
152
152
|
})
|
@@ -155,18 +155,18 @@ describe('compactEvents todo app', () => {
|
|
155
155
|
const expected = compact([
|
156
156
|
mutations.createTodo({ id: 'A', text: 'buy milk' }), // 0
|
157
157
|
mutations.setReadonlyTodo({ id: 'A', readonly: false }), // 1
|
158
|
-
mutations.
|
158
|
+
mutations.todoCompleted({ id: 'A' }), // 2
|
159
159
|
mutations.setTextTodo({ id: 'A', text: 'buy soy milk' }), // 3
|
160
160
|
mutations.setReadonlyTodo({ id: 'A', readonly: true }), // 4
|
161
161
|
])
|
162
162
|
|
163
163
|
expect(expected).toMatchInlineSnapshot(`
|
164
164
|
[
|
165
|
-
{ id: 0, parentId: -1, mutation: "createTodo", args: { id: "A", text: "buy milk" }, facts: "+todo-exists-A +todo-is-writeable-A=true +todo-completed-A=false" }
|
166
|
-
{ id: 1, parentId: 0, mutation: "setReadonlyTodo", args: { id: "A", readonly: false }, facts: "↖todo-exists-A +todo-is-writeable-A=true" }
|
167
|
-
{ id: 2, parentId: 1, mutation: "
|
168
|
-
{ id: 3, parentId: 2, mutation: "setTextTodo", args: { id: "A", text: "buy soy milk" }, facts: "↖todo-exists-A ↖todo-is-writeable-A=true +todo-text-updated-A" }
|
169
|
-
{ id: 4, parentId: 3, mutation: "setReadonlyTodo", args: { id: "A", readonly: true }, facts: "↖todo-exists-A +todo-is-writeable-A=false" }
|
165
|
+
{ id: 0, parentId: -1, mutation: "createTodo", args: { id: "A", text: "buy milk" }, clientId: "client-id", sessionId: "session-id", facts: "+todo-exists-A +todo-is-writeable-A=true +todo-completed-A=false" }
|
166
|
+
{ id: 1, parentId: 0, mutation: "setReadonlyTodo", args: { id: "A", readonly: false }, clientId: "client-id", sessionId: "session-id", facts: "↖todo-exists-A +todo-is-writeable-A=true" }
|
167
|
+
{ id: 2, parentId: 1, mutation: "todoCompleted", args: { id: "A" }, clientId: "client-id", sessionId: "session-id", facts: "↖todo-exists-A ↖todo-is-writeable-A=true +todo-completed-A=true" }
|
168
|
+
{ id: 3, parentId: 2, mutation: "setTextTodo", args: { id: "A", text: "buy soy milk" }, clientId: "client-id", sessionId: "session-id", facts: "↖todo-exists-A ↖todo-is-writeable-A=true +todo-text-updated-A" }
|
169
|
+
{ id: 4, parentId: 3, mutation: "setReadonlyTodo", args: { id: "A", readonly: true }, clientId: "client-id", sessionId: "session-id", facts: "↖todo-exists-A +todo-is-writeable-A=false" }
|
170
170
|
]
|
171
171
|
`)
|
172
172
|
})
|
@@ -188,45 +188,45 @@ describe('compactEvents todo app', () => {
|
|
188
188
|
`)
|
189
189
|
})
|
190
190
|
|
191
|
-
it('
|
191
|
+
it('todoCompleteds', () => {
|
192
192
|
const expected = compact([
|
193
193
|
mutations.createTodo({ id: 'A', text: 'buy milk' }), // 0
|
194
194
|
mutations.createTodo({ id: 'B', text: 'buy bread' }), // 1
|
195
195
|
mutations.createTodo({ id: 'C', text: 'buy cheese' }), // 2
|
196
|
-
mutations.
|
196
|
+
mutations.todoCompleteds({ ids: ['A', 'B', 'C'] }), // 3
|
197
197
|
mutations.toggleTodo({ id: 'A' }), // 4
|
198
|
-
mutations.
|
198
|
+
mutations.todoCompleted({ id: 'A' }), // 5
|
199
199
|
])
|
200
200
|
|
201
201
|
expect(expected).toMatchInlineSnapshot(`
|
202
202
|
[
|
203
|
-
{ id: 0, parentId: -1, mutation: "createTodo", args: { id: "A", text: "buy milk" }, facts: "+todo-exists-A +todo-is-writeable-A=true +todo-completed-A=false" }
|
204
|
-
{ id: 1, parentId: 0, mutation: "createTodo", args: { id: "B", text: "buy bread" }, facts: "+todo-exists-B +todo-is-writeable-B=true +todo-completed-B=false" }
|
205
|
-
{ id: 2, parentId: 1, mutation: "createTodo", args: { id: "C", text: "buy cheese" }, facts: "+todo-exists-C +todo-is-writeable-C=true +todo-completed-C=false" }
|
206
|
-
{ id: 3, parentId: 2, mutation: "
|
207
|
-
{ id: 5, parentId: 3, mutation: "
|
203
|
+
{ id: 0, parentId: -1, mutation: "createTodo", args: { id: "A", text: "buy milk" }, clientId: "client-id", sessionId: "session-id", facts: "+todo-exists-A +todo-is-writeable-A=true +todo-completed-A=false" }
|
204
|
+
{ id: 1, parentId: 0, mutation: "createTodo", args: { id: "B", text: "buy bread" }, clientId: "client-id", sessionId: "session-id", facts: "+todo-exists-B +todo-is-writeable-B=true +todo-completed-B=false" }
|
205
|
+
{ id: 2, parentId: 1, mutation: "createTodo", args: { id: "C", text: "buy cheese" }, clientId: "client-id", sessionId: "session-id", facts: "+todo-exists-C +todo-is-writeable-C=true +todo-completed-C=false" }
|
206
|
+
{ id: 3, parentId: 2, mutation: "todoCompleteds", args: { ids: ["A", "B", "C"] }, clientId: "client-id", sessionId: "session-id", facts: "↖todo-exists-A ↖todo-is-writeable-A=true ↖todo-exists-B ↖todo-is-writeable-B=true ↖todo-exists-C ↖todo-is-writeable-C=true +todo-completed-A=true +todo-completed-B=true +todo-completed-C=true" }
|
207
|
+
{ id: 5, parentId: 3, mutation: "todoCompleted", args: { id: "A" }, clientId: "client-id", sessionId: "session-id", facts: "↖todo-exists-A ↖todo-is-writeable-A=true +todo-completed-A=true" }
|
208
208
|
]
|
209
209
|
`)
|
210
210
|
})
|
211
211
|
|
212
|
-
it('
|
212
|
+
it('todoCompleteds 2', () => {
|
213
213
|
const expected = compact([
|
214
214
|
mutations.createTodo({ id: 'A', text: 'buy milk' }), // 0
|
215
215
|
mutations.createTodo({ id: 'B', text: 'buy bread' }), // 1
|
216
216
|
mutations.createTodo({ id: 'C', text: 'buy cheese' }), // 2
|
217
217
|
mutations.toggleTodo({ id: 'A' }), // 3
|
218
|
-
mutations.
|
218
|
+
mutations.todoCompleteds({ ids: ['A', 'B', 'C'] }), // 4
|
219
219
|
mutations.toggleTodo({ id: 'A' }), // 5
|
220
|
-
mutations.
|
220
|
+
mutations.todoCompleted({ id: 'A' }), // 6
|
221
221
|
])
|
222
222
|
|
223
223
|
expect(expected).toMatchInlineSnapshot(`
|
224
224
|
[
|
225
|
-
{ id: 0, parentId: -1, mutation: "createTodo", args: { id: "A", text: "buy milk" }, facts: "+todo-exists-A +todo-is-writeable-A=true +todo-completed-A=false" }
|
226
|
-
{ id: 1, parentId: 0, mutation: "createTodo", args: { id: "B", text: "buy bread" }, facts: "+todo-exists-B +todo-is-writeable-B=true +todo-completed-B=false" }
|
227
|
-
{ id: 2, parentId: 1, mutation: "createTodo", args: { id: "C", text: "buy cheese" }, facts: "+todo-exists-C +todo-is-writeable-C=true +todo-completed-C=false" }
|
228
|
-
{ id: 4, parentId: 2, mutation: "
|
229
|
-
{ id: 6, parentId: 4, mutation: "
|
225
|
+
{ id: 0, parentId: -1, mutation: "createTodo", args: { id: "A", text: "buy milk" }, clientId: "client-id", sessionId: "session-id", facts: "+todo-exists-A +todo-is-writeable-A=true +todo-completed-A=false" }
|
226
|
+
{ id: 1, parentId: 0, mutation: "createTodo", args: { id: "B", text: "buy bread" }, clientId: "client-id", sessionId: "session-id", facts: "+todo-exists-B +todo-is-writeable-B=true +todo-completed-B=false" }
|
227
|
+
{ id: 2, parentId: 1, mutation: "createTodo", args: { id: "C", text: "buy cheese" }, clientId: "client-id", sessionId: "session-id", facts: "+todo-exists-C +todo-is-writeable-C=true +todo-completed-C=false" }
|
228
|
+
{ id: 4, parentId: 2, mutation: "todoCompleteds", args: { ids: ["A", "B", "C"] }, clientId: "client-id", sessionId: "session-id", facts: "↖todo-exists-A ↖todo-is-writeable-A=true ↖todo-exists-B ↖todo-is-writeable-B=true ↖todo-exists-C ↖todo-is-writeable-C=true +todo-completed-A=true +todo-completed-B=true +todo-completed-C=true" }
|
229
|
+
{ id: 6, parentId: 4, mutation: "todoCompleted", args: { id: "A" }, clientId: "client-id", sessionId: "session-id", facts: "↖todo-exists-A ↖todo-is-writeable-A=true +todo-completed-A=true" }
|
230
230
|
]
|
231
231
|
`)
|
232
232
|
})
|
@@ -42,8 +42,8 @@ export const mutations = {
|
|
42
42
|
: { modify: { set: [facts.todoExists(id), facts.todoIsWriteable(id, true), facts.todoTextUpdated(id)] } },
|
43
43
|
},
|
44
44
|
),
|
45
|
-
|
46
|
-
'
|
45
|
+
todoCompleted: defineMutation(
|
46
|
+
'todoCompleted',
|
47
47
|
Schema.Struct({ id: Schema.String }),
|
48
48
|
// consider `RETURNING` to validate before applying facts
|
49
49
|
'UPDATE todos SET completed = true WHERE id = $id',
|
@@ -58,8 +58,8 @@ export const mutations = {
|
|
58
58
|
}),
|
59
59
|
},
|
60
60
|
),
|
61
|
-
|
62
|
-
'
|
61
|
+
todoUncompleted: defineMutation(
|
62
|
+
'todoUncompleted',
|
63
63
|
Schema.Struct({ id: Schema.String }),
|
64
64
|
'UPDATE todos SET completed = false WHERE id = $id',
|
65
65
|
{
|
@@ -69,8 +69,8 @@ export const mutations = {
|
|
69
69
|
}),
|
70
70
|
},
|
71
71
|
),
|
72
|
-
|
73
|
-
'
|
72
|
+
todoCompleteds: defineMutation(
|
73
|
+
'todoCompleteds',
|
74
74
|
Schema.Struct({ ids: Schema.Array(Schema.String) }),
|
75
75
|
'UPDATE todos SET completed = true WHERE id IN ($ids:csv)',
|
76
76
|
{
|
@@ -124,7 +124,7 @@ export const mutations = {
|
|
124
124
|
Schema.Struct({ id: Schema.String, text: Schema.String }),
|
125
125
|
'UPDATE todos SET text = $text WHERE id = $id',
|
126
126
|
{
|
127
|
-
|
127
|
+
clientOnly: true,
|
128
128
|
facts: ({ id }) => ({ modify: { set: [facts.inputValue(id)] } }),
|
129
129
|
},
|
130
130
|
),
|
@@ -135,6 +135,8 @@ export type PartialEvent = { mutation: string; args: any }
|
|
135
135
|
export const toEventNodes = (
|
136
136
|
partialEvents: PartialEvent[],
|
137
137
|
mutationDefs: Record<string, MutationDef.Any>,
|
138
|
+
clientId: string,
|
139
|
+
sessionId: string | undefined,
|
138
140
|
): HistoryDagNode[] => {
|
139
141
|
const nodesAcc: HistoryDagNode[] = [rootEventNode]
|
140
142
|
|
@@ -142,7 +144,7 @@ export const toEventNodes = (
|
|
142
144
|
|
143
145
|
const eventNodes = partialEvents.map((partialEvent) => {
|
144
146
|
const mutationDef = mutationDefs[partialEvent.mutation]!
|
145
|
-
const eventId = EventId.nextPair(currentEventId, mutationDef.options.
|
147
|
+
const eventId = EventId.nextPair(currentEventId, mutationDef.options.clientOnly).id
|
146
148
|
currentEventId = eventId
|
147
149
|
|
148
150
|
const factsSnapshot = factsSnapshotForDag(historyDagFromNodes(nodesAcc, { skipFactsCheck: true }), undefined)
|
@@ -200,6 +202,8 @@ export const toEventNodes = (
|
|
200
202
|
mutation: partialEvent.mutation,
|
201
203
|
args: partialEvent.args,
|
202
204
|
factsGroup: facts,
|
205
|
+
clientId,
|
206
|
+
sessionId,
|
203
207
|
} satisfies HistoryDagNode
|
204
208
|
nodesAcc.push(node)
|
205
209
|
return node
|
@@ -214,11 +218,11 @@ export const toEventNodes = (
|
|
214
218
|
|
215
219
|
const getParentId = (eventId: EventId.EventId): EventId.EventId => {
|
216
220
|
const globalParentId = eventId.global
|
217
|
-
const
|
221
|
+
const clientParentId = eventId.client - 1
|
218
222
|
|
219
|
-
if (
|
220
|
-
return EventId.make({ global: globalParentId - 1,
|
223
|
+
if (clientParentId < 0) {
|
224
|
+
return EventId.make({ global: globalParentId - 1, client: EventId.clientDefault })
|
221
225
|
}
|
222
226
|
|
223
|
-
return EventId.make({ global: globalParentId,
|
227
|
+
return EventId.make({ global: globalParentId, client: clientParentId })
|
224
228
|
}
|
@@ -18,6 +18,8 @@ class TestEvent extends MutationEvent.EncodedWithMeta {
|
|
18
18
|
mutation: 'a',
|
19
19
|
args: payload,
|
20
20
|
meta: {},
|
21
|
+
clientId: 'static-local-id',
|
22
|
+
sessionId: undefined,
|
21
23
|
})
|
22
24
|
}
|
23
25
|
|
@@ -26,17 +28,17 @@ class TestEvent extends MutationEvent.EncodedWithMeta {
|
|
26
28
|
}
|
27
29
|
|
28
30
|
// Only used for Vitest printing
|
29
|
-
// toJSON = () => `(${this.id.global},${this.id.
|
31
|
+
// toJSON = () => `(${this.id.global},${this.id.client},${this.payload})`
|
30
32
|
// toString = () => this.toJSON()
|
31
33
|
}
|
32
34
|
|
33
|
-
const e_r_1 = new TestEvent({ global: -1,
|
34
|
-
const e_0_0 = new TestEvent({ global: 0,
|
35
|
-
const e_0_1 = new TestEvent({ global: 0,
|
36
|
-
const e_0_2 = new TestEvent({ global: 0,
|
37
|
-
const e_0_3 = new TestEvent({ global: 0,
|
38
|
-
const e_1_0 = new TestEvent({ global: 1,
|
39
|
-
const e_1_1 = new TestEvent({ global: 1,
|
35
|
+
const e_r_1 = new TestEvent({ global: -1, client: 1 }, EventId.ROOT, 'a', true)
|
36
|
+
const e_0_0 = new TestEvent({ global: 0, client: 0 }, EventId.ROOT, 'a', false)
|
37
|
+
const e_0_1 = new TestEvent({ global: 0, client: 1 }, e_0_0.id, 'a', true)
|
38
|
+
const e_0_2 = new TestEvent({ global: 0, client: 2 }, e_0_1.id, 'a', true)
|
39
|
+
const e_0_3 = new TestEvent({ global: 0, client: 3 }, e_0_2.id, 'a', true)
|
40
|
+
const e_1_0 = new TestEvent({ global: 1, client: 0 }, e_0_0.id, 'a', false)
|
41
|
+
const e_1_1 = new TestEvent({ global: 1, client: 1 }, e_1_0.id, 'a', true)
|
40
42
|
|
41
43
|
const isEqualEvent = MutationEvent.isEqualEncoded
|
42
44
|
|
@@ -176,7 +178,7 @@ describe('syncstate', () => {
|
|
176
178
|
)
|
177
179
|
|
178
180
|
describe('upstream-advance: advance', () => {
|
179
|
-
it('should throw error if newEvents are not sorted in ascending order by eventId (
|
181
|
+
it('should throw error if newEvents are not sorted in ascending order by eventId (client)', () => {
|
180
182
|
const syncState = new SyncState.SyncState({
|
181
183
|
pending: [e_0_0],
|
182
184
|
rollbackTail: [],
|
@@ -267,7 +269,7 @@ describe('syncstate', () => {
|
|
267
269
|
expect(result.newEvents).toStrictEqual([e_0_2, e_0_3, e_1_0, e_1_1])
|
268
270
|
})
|
269
271
|
|
270
|
-
it('should ignore
|
272
|
+
it('should ignore client events (incoming is subset of pending)', () => {
|
271
273
|
const syncState = new SyncState.SyncState({
|
272
274
|
pending: [e_r_1, e_0_0],
|
273
275
|
rollbackTail: [],
|
@@ -287,7 +289,7 @@ describe('syncstate', () => {
|
|
287
289
|
expect(result.newEvents).toStrictEqual([])
|
288
290
|
})
|
289
291
|
|
290
|
-
it('should ignore
|
292
|
+
it('should ignore client events (incoming is subset of pending case 2)', () => {
|
291
293
|
const syncState = new SyncState.SyncState({
|
292
294
|
pending: [e_r_1, e_0_0, e_1_0],
|
293
295
|
rollbackTail: [],
|
@@ -307,7 +309,7 @@ describe('syncstate', () => {
|
|
307
309
|
expect(result.newEvents).toStrictEqual([])
|
308
310
|
})
|
309
311
|
|
310
|
-
it('should ignore
|
312
|
+
it('should ignore client events (incoming goes beyond pending)', () => {
|
311
313
|
const syncState = new SyncState.SyncState({
|
312
314
|
pending: [e_r_1, e_0_0, e_0_1],
|
313
315
|
rollbackTail: [],
|
@@ -330,7 +332,7 @@ describe('syncstate', () => {
|
|
330
332
|
})
|
331
333
|
|
332
334
|
describe('upstream-advance: rebase', () => {
|
333
|
-
it('should rebase single
|
335
|
+
it('should rebase single client event to end', () => {
|
334
336
|
const syncState = new SyncState.SyncState({
|
335
337
|
pending: [e_0_0],
|
336
338
|
rollbackTail: [],
|
@@ -351,7 +353,7 @@ describe('syncstate', () => {
|
|
351
353
|
})
|
352
354
|
|
353
355
|
it('should rebase different event with same id (no rollback tail)', () => {
|
354
|
-
const e_0_0_b = new TestEvent({ global: 0,
|
356
|
+
const e_0_0_b = new TestEvent({ global: 0, client: 0 }, EventId.ROOT, '0_0_b', true)
|
355
357
|
const syncState = new SyncState.SyncState({
|
356
358
|
pending: [e_0_0_b],
|
357
359
|
rollbackTail: [],
|
@@ -372,7 +374,7 @@ describe('syncstate', () => {
|
|
372
374
|
})
|
373
375
|
|
374
376
|
it('should rebase different event with same id', () => {
|
375
|
-
const e_1_0_b = new TestEvent({ global: 1,
|
377
|
+
const e_1_0_b = new TestEvent({ global: 1, client: 0 }, e_0_0.id, '1_0_b', false)
|
376
378
|
const syncState = new SyncState.SyncState({
|
377
379
|
pending: [e_1_0_b],
|
378
380
|
rollbackTail: [e_0_0, e_0_1],
|
@@ -391,7 +393,7 @@ describe('syncstate', () => {
|
|
391
393
|
expect(result.newSyncState.localHead).toMatchObject(e_1_0_e_2_0.id)
|
392
394
|
})
|
393
395
|
|
394
|
-
it('should rebase single
|
396
|
+
it('should rebase single client event to end (more incoming events)', () => {
|
395
397
|
const syncState = new SyncState.SyncState({
|
396
398
|
pending: [e_0_0],
|
397
399
|
rollbackTail: [],
|
@@ -435,7 +437,7 @@ describe('syncstate', () => {
|
|
435
437
|
expect(result.newSyncState.localHead).toMatchObject(e_0_1_e_1_1.id)
|
436
438
|
})
|
437
439
|
|
438
|
-
it('should rebase all
|
440
|
+
it('should rebase all client events when incoming chain starts differently', () => {
|
439
441
|
const syncState = new SyncState.SyncState({
|
440
442
|
pending: [e_0_0, e_0_1],
|
441
443
|
rollbackTail: [],
|
package/src/sync/syncstate.ts
CHANGED
@@ -49,8 +49,8 @@ export class SyncState extends Schema.Class<SyncState>('SyncState')({
|
|
49
49
|
return {
|
50
50
|
pending: this.pending.map((e) => e.toJSON()),
|
51
51
|
rollbackTail: this.rollbackTail.map((e) => e.toJSON()),
|
52
|
-
upstreamHead: `(${this.upstreamHead.global},${this.upstreamHead.
|
53
|
-
localHead: `(${this.localHead.global},${this.localHead.
|
52
|
+
upstreamHead: `(${this.upstreamHead.global},${this.upstreamHead.client})`,
|
53
|
+
localHead: `(${this.localHead.global},${this.localHead.client})`,
|
54
54
|
}
|
55
55
|
}
|
56
56
|
}
|
@@ -137,7 +137,7 @@ export const updateSyncState = ({
|
|
137
137
|
)
|
138
138
|
if (rollbackIndex === -1) {
|
139
139
|
return shouldNeverHappen(
|
140
|
-
`Rollback event not found in rollback tail. Rollback until: [${payload.rollbackUntil.global},${payload.rollbackUntil.
|
140
|
+
`Rollback event not found in rollback tail. Rollback until: [${payload.rollbackUntil.global},${payload.rollbackUntil.client}]. Rollback tail: [${syncState.rollbackTail.map((e) => e.toString()).join(', ')}]`,
|
141
141
|
)
|
142
142
|
}
|
143
143
|
|
@@ -200,8 +200,8 @@ export const updateSyncState = ({
|
|
200
200
|
})
|
201
201
|
|
202
202
|
if (divergentPendingIndex === -1) {
|
203
|
-
const pendingEventIds = new Set(syncState.pending.map((e) => `${e.id.global},${e.id.
|
204
|
-
const newEvents = payload.newEvents.filter((e) => !pendingEventIds.has(`${e.id.global},${e.id.
|
203
|
+
const pendingEventIds = new Set(syncState.pending.map((e) => `${e.id.global},${e.id.client}`))
|
204
|
+
const newEvents = payload.newEvents.filter((e) => !pendingEventIds.has(`${e.id.global},${e.id.client}`))
|
205
205
|
|
206
206
|
// In the case where the incoming events are a subset of the pending events,
|
207
207
|
// we need to split the pending events into two groups:
|
@@ -227,7 +227,7 @@ export const updateSyncState = ({
|
|
227
227
|
|
228
228
|
const seenEventIds = new Set<string>()
|
229
229
|
const pendingAndNewEvents = [...pendingMatching, ...payload.newEvents].filter((event) => {
|
230
|
-
const eventIdStr = `${event.id.global},${event.id.
|
230
|
+
const eventIdStr = `${event.id.global},${event.id.client}`
|
231
231
|
if (seenEventIds.has(eventIdStr)) {
|
232
232
|
return false
|
233
233
|
}
|
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.0-dev.
|
5
|
+
export const liveStoreVersion = '0.3.0-dev.14' as const
|
6
6
|
|
7
7
|
/**
|
8
8
|
* This version number is incremented whenever the internal storage format changes in a breaking way.
|
package/tsconfig.json
CHANGED