@livestore/common 0.0.58-dev.0 → 0.0.58-dev.10
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 +48 -6
- package/dist/adapter-types.d.ts.map +1 -1
- package/dist/adapter-types.js +16 -1
- package/dist/adapter-types.js.map +1 -1
- package/dist/bounded-collections.js.map +1 -1
- package/dist/derived-mutations.d.ts +5 -5
- package/dist/derived-mutations.d.ts.map +1 -1
- package/dist/derived-mutations.js +4 -2
- package/dist/derived-mutations.js.map +1 -1
- package/dist/derived-mutations.test.js +1 -0
- package/dist/derived-mutations.test.js.map +1 -1
- package/dist/devtools/devtools-bridge.d.ts +1 -1
- package/dist/devtools/devtools-bridge.d.ts.map +1 -1
- package/dist/devtools/devtools-messages.d.ts +91 -13
- package/dist/devtools/devtools-messages.d.ts.map +1 -1
- package/dist/devtools/devtools-messages.js +13 -4
- package/dist/devtools/devtools-messages.js.map +1 -1
- package/dist/devtools/index.d.ts +1 -0
- package/dist/devtools/index.d.ts.map +1 -1
- package/dist/devtools/index.js +2 -0
- package/dist/devtools/index.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/rehydrate-from-mutationlog.d.ts.map +1 -1
- package/dist/rehydrate-from-mutationlog.js +11 -5
- package/dist/rehydrate-from-mutationlog.js.map +1 -1
- package/dist/schema/index.d.ts +2 -2
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +1 -1
- package/dist/schema/index.js.map +1 -1
- package/dist/schema/mutations.d.ts +137 -17
- package/dist/schema/mutations.d.ts.map +1 -1
- package/dist/schema/mutations.js +42 -16
- 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/system-tables.d.ts +119 -6
- package/dist/schema/system-tables.d.ts.map +1 -1
- package/dist/schema/system-tables.js +22 -9
- package/dist/schema/system-tables.js.map +1 -1
- package/dist/schema/table-def.d.ts +3 -3
- package/dist/schema/table-def.d.ts.map +1 -1
- package/dist/schema/table-def.js +1 -1
- 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 +2 -2
- package/dist/schema-management/migrations.js.map +1 -1
- package/dist/sql-queries/sql-queries.d.ts +10 -3
- package/dist/sql-queries/sql-queries.d.ts.map +1 -1
- package/dist/sql-queries/sql-queries.js +8 -7
- 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/types.d.ts +2 -2
- package/dist/sql-queries/types.d.ts.map +1 -1
- package/dist/sync/next/compact-events.d.ts +15 -0
- package/dist/sync/next/compact-events.d.ts.map +1 -0
- package/dist/sync/next/compact-events.js +176 -0
- package/dist/sync/next/compact-events.js.map +1 -0
- package/dist/sync/next/facts.d.ts +37 -0
- package/dist/sync/next/facts.d.ts.map +1 -0
- package/dist/sync/next/facts.js +156 -0
- package/dist/sync/next/facts.js.map +1 -0
- package/dist/sync/next/graphology.d.ts +8 -0
- package/dist/sync/next/graphology.d.ts.map +1 -0
- package/dist/sync/next/graphology.js +36 -0
- package/dist/sync/next/graphology.js.map +1 -0
- package/dist/sync/next/graphology_.d.ts +3 -0
- package/dist/sync/next/graphology_.d.ts.map +1 -0
- package/dist/sync/next/graphology_.js +3 -0
- package/dist/sync/next/graphology_.js.map +1 -0
- package/dist/sync/next/history-dag.d.ts +30 -0
- package/dist/sync/next/history-dag.d.ts.map +1 -0
- package/dist/sync/next/history-dag.js +69 -0
- package/dist/sync/next/history-dag.js.map +1 -0
- package/dist/sync/next/mod.d.ts +5 -0
- package/dist/sync/next/mod.d.ts.map +1 -0
- package/dist/sync/next/mod.js +5 -0
- package/dist/sync/next/mod.js.map +1 -0
- package/dist/sync/next/rebase-events.d.ts +27 -0
- package/dist/sync/next/rebase-events.d.ts.map +1 -0
- package/dist/sync/next/rebase-events.js +41 -0
- package/dist/sync/next/rebase-events.js.map +1 -0
- package/dist/sync/next/test/compact-events.calculator.test.d.ts +2 -0
- package/dist/sync/next/test/compact-events.calculator.test.d.ts.map +1 -0
- package/dist/sync/next/test/compact-events.calculator.test.js +101 -0
- package/dist/sync/next/test/compact-events.calculator.test.js.map +1 -0
- package/dist/sync/next/test/compact-events.test.d.ts +2 -0
- package/dist/sync/next/test/compact-events.test.d.ts.map +1 -0
- package/dist/sync/next/test/compact-events.test.js +201 -0
- package/dist/sync/next/test/compact-events.test.js.map +1 -0
- package/dist/sync/next/test/mod.d.ts +2 -0
- package/dist/sync/next/test/mod.d.ts.map +1 -0
- package/dist/sync/next/test/mod.js +2 -0
- package/dist/sync/next/test/mod.js.map +1 -0
- package/dist/sync/next/test/mutation-fixtures.d.ts +73 -0
- package/dist/sync/next/test/mutation-fixtures.d.ts.map +1 -0
- package/dist/sync/next/test/mutation-fixtures.js +161 -0
- package/dist/sync/next/test/mutation-fixtures.js.map +1 -0
- package/dist/sync/sync.d.ts +19 -6
- package/dist/sync/sync.d.ts.map +1 -1
- package/dist/sync/sync.js.map +1 -1
- package/dist/version.d.ts +8 -0
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +9 -0
- package/dist/version.js.map +1 -1
- package/package.json +21 -4
- package/src/adapter-types.ts +46 -7
- package/src/bounded-collections.ts +1 -1
- package/src/derived-mutations.test.ts +2 -1
- package/src/derived-mutations.ts +10 -10
- package/src/devtools/devtools-bridge.ts +1 -1
- package/src/devtools/devtools-messages.ts +12 -2
- package/src/devtools/index.ts +2 -0
- package/src/index.ts +6 -0
- package/src/rehydrate-from-mutationlog.ts +16 -7
- package/src/schema/index.ts +4 -3
- package/src/schema/mutations.ts +175 -30
- package/src/schema/schema-helpers.ts +1 -1
- package/src/schema/system-tables.ts +30 -9
- package/src/schema/table-def.ts +3 -3
- package/src/schema-management/migrations.ts +2 -2
- package/src/sql-queries/sql-queries.ts +21 -10
- package/src/sql-queries/sql-query-builder.ts +1 -1
- package/src/sql-queries/types.ts +2 -2
- package/src/sync/next/ambient.d.ts +3 -0
- package/src/sync/next/compact-events.ts +218 -0
- package/src/sync/next/facts.ts +229 -0
- package/src/sync/next/graphology.ts +49 -0
- package/src/sync/next/graphology_.ts +2 -0
- package/src/sync/next/history-dag.ts +109 -0
- package/src/sync/next/mod.ts +4 -0
- package/src/sync/next/rebase-events.ts +97 -0
- package/src/sync/next/test/compact-events.calculator.test.ts +121 -0
- package/src/sync/next/test/compact-events.test.ts +232 -0
- package/src/sync/next/test/mod.ts +1 -0
- package/src/sync/next/test/mutation-fixtures.ts +230 -0
- package/src/sync/sync.ts +30 -6
- package/src/version.ts +10 -0
- package/tsconfig.json +1 -1
@@ -0,0 +1,161 @@
|
|
1
|
+
import { Schema } from '@livestore/utils/effect';
|
2
|
+
import { ROOT_ID } from '../../../adapter-types.js';
|
3
|
+
import { defineFacts, defineMutation } from '../../../schema/mutations.js';
|
4
|
+
import { factsSnapshotForDag, getFactsGroupForMutationArgs } from '../facts.js';
|
5
|
+
import { historyDagFromNodes, rootEventNode } from '../history-dag.js';
|
6
|
+
/** Used for conflict detection and event history compaction */
|
7
|
+
export const facts = defineFacts({
|
8
|
+
todoExists: (id) => `todo-exists-${id}`,
|
9
|
+
todoIsWriteable: (id, writeable) => [`todo-is-writeable-${id}`, writeable],
|
10
|
+
todoCompleted: (id, completed) => [`todo-completed-${id}`, completed],
|
11
|
+
todoTextUpdated: (id) => `todo-text-updated-${id}`,
|
12
|
+
inputValue: (id) => `input-value-${id}`,
|
13
|
+
});
|
14
|
+
export const mutations = {
|
15
|
+
createTodo: defineMutation('createTodo', Schema.Struct({ id: Schema.String, text: Schema.String }), 'INSERT INTO todos (id, text) VALUES ($id, $text)', {
|
16
|
+
facts: ({ id }) => ({
|
17
|
+
modify: {
|
18
|
+
set: [facts.todoExists(id), facts.todoIsWriteable(id, true), facts.todoCompleted(id, false)],
|
19
|
+
},
|
20
|
+
}),
|
21
|
+
}),
|
22
|
+
upsertTodo: defineMutation('upsertTodo', Schema.Struct({ id: Schema.String, text: Schema.optional(Schema.String) }), 'INSERT INTO todos (id, text) VALUES ($id, $text) ON CONFLICT (id) DO UPDATE SET text = $text', {
|
23
|
+
facts: ({ id }, currentFacts) =>
|
24
|
+
// TODO enable an API along the lines of `map.has(key, value)`
|
25
|
+
currentFacts.has(facts.todoExists(id)) && currentFacts.get(facts.todoIsWriteable(id, true)[0]) === false
|
26
|
+
? { require: [facts.todoExists(id), facts.todoIsWriteable(id, true)] }
|
27
|
+
: { modify: { set: [facts.todoExists(id), facts.todoIsWriteable(id, true), facts.todoTextUpdated(id)] } },
|
28
|
+
}),
|
29
|
+
completeTodo: defineMutation('completeTodo', Schema.Struct({ id: Schema.String }),
|
30
|
+
// consider `RETURNING` to validate before applying facts
|
31
|
+
'UPDATE todos SET completed = true WHERE id = $id', {
|
32
|
+
// prewrite assertions from DB
|
33
|
+
// enables more concurrency
|
34
|
+
// turning database inside out
|
35
|
+
// similar to upsert semantics
|
36
|
+
facts: ({ id }) => ({
|
37
|
+
require: [facts.todoExists(id), facts.todoIsWriteable(id, true)],
|
38
|
+
modify: { set: [facts.todoCompleted(id, true)] },
|
39
|
+
}),
|
40
|
+
}),
|
41
|
+
uncompleteTodo: defineMutation('uncompleteTodo', Schema.Struct({ id: Schema.String }), 'UPDATE todos SET completed = false WHERE id = $id', {
|
42
|
+
facts: ({ id }) => ({
|
43
|
+
require: [facts.todoExists(id), facts.todoIsWriteable(id, true)],
|
44
|
+
modify: { set: [facts.todoCompleted(id, false)] },
|
45
|
+
}),
|
46
|
+
}),
|
47
|
+
completeTodos: defineMutation('completeTodos', Schema.Struct({ ids: Schema.Array(Schema.String) }), 'UPDATE todos SET completed = true WHERE id IN ($ids:csv)', {
|
48
|
+
facts: ({ ids }) => ({
|
49
|
+
require: ids.flatMap((id) => [facts.todoExists(id), facts.todoIsWriteable(id, true)]),
|
50
|
+
modify: { set: ids.map((id) => facts.todoCompleted(id, true)) },
|
51
|
+
}),
|
52
|
+
}),
|
53
|
+
toggleTodo: defineMutation('toggleTodo', Schema.Struct({ id: Schema.String }), 'UPDATE todos SET completed = NOT completed WHERE id = $id', {
|
54
|
+
facts: ({ id }, currentFacts) => {
|
55
|
+
const currentIsCompleted = currentFacts.get(facts.todoCompleted(id, true)[0]) === true;
|
56
|
+
return {
|
57
|
+
require: [facts.todoExists(id), facts.todoIsWriteable(id, true)],
|
58
|
+
modify: {
|
59
|
+
// remove: [facts.todoCompleted(id, currentIsCompleted)],
|
60
|
+
set: [facts.todoCompleted(id, !currentIsCompleted)],
|
61
|
+
},
|
62
|
+
};
|
63
|
+
},
|
64
|
+
}),
|
65
|
+
setReadonlyTodo: defineMutation('setReadonlyTodo', Schema.Struct({ id: Schema.String, readonly: Schema.Boolean }), 'UPDATE todos SET readonly = $readonly WHERE id = $id', {
|
66
|
+
facts: ({ id, readonly }) => ({
|
67
|
+
require: [facts.todoExists(id)],
|
68
|
+
modify: { set: [facts.todoIsWriteable(id, !readonly)] },
|
69
|
+
}),
|
70
|
+
}),
|
71
|
+
setTextTodo: defineMutation('setTextTodo', Schema.Struct({ id: Schema.String, text: Schema.String }), 'UPDATE todos SET text = $text WHERE id = $id', {
|
72
|
+
facts: ({ id }) => ({
|
73
|
+
require: [facts.todoExists(id), facts.todoIsWriteable(id, true)],
|
74
|
+
modify: { set: [facts.todoTextUpdated(id)] },
|
75
|
+
}),
|
76
|
+
}),
|
77
|
+
setInputValue: defineMutation('setInputValue', Schema.Struct({ id: Schema.String, text: Schema.String }), 'UPDATE todos SET text = $text WHERE id = $id', {
|
78
|
+
localOnly: true,
|
79
|
+
facts: ({ id }) => ({ modify: { set: [facts.inputValue(id)] } }),
|
80
|
+
}),
|
81
|
+
};
|
82
|
+
export const toEventNodes = (partialEvents, mutationDefs) => {
|
83
|
+
const nodesAcc = [rootEventNode];
|
84
|
+
let currentEventId = ROOT_ID;
|
85
|
+
const getNextEventId = (mutationDef) => {
|
86
|
+
if (mutationDef.options.localOnly) {
|
87
|
+
return { global: currentEventId.global, local: currentEventId.local + 1 };
|
88
|
+
}
|
89
|
+
return { global: currentEventId.global + 1, local: 0 };
|
90
|
+
};
|
91
|
+
const eventNodes = partialEvents.map((partialEvent) => {
|
92
|
+
const mutationDef = mutationDefs[partialEvent.mutation];
|
93
|
+
const eventId = getNextEventId(mutationDef);
|
94
|
+
currentEventId = eventId;
|
95
|
+
const factsSnapshot = factsSnapshotForDag(historyDagFromNodes(nodesAcc, { skipFactsCheck: true }), undefined);
|
96
|
+
// console.log('factsSnapshot', eventId, factsSnapshot)
|
97
|
+
// const depRead: MutationEventFactsSnapshot = new Map<string, any>()
|
98
|
+
// const factsSnapshotProxy = new Proxy(factsSnapshot, {
|
99
|
+
// get: (target, prop) => {
|
100
|
+
// if (prop === 'has') {
|
101
|
+
// return (key: string) => {
|
102
|
+
// depRead.set(key, EMPTY_FACT_VALUE)
|
103
|
+
// return target.has(key)
|
104
|
+
// }
|
105
|
+
// } else if (prop === 'get') {
|
106
|
+
// return (key: string) => {
|
107
|
+
// depRead.set(key, EMPTY_FACT_VALUE)
|
108
|
+
// return target.get(key)
|
109
|
+
// }
|
110
|
+
// }
|
111
|
+
// notYetImplemented(`toEventNodes: ${prop.toString()} is not yet implemented`)
|
112
|
+
// },
|
113
|
+
// })
|
114
|
+
// const factsRes = mutationDef.options.facts?.(partialEvent.args, factsSnapshotProxy)
|
115
|
+
// console.log('factsRes', factsRes?.modify, factsRes?.require)
|
116
|
+
// const iterableToMap = (iterable: Iterable<MutationEventFactInput>) => {
|
117
|
+
// const map = new Map()
|
118
|
+
// for (const item of iterable) {
|
119
|
+
// if (typeof item === 'string') {
|
120
|
+
// map.set(item, EMPTY_FACT_VALUE)
|
121
|
+
// } else {
|
122
|
+
// map.set(item[0], item[1])
|
123
|
+
// }
|
124
|
+
// }
|
125
|
+
// return map
|
126
|
+
// }
|
127
|
+
// const facts = {
|
128
|
+
// modifyAdd: factsRes?.modify.add ? iterableToMap(factsRes.modify.add) : new Map(),
|
129
|
+
// modifyRemove: factsRes?.modify.remove ? iterableToMap(factsRes.modify.remove) : new Map(),
|
130
|
+
// depRequire: factsRes?.require ? iterableToMap(factsRes.require) : new Map(),
|
131
|
+
// depRead,
|
132
|
+
// } satisfies MutationEventFactsGroup
|
133
|
+
// applyFactGroup(facts, factsSnapshot)
|
134
|
+
const facts = getFactsGroupForMutationArgs({
|
135
|
+
factsCallback: mutationDef.options.facts,
|
136
|
+
args: partialEvent.args,
|
137
|
+
currentFacts: factsSnapshot,
|
138
|
+
});
|
139
|
+
const node = {
|
140
|
+
id: eventId,
|
141
|
+
parentId: getParentId(eventId),
|
142
|
+
mutation: partialEvent.mutation,
|
143
|
+
args: partialEvent.args,
|
144
|
+
factsGroup: facts,
|
145
|
+
};
|
146
|
+
nodesAcc.push(node);
|
147
|
+
return node;
|
148
|
+
});
|
149
|
+
eventNodes.unshift(rootEventNode);
|
150
|
+
// console.log('eventNodes', eventNodes)
|
151
|
+
return eventNodes;
|
152
|
+
};
|
153
|
+
const getParentId = (eventId) => {
|
154
|
+
const globalParentId = eventId.global;
|
155
|
+
const localParentId = eventId.local - 1;
|
156
|
+
if (localParentId < 0) {
|
157
|
+
return { global: globalParentId - 1, local: 0 };
|
158
|
+
}
|
159
|
+
return { global: globalParentId, local: localParentId };
|
160
|
+
};
|
161
|
+
//# sourceMappingURL=mutation-fixtures.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"mutation-fixtures.js","sourceRoot":"","sources":["../../../../src/sync/next/test/mutation-fixtures.ts"],"names":[],"mappings":"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"}
|
package/dist/sync/sync.d.ts
CHANGED
@@ -1,12 +1,25 @@
|
|
1
|
-
import {
|
1
|
+
import type { Effect, HttpClient, Option, Stream, SubscriptionRef } from '@livestore/utils/effect';
|
2
|
+
import { Schema } from '@livestore/utils/effect';
|
3
|
+
import type { EventId } from '../adapter-types.js';
|
2
4
|
import type { MutationEvent } from '../schema/mutations.js';
|
3
|
-
export
|
4
|
-
|
5
|
-
|
5
|
+
export interface SyncBackendOptionsBase {
|
6
|
+
type: string;
|
7
|
+
[key: string]: Schema.JsonValue;
|
8
|
+
}
|
9
|
+
export type SyncBackend<TSyncMetadata = Schema.JsonValue> = {
|
10
|
+
pull: (args: Option.Option<{
|
11
|
+
cursor: EventId;
|
12
|
+
metadata: Option.Option<TSyncMetadata>;
|
13
|
+
}>, options: {
|
14
|
+
listenForNew: boolean;
|
15
|
+
}) => Stream.Stream<{
|
6
16
|
mutationEventEncoded: MutationEvent.AnyEncoded;
|
17
|
+
metadata: Option.Option<TSyncMetadata>;
|
7
18
|
persisted: boolean;
|
8
|
-
}>;
|
9
|
-
push: (mutationEventEncoded: MutationEvent.AnyEncoded, persisted: boolean) => Effect.Effect<
|
19
|
+
}, IsOfflineError | InvalidPullError, HttpClient.HttpClient>;
|
20
|
+
push: (mutationEventEncoded: MutationEvent.AnyEncoded, persisted: boolean) => Effect.Effect<{
|
21
|
+
metadata: Option.Option<TSyncMetadata>;
|
22
|
+
}, IsOfflineError | InvalidPushError, HttpClient.HttpClient>;
|
10
23
|
isConnected: SubscriptionRef.SubscriptionRef<boolean>;
|
11
24
|
};
|
12
25
|
declare const IsOfflineError_base: Schema.TaggedErrorClass<IsOfflineError, "IsOfflineError", {
|
package/dist/sync/sync.d.ts.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/sync/sync.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
1
|
+
{"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/sync/sync.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAClG,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAEhD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAE3D,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAA;IACZ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC,SAAS,CAAA;CAChC;AAED,MAAM,MAAM,WAAW,CAAC,aAAa,GAAG,MAAM,CAAC,SAAS,IAAI;IAC1D,IAAI,EAAE,CACJ,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC;QAClB,MAAM,EAAE,OAAO,CAAA;QACf,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAA;KACvC,CAAC,EACF,OAAO,EAAE;QAAE,YAAY,EAAE,OAAO,CAAA;KAAE,KAC/B,MAAM,CAAC,MAAM,CAChB;QACE,oBAAoB,EAAE,aAAa,CAAC,UAAU,CAAA;QAC9C,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAA;QACtC,SAAS,EAAE,OAAO,CAAA;KACnB,EACD,cAAc,GAAG,gBAAgB,EACjC,UAAU,CAAC,UAAU,CACtB,CAAA;IAED,IAAI,EAAE,CACJ,oBAAoB,EAAE,aAAa,CAAC,UAAU,EAC9C,SAAS,EAAE,OAAO,KACf,MAAM,CAAC,MAAM,CAChB;QAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAA;KAAE,EAC1C,cAAc,GAAG,gBAAgB,EACjC,UAAU,CAAC,UAAU,CACtB,CAAA;IACD,WAAW,EAAE,eAAe,CAAC,eAAe,CAAC,OAAO,CAAC,CAAA;CACtD,CAAA;;;;AAED,qBAAa,cAAe,SAAQ,mBAA0D;CAAG;;;;;;AACjG,qBAAa,gBAAiB,SAAQ,qBAEpC;CAAG;;;;;;AACL,qBAAa,gBAAiB,SAAQ,qBAEpC;CAAG"}
|
package/dist/sync/sync.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/sync/sync.ts"],"names":[],"mappings":"
|
1
|
+
{"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/sync/sync.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAsChD,MAAM,OAAO,cAAe,SAAQ,MAAM,CAAC,WAAW,EAAkB,CAAC,gBAAgB,EAAE,EAAE,CAAC;CAAG;AACjG,MAAM,OAAO,gBAAiB,SAAQ,MAAM,CAAC,WAAW,EAAoB,CAAC,kBAAkB,EAAE;IAC/F,OAAO,EAAE,MAAM,CAAC,MAAM;CACvB,CAAC;CAAG;AACL,MAAM,OAAO,gBAAiB,SAAQ,MAAM,CAAC,WAAW,EAAoB,CAAC,kBAAkB,EAAE;IAC/F,OAAO,EAAE,MAAM,CAAC,MAAM;CACvB,CAAC;CAAG"}
|
package/dist/version.d.ts
CHANGED
@@ -1,2 +1,10 @@
|
|
1
1
|
export declare const liveStoreVersion: string;
|
2
|
+
/**
|
3
|
+
* This version number is incremented whenever the internal storage format changes in a breaking way.
|
4
|
+
* Whenever this version changes, LiveStore will start with fresh database files. Old database files are not deleted.
|
5
|
+
*
|
6
|
+
* While LiveStore is in alpha, this might happen more frequently.
|
7
|
+
* In the future, LiveStore will provide a migration path for older database files to avoid the impression of data loss.
|
8
|
+
*/
|
9
|
+
export declare const liveStoreStorageFormatVersion = 2;
|
2
10
|
//# sourceMappingURL=version.d.ts.map
|
package/dist/version.d.ts.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"
|
1
|
+
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,gBAAgB,QAAsB,CAAA;AAEnD;;;;;;GAMG;AACH,eAAO,MAAM,6BAA6B,IAAI,CAAA"}
|
package/dist/version.js
CHANGED
@@ -1,3 +1,12 @@
|
|
1
1
|
import packageJson from '../package.json' with { type: 'json' };
|
2
|
+
// import packageJson from '../package.json' assert { type: 'json' }
|
2
3
|
export const liveStoreVersion = packageJson.version;
|
4
|
+
/**
|
5
|
+
* This version number is incremented whenever the internal storage format changes in a breaking way.
|
6
|
+
* Whenever this version changes, LiveStore will start with fresh database files. Old database files are not deleted.
|
7
|
+
*
|
8
|
+
* While LiveStore is in alpha, this might happen more frequently.
|
9
|
+
* In the future, LiveStore will provide a migration path for older database files to avoid the impression of data loss.
|
10
|
+
*/
|
11
|
+
export const liveStoreStorageFormatVersion = 2;
|
3
12
|
//# sourceMappingURL=version.js.map
|
package/dist/version.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,OAAO,WAAW,MAAM,iBAAiB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAA;
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,OAAO,WAAW,MAAM,iBAAiB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAA;AAC/D,oEAAoE;AAEpE,MAAM,CAAC,MAAM,gBAAgB,GAAG,WAAW,CAAC,OAAO,CAAA;AAEnD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC,CAAA"}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@livestore/common",
|
3
|
-
"version": "0.0.58-dev.
|
3
|
+
"version": "0.0.58-dev.10",
|
4
4
|
"type": "module",
|
5
5
|
"exports": {
|
6
6
|
".": {
|
@@ -14,6 +14,14 @@
|
|
14
14
|
"./schema": {
|
15
15
|
"types": "./dist/schema/index.d.ts",
|
16
16
|
"default": "./dist/schema/index.js"
|
17
|
+
},
|
18
|
+
"./sync/next": {
|
19
|
+
"types": "./dist/sync/next/mod.d.ts",
|
20
|
+
"default": "./dist/sync/next/mod.js"
|
21
|
+
},
|
22
|
+
"./sync/next/test": {
|
23
|
+
"types": "./dist/sync/next/test/mod.d.ts",
|
24
|
+
"default": "./dist/sync/next/test/mod.js"
|
17
25
|
}
|
18
26
|
},
|
19
27
|
"types": "./dist/index.d.ts",
|
@@ -24,16 +32,25 @@
|
|
24
32
|
],
|
25
33
|
"sql-queries": [
|
26
34
|
"./dist/sql-queries/index.d.ts"
|
35
|
+
],
|
36
|
+
"sync/next": [
|
37
|
+
"./dist/sync/next/mod.d.ts"
|
38
|
+
],
|
39
|
+
"sync/next/test": [
|
40
|
+
"./dist/sync/next/test/mod.d.ts"
|
27
41
|
]
|
28
42
|
}
|
29
43
|
},
|
30
44
|
"dependencies": {
|
31
45
|
"@opentelemetry/api": "^1.9.0",
|
32
|
-
"
|
33
|
-
"
|
46
|
+
"graphology": "0.26.0-alpha1",
|
47
|
+
"graphology-dag": "0.4.1",
|
48
|
+
"graphology-types": "0.24.7",
|
49
|
+
"@livestore/utils": "0.0.58-dev.10",
|
50
|
+
"@livestore/db-schema": "0.0.58-dev.10"
|
34
51
|
},
|
35
52
|
"devDependencies": {
|
36
|
-
"vitest": "^2.
|
53
|
+
"vitest": "^2.1.4"
|
37
54
|
},
|
38
55
|
"publishConfig": {
|
39
56
|
"access": "public"
|
package/src/adapter-types.ts
CHANGED
@@ -9,9 +9,10 @@ export interface PreparedStatement {
|
|
9
9
|
execute(bindValues: PreparedBindValues | undefined, options?: { onRowsChanged?: (rowsChanged: number) => void }): void
|
10
10
|
select<T>(bindValues: PreparedBindValues | undefined): ReadonlyArray<T>
|
11
11
|
finalize(): void
|
12
|
+
sql: string
|
12
13
|
}
|
13
14
|
|
14
|
-
export type
|
15
|
+
export type ClientSession = {
|
15
16
|
/** SQLite database with synchronous API running in the same thread (usually in-memory) */
|
16
17
|
syncDb: SynchronousDatabase
|
17
18
|
/** The coordinator is responsible for persisting the database, syncing etc */
|
@@ -28,6 +29,7 @@ export type SynchronousDatabase = {
|
|
28
29
|
): void
|
29
30
|
select<T>(queryStr: string, bindValues?: PreparedBindValues | undefined): ReadonlyArray<T>
|
30
31
|
export(): Uint8Array
|
32
|
+
close(): void
|
31
33
|
}
|
32
34
|
|
33
35
|
export type ResetMode = 'all-data' | 'only-app-db'
|
@@ -60,24 +62,62 @@ export type BootStatus = typeof BootStatus.Type
|
|
60
62
|
export type Coordinator = {
|
61
63
|
devtools: {
|
62
64
|
enabled: boolean
|
65
|
+
// TODO incorporate sessionId and rethink appHostId
|
63
66
|
appHostId: string
|
64
67
|
}
|
68
|
+
sessionId: string
|
65
69
|
// TODO is exposing the lock status really needed (or only relevant for web adapter?)
|
66
70
|
lockStatus: SubscriptionRef.SubscriptionRef<LockStatus>
|
67
|
-
syncMutations: Stream.Stream<MutationEvent.
|
71
|
+
syncMutations: Stream.Stream<MutationEvent.Any, UnexpectedError>
|
68
72
|
execute(queryStr: string, bindValues: PreparedBindValues | undefined): Effect.Effect<void, UnexpectedError>
|
69
|
-
mutate(
|
73
|
+
mutate(
|
74
|
+
mutationEventEncoded: MutationEvent.AnyEncoded,
|
75
|
+
options: { persisted: boolean },
|
76
|
+
): Effect.Effect<void, UnexpectedError>
|
77
|
+
/** Can be called synchronously */
|
78
|
+
nextMutationEventIdPair: (opts: { localOnly: boolean }) => Effect.Effect<EventIdPair, UnexpectedError>
|
79
|
+
/** Used to initially get the current mutation event id to use as `parentId` for the next mutation event */
|
80
|
+
getCurrentMutationEventId: Effect.Effect<EventId, UnexpectedError>
|
70
81
|
export: Effect.Effect<Uint8Array | undefined, UnexpectedError>
|
71
82
|
getMutationLogData: Effect.Effect<Uint8Array, UnexpectedError>
|
72
83
|
networkStatus: SubscriptionRef.SubscriptionRef<NetworkStatus>
|
73
84
|
}
|
74
85
|
|
86
|
+
/**
|
87
|
+
* Can be used in queries to refer to the current session id.
|
88
|
+
* Will be replaced with the actual session id at runtime
|
89
|
+
*
|
90
|
+
* Example:
|
91
|
+
* ```ts
|
92
|
+
* const query$ = rowQuery(tables.app, SessionIdSymbol)
|
93
|
+
* ```
|
94
|
+
*/
|
95
|
+
export const SessionIdSymbol = Symbol.for('@livestore/session-id')
|
96
|
+
export type SessionIdSymbol = typeof SessionIdSymbol
|
97
|
+
|
75
98
|
export type LockStatus = 'has-lock' | 'no-lock'
|
76
99
|
|
100
|
+
/**
|
101
|
+
* LiveStore event id value consisting of a globally unique event sequence number
|
102
|
+
* and a local sequence number.
|
103
|
+
*
|
104
|
+
* The local sequence number is only used for localOnly mutations and starts from 0 for each global sequence number.
|
105
|
+
*/
|
106
|
+
export type EventId = { global: number; local: number }
|
107
|
+
|
108
|
+
export const EventId = Schema.Struct({
|
109
|
+
global: Schema.Number,
|
110
|
+
local: Schema.Number,
|
111
|
+
}).annotations({ title: 'LiveStore.EventId' })
|
112
|
+
|
113
|
+
export type EventIdPair = { id: EventId; parentId: EventId }
|
114
|
+
|
115
|
+
export const ROOT_ID = { global: -1, local: 0 } satisfies EventId
|
116
|
+
|
77
117
|
export type BootDb = {
|
78
118
|
_tag: 'BootDb'
|
79
119
|
execute(queryStr: string, bindValues?: PreparedBindValues): void
|
80
|
-
mutate: <const TMutationArg extends ReadonlyArray<MutationEvent.
|
120
|
+
mutate: <const TMutationArg extends ReadonlyArray<MutationEvent.PartialAny>>(...list: TMutationArg) => void
|
81
121
|
select<T>(queryStr: string, bindValues?: PreparedBindValues): ReadonlyArray<T>
|
82
122
|
txn(callback: () => void): void
|
83
123
|
}
|
@@ -89,7 +129,6 @@ export class UnexpectedError extends Schema.TaggedError<UnexpectedError>()('Live
|
|
89
129
|
}) {
|
90
130
|
static mapToUnexpectedError = <A, E, R>(effect: Effect.Effect<A, E, R>) =>
|
91
131
|
effect.pipe(
|
92
|
-
Effect.tapCauseLogPretty,
|
93
132
|
Effect.mapError((cause) => (Schema.is(UnexpectedError)(cause) ? cause : new UnexpectedError({ cause }))),
|
94
133
|
Effect.catchAllDefect((cause) => new UnexpectedError({ cause })),
|
95
134
|
)
|
@@ -167,11 +206,11 @@ export type ConnectDevtoolsToStore = (
|
|
167
206
|
storeDevtoolsChannel: StoreDevtoolsChannel,
|
168
207
|
) => Effect.Effect<void, UnexpectedError, Scope.Scope>
|
169
208
|
|
170
|
-
export type
|
209
|
+
export type Adapter = (opts: {
|
171
210
|
schema: LiveStoreSchema
|
172
211
|
storeId: string
|
173
212
|
devtoolsEnabled: boolean
|
174
213
|
bootStatusQueue: Queue.Queue<BootStatus>
|
175
214
|
shutdown: (cause: Cause.Cause<any>) => Effect.Effect<void>
|
176
215
|
connectDevtoolsToStore: ConnectDevtoolsToStore
|
177
|
-
}) => Effect.Effect<
|
216
|
+
}) => Effect.Effect<ClientSession, UnexpectedError, Scope.Scope>
|
@@ -16,7 +16,7 @@ export class BoundMap<K, V> {
|
|
16
16
|
this.#map.set(key, value)
|
17
17
|
// console.log(this.#map.size, this.#sizeLimit);
|
18
18
|
if (this.#map.size > this.#sizeLimit) {
|
19
|
-
const firstKey = this.#map.keys().next().value
|
19
|
+
const firstKey = this.#map.keys().next().value as K
|
20
20
|
const deletedValue = this.#map.get(firstKey)!
|
21
21
|
this.#map.delete(firstKey)
|
22
22
|
if (this.onEvict) {
|
@@ -94,7 +94,8 @@ describe('derived mutations', () => {
|
|
94
94
|
})
|
95
95
|
})
|
96
96
|
|
97
|
-
const patchId = (muationEvent: MutationEvent.
|
97
|
+
const patchId = (muationEvent: MutationEvent.PartialAny) => {
|
98
|
+
// TODO use new id paradigm
|
98
99
|
const id = `00000000-0000-0000-0000-000000000000`
|
99
100
|
return { ...muationEvent, id }
|
100
101
|
}
|
package/src/derived-mutations.ts
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
+
import type { SqliteDsl } from '@livestore/db-schema'
|
1
2
|
import type { GetValForKey } from '@livestore/utils'
|
2
3
|
import { ReadonlyRecord, Schema } from '@livestore/utils/effect'
|
3
|
-
import type { SqliteDsl } from 'effect-db-schema'
|
4
4
|
|
5
5
|
import type { MutationEvent } from './schema/mutations.js'
|
6
6
|
import { defineMutation } from './schema/mutations.js'
|
@@ -38,9 +38,9 @@ export const deriveCreateMutationDef = <
|
|
38
38
|
(col) => col.nullable === false && col.default._tag === 'None',
|
39
39
|
)
|
40
40
|
|
41
|
-
const insertSchema = Schema.Struct(ReadonlyRecord.map(requiredColumns, (col) => col.schema))
|
42
|
-
Schema.extend(Schema.partial(Schema.Struct(ReadonlyRecord.map(optionalFields, (col) => col.schema))))
|
43
|
-
|
41
|
+
const insertSchema = Schema.Struct(ReadonlyRecord.map(requiredColumns, (col) => col.schema))
|
42
|
+
.pipe(Schema.extend(Schema.partial(Schema.Struct(ReadonlyRecord.map(optionalFields, (col) => col.schema)))))
|
43
|
+
.annotations({ title: `${tableName}:Insert` })
|
44
44
|
|
45
45
|
return defineMutation(
|
46
46
|
`_Derived_Create_${tableName}`,
|
@@ -76,7 +76,7 @@ export const deriveUpdateMutationDef = <
|
|
76
76
|
Schema.Struct({
|
77
77
|
where: Schema.partial(table.schema),
|
78
78
|
values: Schema.partial(table.schema),
|
79
|
-
}),
|
79
|
+
}).annotations({ title: `${tableName}:Update` }),
|
80
80
|
({ where, values }) => {
|
81
81
|
const [sql, bindValues] = updateRows({
|
82
82
|
tableName: table.sqliteDef.name,
|
@@ -140,8 +140,8 @@ export namespace DerivedMutationHelperFns {
|
|
140
140
|
> = SqliteDsl.AnyIfConstained<
|
141
141
|
TColumns,
|
142
142
|
UseShortcut<TOptions> extends true
|
143
|
-
? (values?: GetValForKey<SqliteDsl.FromColumns.InsertRowDecoded<TColumns>, 'value'>) => MutationEvent.
|
144
|
-
: (values: SqliteDsl.FromColumns.InsertRowDecoded<TColumns>) => MutationEvent.
|
143
|
+
? (values?: GetValForKey<SqliteDsl.FromColumns.InsertRowDecoded<TColumns>, 'value'>) => MutationEvent.PartialAny
|
144
|
+
: (values: SqliteDsl.FromColumns.InsertRowDecoded<TColumns>) => MutationEvent.PartialAny
|
145
145
|
>
|
146
146
|
|
147
147
|
export type UpdateMutationFn<
|
@@ -150,17 +150,17 @@ export namespace DerivedMutationHelperFns {
|
|
150
150
|
> = SqliteDsl.AnyIfConstained<
|
151
151
|
TColumns,
|
152
152
|
UseShortcut<TOptions> extends true
|
153
|
-
? (values: Partial<GetValForKey<SqliteDsl.FromColumns.RowDecoded<TColumns>, 'value'>>) => MutationEvent.
|
153
|
+
? (values: Partial<GetValForKey<SqliteDsl.FromColumns.RowDecoded<TColumns>, 'value'>>) => MutationEvent.PartialAny
|
154
154
|
: (args: {
|
155
155
|
where: Partial<SqliteDsl.FromColumns.RowDecoded<TColumns>>
|
156
156
|
values: Partial<SqliteDsl.FromColumns.RowDecoded<TColumns>>
|
157
|
-
}) => MutationEvent.
|
157
|
+
}) => MutationEvent.PartialAny
|
158
158
|
>
|
159
159
|
|
160
160
|
export type DeleteMutationFn<
|
161
161
|
TColumns extends SqliteDsl.ConstraintColumns,
|
162
162
|
_TOptions extends DbSchema.TableOptions,
|
163
|
-
> = (args: { where: Partial<SqliteDsl.FromColumns.RowDecoded<TColumns>> }) => MutationEvent.
|
163
|
+
> = (args: { where: Partial<SqliteDsl.FromColumns.RowDecoded<TColumns>> }) => MutationEvent.PartialAny
|
164
164
|
|
165
165
|
type UseShortcut<TOptions extends DbSchema.TableOptions> = TOptions['isSingleColumn'] extends true
|
166
166
|
? TOptions['isSingleton'] extends true
|
@@ -74,7 +74,7 @@ export class MutationBroadcast extends LSDMessage('LSD.MutationBroadcast', {
|
|
74
74
|
}) {}
|
75
75
|
|
76
76
|
export class RunMutationReq extends LSDReqResMessage('LSD.RunMutationReq', {
|
77
|
-
mutationEventEncoded: mutationEventSchemaEncodedAny,
|
77
|
+
mutationEventEncoded: mutationEventSchemaEncodedAny.pipe(Schema.omit('id', 'parentId')),
|
78
78
|
persisted: Schema.Boolean,
|
79
79
|
}) {}
|
80
80
|
|
@@ -158,12 +158,19 @@ export class SyncingInfoRes extends LSDReqResMessage('LSD.SyncingInfoRes', {
|
|
158
158
|
syncingInfo: SyncingInfo,
|
159
159
|
}) {}
|
160
160
|
|
161
|
+
export class SyncHistorySubscribe extends LSDReqResMessage('LSD.SyncHistorySubscribe', {}) {}
|
162
|
+
export class SyncHistoryUnsubscribe extends LSDReqResMessage('LSD.SyncHistoryUnsubscribe', {}) {}
|
163
|
+
export class SyncHistoryRes extends LSDReqResMessage('LSD.SyncHistoryRes', {
|
164
|
+
mutationEventEncoded: mutationEventSchemaEncodedAny,
|
165
|
+
metadata: Schema.Option(Schema.JsonValue),
|
166
|
+
}) {}
|
167
|
+
|
161
168
|
export class DevtoolsReady extends LSDMessage('LSD.DevtoolsReady', {}) {}
|
162
169
|
|
163
170
|
export class DevtoolsConnected extends LSDChannelMessage('LSD.DevtoolsConnected', {}) {}
|
164
171
|
|
165
172
|
export class AppHostReady extends LSDChannelMessage('LSD.AppHostReady', {
|
166
|
-
|
173
|
+
isLeader: Schema.Boolean,
|
167
174
|
}) {}
|
168
175
|
|
169
176
|
export class Disconnect extends LSDChannelMessage('LSD.Disconnect', {}) {}
|
@@ -186,6 +193,8 @@ export const MessageToAppHostCoordinator = Schema.Union(
|
|
186
193
|
RunMutationReq,
|
187
194
|
Ping,
|
188
195
|
DatabaseFileInfoReq,
|
196
|
+
SyncHistorySubscribe,
|
197
|
+
SyncHistoryUnsubscribe,
|
189
198
|
SyncingInfoReq,
|
190
199
|
).annotations({ identifier: 'LSD.MessageToAppHostCoordinator' })
|
191
200
|
|
@@ -219,6 +228,7 @@ export const MessageFromAppHostCoordinator = Schema.Union(
|
|
219
228
|
RunMutationRes,
|
220
229
|
Pong,
|
221
230
|
DatabaseFileInfoRes,
|
231
|
+
SyncHistoryRes,
|
222
232
|
SyncingInfoRes,
|
223
233
|
).annotations({ identifier: 'LSD.MessageFromAppHostCoordinator' })
|
224
234
|
|
package/src/devtools/index.ts
CHANGED
@@ -8,6 +8,7 @@ export * from './devtools-bridge.js'
|
|
8
8
|
export namespace WebBridge {
|
9
9
|
export class AppHostReady extends Schema.TaggedStruct('LSD.WebBridge.AppHostReady', {
|
10
10
|
appHostId: Schema.String,
|
11
|
+
// storeId: Schema.String,
|
11
12
|
isLeader: Schema.Boolean,
|
12
13
|
}) {}
|
13
14
|
|
@@ -24,6 +25,7 @@ export namespace WebBridge {
|
|
24
25
|
*/
|
25
26
|
webBridgeId: Schema.String,
|
26
27
|
isLeader: Schema.Boolean,
|
28
|
+
storeId: Schema.String,
|
27
29
|
}) {}
|
28
30
|
|
29
31
|
export class AppHostWillDisconnect extends Schema.TaggedStruct('LSD.WebBridge.AppHostWillDisconnect', {
|
package/src/index.ts
CHANGED
@@ -3,7 +3,7 @@ import { Chunk, Effect, Option, Schema, Stream } from '@livestore/utils/effect'
|
|
3
3
|
|
4
4
|
import { type MigrationOptionsFromMutationLog, type SynchronousDatabase, UnexpectedError } from './adapter-types.js'
|
5
5
|
import { getExecArgsFromMutation } from './mutation.js'
|
6
|
-
import type { LiveStoreSchema, MutationDef, MutationLogMetaRow } from './schema/index.js'
|
6
|
+
import type { LiveStoreSchema, MutationDef, MutationEvent, MutationLogMetaRow } from './schema/index.js'
|
7
7
|
import { MUTATION_LOG_META_TABLE } from './schema/index.js'
|
8
8
|
import type { PreparedBindValues } from './util.js'
|
9
9
|
import { sql } from './util.js'
|
@@ -54,10 +54,11 @@ This likely means the schema has changed in an incompatible way.
|
|
54
54
|
)
|
55
55
|
|
56
56
|
const mutationEventDecoded = {
|
57
|
-
id: row.
|
57
|
+
id: { global: row.idGlobal, local: row.idLocal },
|
58
|
+
parentId: { global: row.parentIdGlobal, local: row.parentIdLocal },
|
58
59
|
mutation: row.mutation,
|
59
60
|
args: argsDecoded,
|
60
|
-
}
|
61
|
+
} satisfies MutationEvent.Any
|
61
62
|
|
62
63
|
const execArgsArr = getExecArgsFromMutation({ mutationDef, mutationEventDecoded })
|
63
64
|
|
@@ -84,8 +85,8 @@ This likely means the schema has changed in an incompatible way.
|
|
84
85
|
|
85
86
|
const stmt = logDb.prepare(sql`\
|
86
87
|
SELECT * FROM ${MUTATION_LOG_META_TABLE}
|
87
|
-
WHERE
|
88
|
-
ORDER BY
|
88
|
+
WHERE idGlobal > COALESCE($idGlobal, '') AND idLocal > COALESCE($idLocal, '')
|
89
|
+
ORDER BY idGlobal ASC, idLocal ASC
|
89
90
|
LIMIT ${CHUNK_SIZE}
|
90
91
|
`)
|
91
92
|
|
@@ -97,9 +98,17 @@ LIMIT ${CHUNK_SIZE}
|
|
97
98
|
// End stream if no more rows
|
98
99
|
if (Chunk.isChunk(item) && item.length === 0) return Option.none()
|
99
100
|
|
100
|
-
const lastId = Chunk.isChunk(item)
|
101
|
+
const lastId = Chunk.isChunk(item)
|
102
|
+
? Chunk.last(item).pipe(
|
103
|
+
Option.map((_) => ({ global: _.idGlobal, local: _.idLocal })),
|
104
|
+
Option.getOrUndefined,
|
105
|
+
)
|
106
|
+
: undefined
|
101
107
|
const nextItem = Chunk.fromIterable(
|
102
|
-
stmt.select<MutationLogMetaRow>({
|
108
|
+
stmt.select<MutationLogMetaRow>({
|
109
|
+
$idGlobal: lastId?.global,
|
110
|
+
$idLocal: lastId?.local,
|
111
|
+
} as any as PreparedBindValues),
|
103
112
|
)
|
104
113
|
const prevItem = Chunk.isChunk(item) ? item : Chunk.empty()
|
105
114
|
return Option.some([prevItem, nextItem])
|