@welshman/store 0.14.0-pre4 → 0.14.0
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/store/src/{repository.d.ts → derive.d.ts} +33 -41
- package/dist/store/src/derive.d.ts.map +1 -0
- package/dist/store/src/derive.js +706 -0
- package/dist/store/src/derive.js.map +1 -0
- package/dist/store/src/index.d.ts +9 -1
- package/dist/store/src/index.d.ts.map +1 -1
- package/dist/store/src/index.js +9 -1
- package/dist/store/src/index.js.map +1 -1
- package/dist/store/src/misc.d.ts +2 -7
- package/dist/store/src/misc.d.ts.map +1 -1
- package/dist/store/src/misc.js +1 -1
- package/dist/store/src/misc.js.map +1 -1
- package/dist/{net/src/repository.d.ts → store/src/repository/adapters/memory.d.ts} +22 -30
- package/dist/store/src/repository/adapters/memory.d.ts.map +1 -0
- package/dist/{net/src/repository.js → store/src/repository/adapters/memory.js} +96 -106
- package/dist/store/src/repository/adapters/memory.js.map +1 -0
- package/dist/store/src/repository/adapters/sqlite/engine.d.ts +65 -0
- package/dist/store/src/repository/adapters/sqlite/engine.d.ts.map +1 -0
- package/dist/store/src/repository/adapters/sqlite/engine.js +420 -0
- package/dist/store/src/repository/adapters/sqlite/engine.js.map +1 -0
- package/dist/store/src/repository/adapters/sqlite/leader.d.ts +8 -0
- package/dist/store/src/repository/adapters/sqlite/leader.d.ts.map +1 -0
- package/dist/store/src/repository/adapters/sqlite/leader.js +222 -0
- package/dist/store/src/repository/adapters/sqlite/leader.js.map +1 -0
- package/dist/store/src/repository/adapters/sqlite/protocol.d.ts +52 -0
- package/dist/store/src/repository/adapters/sqlite/protocol.d.ts.map +1 -0
- package/dist/store/src/repository/adapters/sqlite/protocol.js +52 -0
- package/dist/store/src/repository/adapters/sqlite/protocol.js.map +1 -0
- package/dist/store/src/repository/adapters/sqlite/repository.d.ts +54 -0
- package/dist/store/src/repository/adapters/sqlite/repository.d.ts.map +1 -0
- package/dist/store/src/repository/adapters/sqlite/repository.js +238 -0
- package/dist/store/src/repository/adapters/sqlite/repository.js.map +1 -0
- package/dist/store/src/repository/adapters/sqlite/serve.d.ts +4 -0
- package/dist/store/src/repository/adapters/sqlite/serve.d.ts.map +1 -0
- package/dist/store/src/repository/adapters/sqlite/serve.js +40 -0
- package/dist/store/src/repository/adapters/sqlite/serve.js.map +1 -0
- package/dist/store/src/repository/adapters/sqlite/wasm.d.ts +7 -0
- package/dist/store/src/repository/adapters/sqlite/wasm.d.ts.map +1 -0
- package/dist/store/src/repository/adapters/sqlite/wasm.js +61 -0
- package/dist/store/src/repository/adapters/sqlite/wasm.js.map +1 -0
- package/dist/store/src/repository/adapters/sqlite/worker.d.ts +2 -0
- package/dist/store/src/repository/adapters/sqlite/worker.d.ts.map +1 -0
- package/dist/store/src/repository/adapters/sqlite/worker.js +4 -0
- package/dist/store/src/repository/adapters/sqlite/worker.js.map +1 -0
- package/dist/store/src/repository/core.d.ts +68 -0
- package/dist/store/src/repository/core.d.ts.map +1 -0
- package/dist/store/src/repository/core.js +123 -0
- package/dist/store/src/repository/core.js.map +1 -0
- package/dist/store/src/svelte.d.ts +22 -0
- package/dist/store/src/svelte.d.ts.map +1 -0
- package/dist/store/src/svelte.js +100 -0
- package/dist/store/src/svelte.js.map +1 -0
- package/dist/store/src/synced.d.ts +1 -1
- package/dist/store/src/synced.d.ts.map +1 -1
- package/dist/store/src/synced.js +1 -1
- package/dist/store/src/synced.js.map +1 -1
- package/dist/store/src/throttle.d.ts +1 -1
- package/dist/store/src/throttle.d.ts.map +1 -1
- package/dist/{net → store}/src/tracker.d.ts +2 -0
- package/dist/store/src/tracker.d.ts.map +1 -0
- package/dist/{net → store}/src/tracker.js +8 -4
- package/dist/store/src/tracker.js.map +1 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/util/src/Command.d.ts +1 -1
- package/dist/util/src/Command.d.ts.map +1 -1
- package/dist/util/src/Command.js +12 -5
- package/dist/util/src/Command.js.map +1 -1
- package/dist/util/src/Events.d.ts +3 -2
- package/dist/util/src/Events.d.ts.map +1 -1
- package/dist/util/src/Events.js.map +1 -1
- package/dist/util/src/Filters.d.ts.map +1 -1
- package/dist/util/src/Filters.js +6 -2
- package/dist/util/src/Filters.js.map +1 -1
- package/dist/util/src/Kinds.d.ts +1 -0
- package/dist/util/src/Kinds.d.ts.map +1 -1
- package/dist/util/src/Kinds.js +1 -0
- package/dist/util/src/Kinds.js.map +1 -1
- package/dist/util/src/RelaySelection.d.ts +5 -0
- package/dist/util/src/RelaySelection.d.ts.map +1 -1
- package/dist/util/src/RelaySelection.js.map +1 -1
- package/dist/util/src/Tags.d.ts +5 -0
- package/dist/util/src/Tags.d.ts.map +1 -1
- package/dist/util/src/Tags.js +3 -0
- package/dist/util/src/Tags.js.map +1 -1
- package/dist/util/src/index.d.ts +1 -0
- package/dist/util/src/index.d.ts.map +1 -1
- package/dist/util/src/index.js +1 -0
- package/dist/util/src/index.js.map +1 -1
- package/package.json +31 -12
- package/dist/net/src/adapter.d.ts +0 -47
- package/dist/net/src/adapter.d.ts.map +0 -1
- package/dist/net/src/adapter.js +0 -139
- package/dist/net/src/adapter.js.map +0 -1
- package/dist/net/src/auth.d.ts +0 -40
- package/dist/net/src/auth.d.ts.map +0 -1
- package/dist/net/src/auth.js +0 -131
- package/dist/net/src/auth.js.map +0 -1
- package/dist/net/src/context.d.ts +0 -10
- package/dist/net/src/context.d.ts.map +0 -1
- package/dist/net/src/context.js +0 -2
- package/dist/net/src/context.js.map +0 -1
- package/dist/net/src/count.d.ts +0 -30
- package/dist/net/src/count.d.ts.map +0 -1
- package/dist/net/src/count.js +0 -97
- package/dist/net/src/count.js.map +0 -1
- package/dist/net/src/diff.d.ts +0 -57
- package/dist/net/src/diff.d.ts.map +0 -1
- package/dist/net/src/diff.js +0 -169
- package/dist/net/src/diff.js.map +0 -1
- package/dist/net/src/index.d.ts +0 -17
- package/dist/net/src/index.d.ts.map +0 -1
- package/dist/net/src/index.js +0 -17
- package/dist/net/src/index.js.map +0 -1
- package/dist/net/src/message.d.ts +0 -106
- package/dist/net/src/message.d.ts.map +0 -1
- package/dist/net/src/message.js +0 -98
- package/dist/net/src/message.js.map +0 -1
- package/dist/net/src/multiplex.d.ts +0 -14
- package/dist/net/src/multiplex.d.ts.map +0 -1
- package/dist/net/src/multiplex.js +0 -219
- package/dist/net/src/multiplex.js.map +0 -1
- package/dist/net/src/negentropy.d.ts +0 -48
- package/dist/net/src/negentropy.d.ts.map +0 -1
- package/dist/net/src/negentropy.js +0 -528
- package/dist/net/src/negentropy.js.map +0 -1
- package/dist/net/src/policy.d.ts +0 -63
- package/dist/net/src/policy.d.ts.map +0 -1
- package/dist/net/src/policy.js +0 -388
- package/dist/net/src/policy.js.map +0 -1
- package/dist/net/src/pool.d.ts +0 -15
- package/dist/net/src/pool.d.ts.map +0 -1
- package/dist/net/src/pool.js +0 -51
- package/dist/net/src/pool.js.map +0 -1
- package/dist/net/src/publish.d.ts +0 -47
- package/dist/net/src/publish.d.ts.map +0 -1
- package/dist/net/src/publish.js +0 -112
- package/dist/net/src/publish.js.map +0 -1
- package/dist/net/src/repository.d.ts.map +0 -1
- package/dist/net/src/repository.js.map +0 -1
- package/dist/net/src/request.d.ts +0 -38
- package/dist/net/src/request.d.ts.map +0 -1
- package/dist/net/src/request.js +0 -220
- package/dist/net/src/request.js.map +0 -1
- package/dist/net/src/socket.d.ts +0 -52
- package/dist/net/src/socket.d.ts.map +0 -1
- package/dist/net/src/socket.js +0 -134
- package/dist/net/src/socket.js.map +0 -1
- package/dist/net/src/tracker.d.ts.map +0 -1
- package/dist/net/src/tracker.js.map +0 -1
- package/dist/net/src/util.d.ts +0 -18
- package/dist/net/src/util.d.ts.map +0 -1
- package/dist/net/src/util.js +0 -25
- package/dist/net/src/util.js.map +0 -1
- package/dist/net/src/wrapManager.d.ts +0 -34
- package/dist/net/src/wrapManager.d.ts.map +0 -1
- package/dist/net/src/wrapManager.js +0 -79
- package/dist/net/src/wrapManager.js.map +0 -1
- package/dist/store/src/repository.d.ts.map +0 -1
- package/dist/store/src/repository.js +0 -580
- package/dist/store/src/repository.js.map +0 -1
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import { noop, randomId } from "@welshman/lib";
|
|
2
|
+
const openChannel = (address) => typeof BroadcastChannel === "undefined"
|
|
3
|
+
? undefined
|
|
4
|
+
: new BroadcastChannel(`welshman-sqlite:${address}`);
|
|
5
|
+
/** Connect to sqlite database `name` through the tab that holds its lock and runs the worker. */
|
|
6
|
+
export const connectSqlite = ({ name, createWorker, }) => {
|
|
7
|
+
const tab = randomId();
|
|
8
|
+
const calls = new Map();
|
|
9
|
+
const listeners = new Set();
|
|
10
|
+
const lock = new AbortController();
|
|
11
|
+
const shared = openChannel(name);
|
|
12
|
+
const inbox = openChannel(`${name}:${tab}`);
|
|
13
|
+
const outboxes = new Map();
|
|
14
|
+
let leading = false;
|
|
15
|
+
let worker;
|
|
16
|
+
let failure;
|
|
17
|
+
let leader;
|
|
18
|
+
let release;
|
|
19
|
+
let closed = false;
|
|
20
|
+
let counter = 0;
|
|
21
|
+
// Which tab asked each call the leader's worker is running
|
|
22
|
+
const askers = new Map();
|
|
23
|
+
// The answers in commit order, and the responses to this tab's calls among them
|
|
24
|
+
const answers = [];
|
|
25
|
+
const responses = new Map();
|
|
26
|
+
const outbox = (to) => {
|
|
27
|
+
let channel = outboxes.get(to);
|
|
28
|
+
if (!channel) {
|
|
29
|
+
channel = openChannel(`${name}:${to}`);
|
|
30
|
+
if (channel) {
|
|
31
|
+
outboxes.set(to, channel);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return channel;
|
|
35
|
+
};
|
|
36
|
+
const notify = (change) => {
|
|
37
|
+
for (const listener of listeners) {
|
|
38
|
+
listener(change);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
const settle = (response) => {
|
|
42
|
+
const call = calls.get(response.id);
|
|
43
|
+
responses.delete(response.id);
|
|
44
|
+
if (call) {
|
|
45
|
+
calls.delete(response.id);
|
|
46
|
+
if ("error" in response) {
|
|
47
|
+
call.reject(new Error(response.error));
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
call.resolve(response.result);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
// Hear answers in commit order, a tab's own as its call's answer, waiting for its response
|
|
55
|
+
const drain = () => {
|
|
56
|
+
let waiting = false;
|
|
57
|
+
while (!waiting && answers.length > 0) {
|
|
58
|
+
const { to, id, change } = answers[0];
|
|
59
|
+
const response = responses.get(id);
|
|
60
|
+
if (to !== tab || !calls.has(id)) {
|
|
61
|
+
answers.shift();
|
|
62
|
+
if (to !== tab && change)
|
|
63
|
+
notify(change);
|
|
64
|
+
}
|
|
65
|
+
else if (response) {
|
|
66
|
+
answers.shift();
|
|
67
|
+
settle(response);
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
waiting = true;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
// The asker gets the response to itself, and every tab the answer's place in the order
|
|
75
|
+
const answer = ({ response, change }) => {
|
|
76
|
+
const to = askers.get(response.id);
|
|
77
|
+
askers.delete(response.id);
|
|
78
|
+
if (to === tab) {
|
|
79
|
+
if (change) {
|
|
80
|
+
shared?.postMessage({ type: "answered", to, id: response.id, change });
|
|
81
|
+
}
|
|
82
|
+
settle(response);
|
|
83
|
+
drain();
|
|
84
|
+
}
|
|
85
|
+
else if (to) {
|
|
86
|
+
outbox(to)?.postMessage({ type: "response", response });
|
|
87
|
+
shared?.postMessage({ type: "answered", to, id: response.id, change });
|
|
88
|
+
if (change)
|
|
89
|
+
notify(change);
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
// A worker that failed answers nothing, so its calls and any after get the failure instead
|
|
93
|
+
const fail = (error) => {
|
|
94
|
+
failure = error;
|
|
95
|
+
for (const id of Array.from(askers.keys())) {
|
|
96
|
+
answer({ response: { id, error } });
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
const run = (request, from) => {
|
|
100
|
+
askers.set(request.id, from);
|
|
101
|
+
if (failure) {
|
|
102
|
+
answer({ response: { id: request.id, error: failure } });
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
worker?.postMessage(request);
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
// Until a leader is known, a call waits in `calls` for one to announce itself
|
|
109
|
+
const send = (request) => {
|
|
110
|
+
if (leading) {
|
|
111
|
+
run(request, tab);
|
|
112
|
+
}
|
|
113
|
+
else if (leader) {
|
|
114
|
+
outbox(leader)?.postMessage({ type: "request", from: tab, request });
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
// Calls made before this leader was known, or sent to one that has gone, go to it in order
|
|
118
|
+
const follow = (tabThatLeads) => {
|
|
119
|
+
if (leader !== tabThatLeads) {
|
|
120
|
+
leader = tabThatLeads;
|
|
121
|
+
for (const call of calls.values()) {
|
|
122
|
+
send(call.request);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
const lead = () => {
|
|
127
|
+
leading = true;
|
|
128
|
+
try {
|
|
129
|
+
worker = createWorker();
|
|
130
|
+
worker.onmessage = ({ data }) => answer(data);
|
|
131
|
+
worker.onerror = (event) => fail(event.message || "The sqlite worker failed");
|
|
132
|
+
worker.postMessage({ type: "open", name });
|
|
133
|
+
}
|
|
134
|
+
catch (e) {
|
|
135
|
+
fail(String(e));
|
|
136
|
+
}
|
|
137
|
+
follow(tab);
|
|
138
|
+
shared?.postMessage({ type: "leader", tab });
|
|
139
|
+
};
|
|
140
|
+
if (shared && inbox) {
|
|
141
|
+
shared.onmessage = ({ data }) => {
|
|
142
|
+
switch (data.type) {
|
|
143
|
+
case "leader":
|
|
144
|
+
follow(data.tab);
|
|
145
|
+
break;
|
|
146
|
+
case "ask":
|
|
147
|
+
if (leading) {
|
|
148
|
+
shared.postMessage({ type: "leader", tab });
|
|
149
|
+
}
|
|
150
|
+
break;
|
|
151
|
+
case "answered":
|
|
152
|
+
answers.push(data);
|
|
153
|
+
drain();
|
|
154
|
+
break;
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
inbox.onmessage = ({ data }) => {
|
|
158
|
+
switch (data.type) {
|
|
159
|
+
case "request":
|
|
160
|
+
if (leading) {
|
|
161
|
+
run(data.request, data.from);
|
|
162
|
+
}
|
|
163
|
+
break;
|
|
164
|
+
case "response":
|
|
165
|
+
if (calls.has(data.response.id)) {
|
|
166
|
+
responses.set(data.response.id, data.response);
|
|
167
|
+
drain();
|
|
168
|
+
}
|
|
169
|
+
break;
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
shared.postMessage({ type: "ask" });
|
|
173
|
+
}
|
|
174
|
+
// Hold the lock until the connection or the tab closes, which takes the worker with it
|
|
175
|
+
if (typeof navigator !== "undefined" && navigator.locks) {
|
|
176
|
+
navigator.locks
|
|
177
|
+
.request(`welshman-sqlite:${name}`, { signal: lock.signal }, () => {
|
|
178
|
+
lead();
|
|
179
|
+
return new Promise(resolve => {
|
|
180
|
+
release = resolve;
|
|
181
|
+
});
|
|
182
|
+
})
|
|
183
|
+
.catch(noop);
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
lead();
|
|
187
|
+
}
|
|
188
|
+
const call = ((method, ...args) => new Promise((resolve, reject) => {
|
|
189
|
+
if (closed) {
|
|
190
|
+
reject(new Error("The sqlite connection is closed"));
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
const request = { id: `${tab}:${counter++}`, method, args };
|
|
194
|
+
calls.set(request.id, { request, resolve, reject });
|
|
195
|
+
send(request);
|
|
196
|
+
}
|
|
197
|
+
}));
|
|
198
|
+
const subscribe = (listener) => {
|
|
199
|
+
listeners.add(listener);
|
|
200
|
+
return () => {
|
|
201
|
+
listeners.delete(listener);
|
|
202
|
+
};
|
|
203
|
+
};
|
|
204
|
+
const close = () => {
|
|
205
|
+
closed = true;
|
|
206
|
+
lock.abort();
|
|
207
|
+
release?.();
|
|
208
|
+
worker?.terminate();
|
|
209
|
+
shared?.close();
|
|
210
|
+
inbox?.close();
|
|
211
|
+
outboxes.forEach(channel => channel.close());
|
|
212
|
+
listeners.clear();
|
|
213
|
+
for (const { reject } of calls.values()) {
|
|
214
|
+
reject(new Error("The sqlite connection is closed"));
|
|
215
|
+
}
|
|
216
|
+
calls.clear();
|
|
217
|
+
responses.clear();
|
|
218
|
+
answers.length = 0;
|
|
219
|
+
};
|
|
220
|
+
return { call, subscribe, close };
|
|
221
|
+
};
|
|
222
|
+
//# sourceMappingURL=leader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"leader.js","sourceRoot":"","sources":["../../../../../../src/repository/adapters/sqlite/leader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { Unsubscriber } from "../../../svelte.js";
|
|
2
|
+
import type { SqliteDatabase, SqliteEngine, WriteOp, WriteResult } from "./engine.js";
|
|
3
|
+
/** The engine methods a worker serves, by name, so nothing else on the engine can be called. */
|
|
4
|
+
export declare const SQLITE_ENGINE_METHODS: readonly ["query", "count", "countTags", "getEvent", "getDeletes", "write", "evict", "prune", "clear"];
|
|
5
|
+
export type SqliteMethods = Pick<SqliteEngine, (typeof SQLITE_ENGINE_METHODS)[number]>;
|
|
6
|
+
/** Methods an app serves from the worker alongside the engine's, over the same database. */
|
|
7
|
+
export type SqliteExtension = Record<string, (...args: any[]) => unknown>;
|
|
8
|
+
/** Builds an app's methods after the engine migrates, so its schema can refer to the engine's. */
|
|
9
|
+
export type ExtendSqlite<M extends SqliteExtension> = (db: SqliteDatabase, engine: SqliteEngine) => M;
|
|
10
|
+
/** The engine's methods and an extension's, which can't shadow them. */
|
|
11
|
+
export type SqliteServed<M extends SqliteExtension> = SqliteMethods & Omit<M, keyof SqliteMethods>;
|
|
12
|
+
/** Calls a method wherever the database lives, in the order calls are made. */
|
|
13
|
+
export type SqliteRpc<M extends SqliteExtension = Record<never, never>> = <K extends keyof SqliteServed<M> & string>(method: K, ...args: Parameters<SqliteServed<M>[K]>) => Promise<ReturnType<SqliteServed<M>[K]>>;
|
|
14
|
+
/** A change a call committed to the database's events, which other connections hear about. */
|
|
15
|
+
export type SqliteChange = {
|
|
16
|
+
type: "write";
|
|
17
|
+
ops: WriteOp[];
|
|
18
|
+
result: WriteResult;
|
|
19
|
+
} | {
|
|
20
|
+
type: "clear";
|
|
21
|
+
};
|
|
22
|
+
/** Calls the database in order, and hears other connections' changes in the order committed. */
|
|
23
|
+
export type SqliteConnection<M extends SqliteExtension = Record<never, never>> = {
|
|
24
|
+
call: SqliteRpc<M>;
|
|
25
|
+
subscribe: (listener: (change: SqliteChange) => void) => Unsubscriber;
|
|
26
|
+
close: () => void;
|
|
27
|
+
};
|
|
28
|
+
export type SqliteRequest = {
|
|
29
|
+
id: string;
|
|
30
|
+
method: string;
|
|
31
|
+
args: unknown[];
|
|
32
|
+
};
|
|
33
|
+
export type SqliteResponse = {
|
|
34
|
+
id: string;
|
|
35
|
+
result: unknown;
|
|
36
|
+
} | {
|
|
37
|
+
id: string;
|
|
38
|
+
error: string;
|
|
39
|
+
};
|
|
40
|
+
/** A worker's answer to a request, with the change it committed, if any. */
|
|
41
|
+
export type SqliteReply = {
|
|
42
|
+
response: SqliteResponse;
|
|
43
|
+
change?: SqliteChange;
|
|
44
|
+
};
|
|
45
|
+
/** Sent to a worker first, naming the database it serves. */
|
|
46
|
+
export type SqliteOpen = {
|
|
47
|
+
type: "open";
|
|
48
|
+
name: string;
|
|
49
|
+
};
|
|
50
|
+
/** Migrates the engine, then answers requests for its methods and the extension's. */
|
|
51
|
+
export declare const createSqliteHandler: <M extends SqliteExtension>(engine: SqliteEngine, extend?: ExtendSqlite<M>) => ({ id, method, args }: SqliteRequest) => SqliteReply;
|
|
52
|
+
//# sourceMappingURL=protocol.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../../../../../src/repository/adapters/sqlite/protocol.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,oBAAoB,CAAA;AACpD,OAAO,KAAK,EAAC,cAAc,EAAE,YAAY,EAAE,OAAO,EAAE,WAAW,EAAC,MAAM,aAAa,CAAA;AAEnF,gGAAgG;AAChG,eAAO,MAAM,qBAAqB,wGAUxB,CAAA;AAEV,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC,OAAO,qBAAqB,CAAC,CAAC,MAAM,CAAC,CAAC,CAAA;AAEtF,4FAA4F;AAC5F,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,CAAA;AAEzE,kGAAkG;AAClG,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,eAAe,IAAI,CACpD,EAAE,EAAE,cAAc,EAClB,MAAM,EAAE,YAAY,KACjB,CAAC,CAAA;AAEN,wEAAwE;AACxE,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,eAAe,IAAI,aAAa,GAAG,IAAI,CAAC,CAAC,EAAE,MAAM,aAAa,CAAC,CAAA;AAElG,+EAA+E;AAC/E,MAAM,MAAM,SAAS,CAAC,CAAC,SAAS,eAAe,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,CACxE,CAAC,SAAS,MAAM,YAAY,CAAC,CAAC,CAAC,GAAG,MAAM,EAExC,MAAM,EAAE,CAAC,EACT,GAAG,IAAI,EAAE,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KACpC,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;AAE5C,8FAA8F;AAC9F,MAAM,MAAM,YAAY,GAAG;IAAC,IAAI,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,OAAO,EAAE,CAAC;IAAC,MAAM,EAAE,WAAW,CAAA;CAAC,GAAG;IAAC,IAAI,EAAE,OAAO,CAAA;CAAC,CAAA;AAEjG,gGAAgG;AAChG,MAAM,MAAM,gBAAgB,CAAC,CAAC,SAAS,eAAe,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI;IAC/E,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,CAAA;IAClB,SAAS,EAAE,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,KAAK,YAAY,CAAA;IACrE,KAAK,EAAE,MAAM,IAAI,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,OAAO,EAAE,CAAA;CAChB,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAC,GAAG;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAC,CAAA;AAExF,4EAA4E;AAC5E,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,EAAE,cAAc,CAAA;IACxB,MAAM,CAAC,EAAE,YAAY,CAAA;CACtB,CAAA;AAED,6DAA6D;AAC7D,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAsBD,sFAAsF;AACtF,eAAO,MAAM,mBAAmB,GAAI,CAAC,SAAS,eAAe,EAC3D,QAAQ,YAAY,EACpB,SAAS,YAAY,CAAC,CAAC,CAAC,MAYhB,sBAAoB,aAAa,KAAG,WAgB7C,CAAA"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/** The engine methods a worker serves, by name, so nothing else on the engine can be called. */
|
|
2
|
+
export const SQLITE_ENGINE_METHODS = [
|
|
3
|
+
"query",
|
|
4
|
+
"count",
|
|
5
|
+
"countTags",
|
|
6
|
+
"getEvent",
|
|
7
|
+
"getDeletes",
|
|
8
|
+
"write",
|
|
9
|
+
"evict",
|
|
10
|
+
"prune",
|
|
11
|
+
"clear",
|
|
12
|
+
];
|
|
13
|
+
// The change an engine method commits, if it's one that changes the events
|
|
14
|
+
const getChange = (method, args, result) => {
|
|
15
|
+
let change;
|
|
16
|
+
switch (method) {
|
|
17
|
+
case "write":
|
|
18
|
+
change = { type: "write", ops: args[0], result: result };
|
|
19
|
+
break;
|
|
20
|
+
case "evict":
|
|
21
|
+
case "prune":
|
|
22
|
+
change = { type: "write", ops: [], result: result };
|
|
23
|
+
break;
|
|
24
|
+
case "clear":
|
|
25
|
+
change = { type: "clear" };
|
|
26
|
+
break;
|
|
27
|
+
}
|
|
28
|
+
return change;
|
|
29
|
+
};
|
|
30
|
+
/** Migrates the engine, then answers requests for its methods and the extension's. */
|
|
31
|
+
export const createSqliteHandler = (engine, extend) => {
|
|
32
|
+
engine.migrate();
|
|
33
|
+
const methods = new Map(Object.entries(extend?.(engine.db, engine) ?? {}));
|
|
34
|
+
for (const method of SQLITE_ENGINE_METHODS) {
|
|
35
|
+
methods.set(method, engine[method]);
|
|
36
|
+
}
|
|
37
|
+
return ({ id, method, args }) => {
|
|
38
|
+
const f = methods.get(method);
|
|
39
|
+
let reply;
|
|
40
|
+
try {
|
|
41
|
+
if (!f)
|
|
42
|
+
throw new Error(`Unknown sqlite method ${method}`);
|
|
43
|
+
const result = f(...args);
|
|
44
|
+
reply = { response: { id, result }, change: getChange(method, args, result) };
|
|
45
|
+
}
|
|
46
|
+
catch (e) {
|
|
47
|
+
reply = { response: { id, error: String(e) } };
|
|
48
|
+
}
|
|
49
|
+
return reply;
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
//# sourceMappingURL=protocol.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../../../../../src/repository/adapters/sqlite/protocol.ts"],"names":[],"mappings":"AAIA,gGAAgG;AAChG,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,OAAO;IACP,OAAO;IACP,WAAW;IACX,UAAU;IACV,YAAY;IACZ,OAAO;IACP,OAAO;IACP,OAAO;IACP,OAAO;CACC,CAAA;AAsDV,2EAA2E;AAC3E,MAAM,SAAS,GAAG,CAAC,MAAc,EAAE,IAAe,EAAE,MAAe,EAAE,EAAE;IACrE,IAAI,MAA2B,CAAA;IAE/B,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,OAAO;YACV,MAAM,GAAG,EAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAc,EAAE,MAAM,EAAE,MAAqB,EAAC,CAAA;YAClF,MAAK;QACP,KAAK,OAAO,CAAC;QACb,KAAK,OAAO;YACV,MAAM,GAAG,EAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,MAAM,EAAE,MAAqB,EAAC,CAAA;YAChE,MAAK;QACP,KAAK,OAAO;YACV,MAAM,GAAG,EAAC,IAAI,EAAE,OAAO,EAAC,CAAA;YACxB,MAAK;IACT,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC,CAAA;AAED,sFAAsF;AACtF,MAAM,CAAC,MAAM,mBAAmB,GAAG,CACjC,MAAoB,EACpB,MAAwB,EACxB,EAAE;IACF,MAAM,CAAC,OAAO,EAAE,CAAA;IAEhB,MAAM,OAAO,GAAG,IAAI,GAAG,CACrB,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAClD,CAAA;IAED,KAAK,MAAM,MAAM,IAAI,qBAAqB,EAAE,CAAC;QAC3C,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAoC,CAAC,CAAA;IACxE,CAAC;IAED,OAAO,CAAC,EAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAgB,EAAe,EAAE;QACxD,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;QAC7B,IAAI,KAAkB,CAAA;QAEtB,IAAI,CAAC;YACH,IAAI,CAAC,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,MAAM,EAAE,CAAC,CAAA;YAE1D,MAAM,MAAM,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAA;YAEzB,KAAK,GAAG,EAAC,QAAQ,EAAE,EAAC,EAAE,EAAE,MAAM,EAAC,EAAE,MAAM,EAAE,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,EAAC,CAAA;QAC3E,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,KAAK,GAAG,EAAC,QAAQ,EAAE,EAAC,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,EAAC,EAAC,CAAA;QAC5C,CAAC;QAED,OAAO,KAAK,CAAA;IACd,CAAC,CAAA;AACH,CAAC,CAAA"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Emitter } from "@welshman/lib";
|
|
2
|
+
import type { Deferred } from "@welshman/lib";
|
|
3
|
+
import type { Filter, TrustedEvent } from "@welshman/util";
|
|
4
|
+
import { Tracker } from "../../../tracker.js";
|
|
5
|
+
import { DeleteIndex } from "../../core.js";
|
|
6
|
+
import type { Repository, ObserveOptions, QueryOptions, CountTagsOptions } from "../../core.js";
|
|
7
|
+
import type { Unsubscriber } from "../../../svelte.js";
|
|
8
|
+
import type { SqliteConnection, SqliteExtension, SqliteRpc } from "./protocol.js";
|
|
9
|
+
export type SqliteRepositoryOptions<M extends SqliteExtension = Record<never, never>> = {
|
|
10
|
+
connection: SqliteConnection<M>;
|
|
11
|
+
batchDelay?: number;
|
|
12
|
+
};
|
|
13
|
+
/** A `Repository` over a `SqliteEngine` connection, which is usually to a worker shared by tabs. */
|
|
14
|
+
export declare class SqliteRepository<M extends SqliteExtension = Record<never, never>> extends Emitter implements Repository {
|
|
15
|
+
readonly options: SqliteRepositoryOptions<M>;
|
|
16
|
+
tracker: Tracker;
|
|
17
|
+
deletes: DeleteIndex;
|
|
18
|
+
/** Open a repository once it holds the deletes that `isDeleted` answers from. */
|
|
19
|
+
static open: <M_1 extends SqliteExtension = Record<never, never>>(options: SqliteRepositoryOptions<M_1>) => Promise<SqliteRepository<M_1>>;
|
|
20
|
+
private rpc;
|
|
21
|
+
private writes;
|
|
22
|
+
private timeout;
|
|
23
|
+
private sending;
|
|
24
|
+
private mirroring;
|
|
25
|
+
private unsubscribe;
|
|
26
|
+
private constructor();
|
|
27
|
+
query: (filters: Filter[], { signal, ...options }?: QueryOptions) => Promise<TrustedEvent[]>;
|
|
28
|
+
count: (filters: Filter[], { signal, ...options }?: QueryOptions) => Promise<number>;
|
|
29
|
+
countTags: (name: string, { signal }?: CountTagsOptions) => Promise<Map<string, number>>;
|
|
30
|
+
getEvent: (idOrAddress: string) => Promise<TrustedEvent>;
|
|
31
|
+
isDeleted: (event: TrustedEvent) => boolean;
|
|
32
|
+
observe: (options: ObserveOptions) => Unsubscriber;
|
|
33
|
+
publish: (event: TrustedEvent) => Deferred<boolean, boolean>;
|
|
34
|
+
removeEvent: (idOrAddress: string) => Promise<void>;
|
|
35
|
+
pendingWrites: () => Promise<undefined> | undefined;
|
|
36
|
+
clear: () => Promise<void>;
|
|
37
|
+
/** Drop every event matching `filters`, with nothing restored in its place. */
|
|
38
|
+
evict: (filters: Filter[]) => Promise<void>;
|
|
39
|
+
/** Call a method the worker serves, once the writes waiting to go have gone, so it sees them. */
|
|
40
|
+
call: SqliteRpc<M>;
|
|
41
|
+
/** Send the writes still waiting, then let go of the connection. */
|
|
42
|
+
close: () => Promise<void>;
|
|
43
|
+
private start;
|
|
44
|
+
private read;
|
|
45
|
+
private enqueue;
|
|
46
|
+
private flush;
|
|
47
|
+
private apply;
|
|
48
|
+
private forget;
|
|
49
|
+
private hydrate;
|
|
50
|
+
private mirror;
|
|
51
|
+
private receive;
|
|
52
|
+
private receiveChange;
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=repository.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../../../../../../src/repository/adapters/sqlite/repository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,OAAO,EAAc,MAAM,eAAe,CAAA;AAClD,OAAO,KAAK,EAAC,QAAQ,EAAQ,MAAM,eAAe,CAAA;AAElD,OAAO,KAAK,EAAC,MAAM,EAAE,YAAY,EAAC,MAAM,gBAAgB,CAAA;AACxD,OAAO,EAAC,OAAO,EAAC,MAAM,qBAAqB,CAAA;AAC3C,OAAO,EAAC,WAAW,EAAoB,MAAM,eAAe,CAAA;AAC5D,OAAO,KAAK,EAAC,UAAU,EAAE,cAAc,EAAE,YAAY,EAAE,gBAAgB,EAAC,MAAM,eAAe,CAAA;AAC7F,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,oBAAoB,CAAA;AAEpD,OAAO,KAAK,EAAe,gBAAgB,EAAE,eAAe,EAAE,SAAS,EAAC,MAAM,eAAe,CAAA;AAE7F,MAAM,MAAM,uBAAuB,CAAC,CAAC,SAAS,eAAe,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI;IACtF,UAAU,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAA;IAE/B,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,CAAA;AAiCD,oGAAoG;AACpG,qBAAa,gBAAgB,CAAC,CAAC,SAAS,eAAe,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,CAC5E,SAAQ,OACR,YAAW,UAAU;IAkCD,QAAQ,CAAC,OAAO,EAAE,uBAAuB,CAAC,CAAC,CAAC;IA/BhE,OAAO,UAAgB;IACvB,OAAO,cAAoB;IAE3B,iFAAiF;IACjF,MAAM,CAAC,IAAI,GAAU,GAAC,SAAS,eAAe,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,EACnE,SAAS,uBAAuB,CAAC,GAAC,CAAC,oCAcpC;IAGD,OAAO,CAAC,GAAG,CAAW;IACtB,OAAO,CAAC,MAAM,CAAqC;IACnD,OAAO,CAAC,OAAO,CAAsC;IAErD,OAAO,CAAC,OAAO,CAA2B;IAE1C,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,WAAW,CAAc;IAEjC,OAAO;IAyBP,KAAK,GAAU,SAAS,MAAM,EAAE,EAAE,yBAAsB,YAAiB,6BAIxE;IAED,KAAK,GAAI,SAAS,MAAM,EAAE,EAAE,yBAAsB,YAAiB,qBACL;IAE9D,SAAS,GAAU,MAAM,MAAM,EAAE,aAAU,gBAAqB,kCAI/D;IAED,QAAQ,GAAU,aAAa,MAAM,2BAKpC;IAED,SAAS,GAAI,OAAO,YAAY,aAAkC;IAElE,OAAO,GAAI,SAAS,cAAc,kBAAqC;IAEvE,OAAO,GAAI,OAAO,YAAY,gCACoC;IAElE,WAAW,GAAU,aAAa,MAAM,mBAEvC;IAED,aAAa,uCAIZ;IAED,KAAK,sBAMJ;IAID,+EAA+E;IAC/E,KAAK,GAAU,SAAS,MAAM,EAAE,mBAM/B;IAED,iGAAiG;IACjG,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,CAIjB;IAED,oEAAoE;IACpE,KAAK,sBAOJ;IAID,OAAO,CAAC,KAAK,CAaZ;IAGD,OAAO,CAAC,IAAI,CASX;IAED,OAAO,CAAC,OAAO,CAOd;IAGD,OAAO,CAAC,KAAK,CA+BZ;IAGD,OAAO,CAAC,KAAK,CAsBZ;IAGD,OAAO,CAAC,MAAM,CAIb;IAED,OAAO,CAAC,OAAO,CAId;IAED,OAAO,CAAC,MAAM,CAQb;IAED,OAAO,CAAC,OAAO,CAId;IAGD,OAAO,CAAC,aAAa,CAoBpB;CACF"}
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import { Emitter, defer, noop } from "@welshman/lib";
|
|
2
|
+
import { verifiedSymbol } from "@welshman/util";
|
|
3
|
+
import { Tracker } from "../../../tracker.js";
|
|
4
|
+
import { DeleteIndex, observeRepository } from "../../core.js";
|
|
5
|
+
const onWriteError = (error) => console.error("Failed to write to sqlite", error);
|
|
6
|
+
const parseEvent = ({ json, verified }) => {
|
|
7
|
+
const event = JSON.parse(json);
|
|
8
|
+
if (verified) {
|
|
9
|
+
event[verifiedSymbol] = true;
|
|
10
|
+
}
|
|
11
|
+
return event;
|
|
12
|
+
};
|
|
13
|
+
// The events a write publishes, re-marked verified since one from another tab lost the symbol
|
|
14
|
+
const getPublished = (ops) => {
|
|
15
|
+
const published = new Map();
|
|
16
|
+
for (const op of ops) {
|
|
17
|
+
if (op[0] === "publish") {
|
|
18
|
+
const [, event, verified] = op;
|
|
19
|
+
if (verified) {
|
|
20
|
+
event[verifiedSymbol] = true;
|
|
21
|
+
}
|
|
22
|
+
published.set(event.id, event);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return published;
|
|
26
|
+
};
|
|
27
|
+
/** A `Repository` over a `SqliteEngine` connection, which is usually to a worker shared by tabs. */
|
|
28
|
+
export class SqliteRepository extends Emitter {
|
|
29
|
+
options;
|
|
30
|
+
// Provenance only for the events that have passed through this repository
|
|
31
|
+
tracker = new Tracker();
|
|
32
|
+
deletes = new DeleteIndex();
|
|
33
|
+
/** Open a repository once it holds the deletes that `isDeleted` answers from. */
|
|
34
|
+
static open = async (options) => {
|
|
35
|
+
const repository = new SqliteRepository(options);
|
|
36
|
+
try {
|
|
37
|
+
await repository.start();
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
// Nobody else holds the repository to let go of its connection
|
|
41
|
+
await repository.close();
|
|
42
|
+
throw error;
|
|
43
|
+
}
|
|
44
|
+
return repository;
|
|
45
|
+
};
|
|
46
|
+
// The engine's slice of the connection, which is all the repository itself calls
|
|
47
|
+
rpc;
|
|
48
|
+
writes = [];
|
|
49
|
+
timeout;
|
|
50
|
+
// Writes sent and not yet reported
|
|
51
|
+
sending = new Set();
|
|
52
|
+
// Set while applying another connection's tracking, which that connection already wrote
|
|
53
|
+
mirroring = false;
|
|
54
|
+
unsubscribe;
|
|
55
|
+
constructor(options) {
|
|
56
|
+
super();
|
|
57
|
+
this.options = options;
|
|
58
|
+
this.rpc = options.connection.call;
|
|
59
|
+
this.setMaxListeners(1000);
|
|
60
|
+
// A failed write is logged when it fails, and nothing waits on provenance
|
|
61
|
+
this.tracker.on("add", (id, url) => {
|
|
62
|
+
if (!this.mirroring) {
|
|
63
|
+
this.enqueue(["track", id, url]).catch(noop);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
this.tracker.on("remove", (id, url) => {
|
|
67
|
+
if (!this.mirroring) {
|
|
68
|
+
this.enqueue(["untrack", id, url]).catch(noop);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
this.unsubscribe = options.connection.subscribe(this.receiveChange);
|
|
72
|
+
}
|
|
73
|
+
// Repository
|
|
74
|
+
query = async (filters, { signal, ...options } = {}) => {
|
|
75
|
+
const result = await this.read(signal, () => this.rpc("query", filters, options));
|
|
76
|
+
return this.receive(result);
|
|
77
|
+
};
|
|
78
|
+
count = (filters, { signal, ...options } = {}) => this.read(signal, () => this.rpc("count", filters, options));
|
|
79
|
+
countTags = async (name, { signal } = {}) => {
|
|
80
|
+
const counts = await this.read(signal, () => this.rpc("countTags", name));
|
|
81
|
+
return new Map(counts);
|
|
82
|
+
};
|
|
83
|
+
getEvent = async (idOrAddress) => {
|
|
84
|
+
const result = await this.read(undefined, () => this.rpc("getEvent", idOrAddress));
|
|
85
|
+
const [event] = this.receive(result);
|
|
86
|
+
return event;
|
|
87
|
+
};
|
|
88
|
+
isDeleted = (event) => this.deletes.isDeleted(event);
|
|
89
|
+
observe = (options) => observeRepository(this, options);
|
|
90
|
+
publish = (event) => this.enqueue(["publish", event, event[verifiedSymbol] === true]);
|
|
91
|
+
removeEvent = async (idOrAddress) => {
|
|
92
|
+
await this.enqueue(["remove", idOrAddress]);
|
|
93
|
+
};
|
|
94
|
+
pendingWrites = () => {
|
|
95
|
+
const writes = [...this.sending, ...this.writes.map(([, deferred]) => deferred)];
|
|
96
|
+
return writes.length > 0 ? Promise.allSettled(writes).then(noop) : undefined;
|
|
97
|
+
};
|
|
98
|
+
clear = async () => {
|
|
99
|
+
this.flush();
|
|
100
|
+
await this.rpc("clear");
|
|
101
|
+
this.forget();
|
|
102
|
+
};
|
|
103
|
+
// Beyond Repository
|
|
104
|
+
/** Drop every event matching `filters`, with nothing restored in its place. */
|
|
105
|
+
evict = async (filters) => {
|
|
106
|
+
this.flush();
|
|
107
|
+
const result = await this.rpc("evict", filters);
|
|
108
|
+
this.apply(result, new Map());
|
|
109
|
+
};
|
|
110
|
+
/** Call a method the worker serves, once the writes waiting to go have gone, so it sees them. */
|
|
111
|
+
call = (method, ...args) => {
|
|
112
|
+
this.flush();
|
|
113
|
+
return this.options.connection.call(method, ...args);
|
|
114
|
+
};
|
|
115
|
+
/** Send the writes still waiting, then let go of the connection. */
|
|
116
|
+
close = async () => {
|
|
117
|
+
this.flush();
|
|
118
|
+
await this.pendingWrites();
|
|
119
|
+
this.unsubscribe();
|
|
120
|
+
this.options.connection.close();
|
|
121
|
+
};
|
|
122
|
+
// Utilities
|
|
123
|
+
start = async () => {
|
|
124
|
+
const pruned = await this.rpc("prune");
|
|
125
|
+
this.apply(pruned, new Map());
|
|
126
|
+
const deletes = await this.rpc("getDeletes");
|
|
127
|
+
// Changes that reached the index before this answer are in it already
|
|
128
|
+
this.deletes.clear();
|
|
129
|
+
for (const [key, record] of deletes) {
|
|
130
|
+
this.deletes.add(record, key);
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
// Flush so the read sees prior writes, checking the signal here since it can't reach the worker
|
|
134
|
+
read = async (signal, f) => {
|
|
135
|
+
signal?.throwIfAborted();
|
|
136
|
+
this.flush();
|
|
137
|
+
const result = await f();
|
|
138
|
+
signal?.throwIfAborted();
|
|
139
|
+
return result;
|
|
140
|
+
};
|
|
141
|
+
enqueue = (op) => {
|
|
142
|
+
const deferred = defer();
|
|
143
|
+
this.writes.push([op, deferred]);
|
|
144
|
+
this.timeout ??= setTimeout(this.flush, this.options.batchDelay ?? 10);
|
|
145
|
+
return deferred;
|
|
146
|
+
};
|
|
147
|
+
// Sends whatever writes are waiting, so anything sent after sees them
|
|
148
|
+
flush = () => {
|
|
149
|
+
if (this.timeout) {
|
|
150
|
+
clearTimeout(this.timeout);
|
|
151
|
+
this.timeout = undefined;
|
|
152
|
+
}
|
|
153
|
+
if (this.writes.length > 0) {
|
|
154
|
+
const writes = this.writes.splice(0);
|
|
155
|
+
const ops = writes.map(([op]) => op);
|
|
156
|
+
const published = getPublished(ops);
|
|
157
|
+
const sent = this.rpc("write", ops).then(result => {
|
|
158
|
+
const added = this.apply(result, published);
|
|
159
|
+
for (const [op, deferred] of writes) {
|
|
160
|
+
deferred.resolve(op[0] === "publish" && added.has(op[1].id));
|
|
161
|
+
}
|
|
162
|
+
}, error => {
|
|
163
|
+
onWriteError(error);
|
|
164
|
+
for (const [, deferred] of writes) {
|
|
165
|
+
deferred.reject(error);
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
this.sending.add(sent);
|
|
169
|
+
sent.finally(() => this.sending.delete(sent));
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
// Mirror what a write did to the deletes, and report it to subscribers with its provenance
|
|
173
|
+
apply = (result, published) => {
|
|
174
|
+
for (const change of result.deletes) {
|
|
175
|
+
if (change[0] === "add") {
|
|
176
|
+
this.deletes.add(change[2], change[1]);
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
this.deletes.withdraw(change[1]);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
this.hydrate(result.relays);
|
|
183
|
+
const added = new Set(result.added);
|
|
184
|
+
const events = [
|
|
185
|
+
...result.added.flatMap(id => published.get(id) ?? []),
|
|
186
|
+
...result.restored.map(parseEvent),
|
|
187
|
+
];
|
|
188
|
+
if (events.length > 0 || result.removed.length > 0) {
|
|
189
|
+
this.emit("update", { added: events, removed: new Set(result.removed) });
|
|
190
|
+
}
|
|
191
|
+
return added;
|
|
192
|
+
};
|
|
193
|
+
// Forget what the database no longer holds
|
|
194
|
+
forget = () => {
|
|
195
|
+
this.deletes.clear();
|
|
196
|
+
this.tracker.clear();
|
|
197
|
+
this.emit("clear");
|
|
198
|
+
};
|
|
199
|
+
hydrate = (relays) => {
|
|
200
|
+
for (const [id, urls] of relays) {
|
|
201
|
+
this.tracker.hydrate(id, urls);
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
mirror = (f) => {
|
|
205
|
+
this.mirroring = true;
|
|
206
|
+
try {
|
|
207
|
+
f();
|
|
208
|
+
}
|
|
209
|
+
finally {
|
|
210
|
+
this.mirroring = false;
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
receive = ({ events, relays }) => {
|
|
214
|
+
this.hydrate(relays);
|
|
215
|
+
return events.map(parseEvent);
|
|
216
|
+
};
|
|
217
|
+
// A change committed through another connection, reported here as if it were this one's
|
|
218
|
+
receiveChange = (change) => {
|
|
219
|
+
if (change.type === "clear") {
|
|
220
|
+
this.forget();
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
const { ops, result } = change;
|
|
224
|
+
this.mirror(() => {
|
|
225
|
+
for (const op of ops) {
|
|
226
|
+
if (op[0] === "track") {
|
|
227
|
+
this.tracker.addRelay(op[1], op[2]);
|
|
228
|
+
}
|
|
229
|
+
if (op[0] === "untrack") {
|
|
230
|
+
this.tracker.removeRelay(op[1], op[2]);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
this.apply(result, getPublished(ops));
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
//# sourceMappingURL=repository.js.map
|