@welshman/app 0.12.5 → 0.13.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/app/src/index.d.ts +1 -0
- package/dist/app/src/index.d.ts.map +1 -1
- package/dist/app/src/index.js +1 -0
- package/dist/app/src/index.js.map +1 -1
- package/dist/app/src/plugins/base.d.ts +18 -41
- package/dist/app/src/plugins/base.d.ts.map +1 -1
- package/dist/app/src/plugins/base.js +25 -51
- package/dist/app/src/plugins/base.js.map +1 -1
- package/dist/app/src/plugins/blockedRelayLists.d.ts +1 -1
- package/dist/app/src/plugins/blockedRelayLists.d.ts.map +1 -1
- package/dist/app/src/plugins/blossomServerLists.d.ts +1 -1
- package/dist/app/src/plugins/blossomServerLists.d.ts.map +1 -1
- package/dist/app/src/plugins/events.d.ts +5 -6
- package/dist/app/src/plugins/events.d.ts.map +1 -1
- package/dist/app/src/plugins/events.js +24 -38
- package/dist/app/src/plugins/events.js.map +1 -1
- package/dist/app/src/plugins/feedLists.d.ts +1 -1
- package/dist/app/src/plugins/feedLists.d.ts.map +1 -1
- package/dist/app/src/plugins/feeds.d.ts +1 -1
- package/dist/app/src/plugins/feeds.d.ts.map +1 -1
- package/dist/app/src/plugins/feeds.js +2 -1
- package/dist/app/src/plugins/feeds.js.map +1 -1
- package/dist/app/src/plugins/handles.d.ts +1 -1
- package/dist/app/src/plugins/handles.d.ts.map +1 -1
- package/dist/app/src/plugins/handles.js +2 -2
- package/dist/app/src/plugins/handles.js.map +1 -1
- package/dist/app/src/plugins/logger.d.ts +1 -1
- package/dist/app/src/plugins/logger.d.ts.map +1 -1
- package/dist/app/src/plugins/logger.js +1 -1
- package/dist/app/src/plugins/logger.js.map +1 -1
- package/dist/app/src/plugins/messagingRelayLists.d.ts +1 -1
- package/dist/app/src/plugins/messagingRelayLists.d.ts.map +1 -1
- package/dist/app/src/plugins/notify.d.ts +23 -0
- package/dist/app/src/plugins/notify.d.ts.map +1 -0
- package/dist/app/src/plugins/notify.js +28 -0
- package/dist/app/src/plugins/notify.js.map +1 -0
- package/dist/app/src/plugins/pinboards.d.ts +1 -1
- package/dist/app/src/plugins/pinboards.d.ts.map +1 -1
- package/dist/app/src/plugins/pinboards.js +2 -1
- package/dist/app/src/plugins/pinboards.js.map +1 -1
- package/dist/app/src/plugins/plaintext.d.ts +6 -2
- package/dist/app/src/plugins/plaintext.d.ts.map +1 -1
- package/dist/app/src/plugins/plaintext.js +34 -14
- package/dist/app/src/plugins/plaintext.js.map +1 -1
- package/dist/app/src/plugins/profiles.d.ts +2 -1
- package/dist/app/src/plugins/profiles.d.ts.map +1 -1
- package/dist/app/src/plugins/profiles.js +2 -2
- package/dist/app/src/plugins/profiles.js.map +1 -1
- package/dist/app/src/plugins/publisher.d.ts +9 -5
- package/dist/app/src/plugins/publisher.d.ts.map +1 -1
- package/dist/app/src/plugins/publisher.js +108 -75
- package/dist/app/src/plugins/publisher.js.map +1 -1
- package/dist/app/src/plugins/relayLists.d.ts +1 -1
- package/dist/app/src/plugins/relayLists.d.ts.map +1 -1
- package/dist/app/src/plugins/relayLists.js +1 -1
- package/dist/app/src/plugins/relayLists.js.map +1 -1
- package/dist/app/src/plugins/relayRoles.d.ts +1 -1
- package/dist/app/src/plugins/relayRoles.d.ts.map +1 -1
- package/dist/app/src/plugins/relayRoles.js +1 -1
- package/dist/app/src/plugins/relayRoles.js.map +1 -1
- package/dist/app/src/plugins/relays.d.ts +2 -1
- package/dist/app/src/plugins/relays.d.ts.map +1 -1
- package/dist/app/src/plugins/relays.js.map +1 -1
- package/dist/app/src/plugins/roomLists.d.ts +1 -1
- package/dist/app/src/plugins/roomLists.d.ts.map +1 -1
- package/dist/app/src/plugins/roomLists.js +2 -1
- package/dist/app/src/plugins/roomLists.js.map +1 -1
- package/dist/app/src/plugins/roomPins.d.ts +1 -1
- package/dist/app/src/plugins/roomPins.d.ts.map +1 -1
- package/dist/app/src/plugins/roomPins.js +1 -1
- package/dist/app/src/plugins/roomPins.js.map +1 -1
- package/dist/app/src/plugins/rooms.d.ts +1 -2
- package/dist/app/src/plugins/rooms.d.ts.map +1 -1
- package/dist/app/src/plugins/rooms.js +1 -2
- package/dist/app/src/plugins/rooms.js.map +1 -1
- package/dist/app/src/plugins/searchRelayLists.d.ts +1 -1
- package/dist/app/src/plugins/searchRelayLists.d.ts.map +1 -1
- package/dist/app/src/plugins/topics.d.ts +2 -1
- package/dist/app/src/plugins/topics.d.ts.map +1 -1
- package/dist/app/src/plugins/topics.js +2 -2
- package/dist/app/src/plugins/topics.js.map +1 -1
- package/dist/app/src/plugins/wot.d.ts +1 -1
- package/dist/app/src/plugins/wot.d.ts.map +1 -1
- package/dist/app/src/plugins/wot.js +1 -2
- package/dist/app/src/plugins/wot.js.map +1 -1
- package/dist/app/src/plugins/wraps.d.ts +5 -1
- package/dist/app/src/plugins/wraps.d.ts.map +1 -1
- package/dist/app/src/plugins/wraps.js +6 -10
- package/dist/app/src/plugins/wraps.js.map +1 -1
- package/dist/app/src/plugins/zapGoals.d.ts +1 -1
- package/dist/app/src/plugins/zapGoals.d.ts.map +1 -1
- package/dist/app/src/plugins/zapGoals.js +1 -1
- package/dist/app/src/plugins/zapGoals.js.map +1 -1
- package/dist/app/src/plugins/zappers.d.ts +1 -1
- package/dist/app/src/plugins/zappers.d.ts.map +1 -1
- package/dist/app/src/plugins/zappers.js +2 -2
- package/dist/app/src/plugins/zappers.js.map +1 -1
- package/dist/app/src/policy.d.ts +4 -0
- package/dist/app/src/policy.d.ts.map +1 -1
- package/dist/app/src/policy.js +12 -1
- package/dist/app/src/policy.js.map +1 -1
- package/dist/app/src/user.d.ts +2 -2
- package/dist/app/src/user.d.ts.map +1 -1
- package/dist/app/src/user.js.map +1 -1
- package/dist/domain/src/core/ListWriter.d.ts +6 -6
- package/dist/domain/src/kinds/Bolt12Offer.d.ts.map +1 -1
- package/dist/domain/src/kinds/Bolt12Offer.js +10 -9
- package/dist/domain/src/kinds/Bolt12Offer.js.map +1 -1
- package/dist/domain/src/kinds/Bolt12Zap.d.ts +6 -11
- package/dist/domain/src/kinds/Bolt12Zap.d.ts.map +1 -1
- package/dist/domain/src/kinds/Bolt12Zap.js +77 -105
- package/dist/domain/src/kinds/Bolt12Zap.js.map +1 -1
- package/dist/domain/src/kinds/Bolt12ZapIntent.d.ts +2 -0
- package/dist/domain/src/kinds/Bolt12ZapIntent.d.ts.map +1 -1
- package/dist/domain/src/kinds/Bolt12ZapIntent.js +31 -20
- package/dist/domain/src/kinds/Bolt12ZapIntent.js.map +1 -1
- package/dist/domain/src/other/Relay.d.ts +21 -0
- package/dist/domain/src/other/Relay.d.ts.map +1 -1
- package/dist/domain/src/other/Relay.js +6 -0
- package/dist/domain/src/other/Relay.js.map +1 -1
- package/dist/feeds/src/request.d.ts.map +1 -1
- package/dist/feeds/src/request.js +14 -5
- package/dist/feeds/src/request.js.map +1 -1
- package/dist/lib/src/TaskQueue.d.ts.map +1 -1
- package/dist/lib/src/TaskQueue.js +8 -2
- package/dist/lib/src/TaskQueue.js.map +1 -1
- package/dist/net/src/message.d.ts +4 -0
- package/dist/net/src/message.d.ts.map +1 -1
- package/dist/net/src/message.js +2 -0
- package/dist/net/src/message.js.map +1 -1
- package/dist/net/src/policy.d.ts.map +1 -1
- package/dist/net/src/policy.js +11 -3
- package/dist/net/src/policy.js.map +1 -1
- package/dist/net/src/repository.d.ts +24 -12
- package/dist/net/src/repository.d.ts.map +1 -1
- package/dist/net/src/repository.js +79 -70
- package/dist/net/src/repository.js.map +1 -1
- package/dist/net/src/util.d.ts +2 -1
- package/dist/net/src/util.d.ts.map +1 -1
- package/dist/net/src/util.js +6 -5
- package/dist/net/src/util.js.map +1 -1
- package/dist/net/src/wrapManager.d.ts +0 -2
- package/dist/net/src/wrapManager.d.ts.map +1 -1
- package/dist/net/src/wrapManager.js +8 -23
- package/dist/net/src/wrapManager.js.map +1 -1
- package/dist/signer/src/index.d.ts +1 -0
- package/dist/signer/src/index.d.ts.map +1 -1
- package/dist/signer/src/index.js +1 -0
- package/dist/signer/src/index.js.map +1 -1
- package/dist/signer/src/nip59.d.ts +13 -6
- package/dist/signer/src/nip59.d.ts.map +1 -1
- package/dist/signer/src/nip59.js +38 -19
- package/dist/signer/src/nip59.js.map +1 -1
- package/dist/signer/src/queue.d.ts +21 -0
- package/dist/signer/src/queue.d.ts.map +1 -0
- package/dist/signer/src/queue.js +40 -0
- package/dist/signer/src/queue.js.map +1 -0
- package/dist/signer/src/signers/nip01.d.ts +14 -2
- package/dist/signer/src/signers/nip01.d.ts.map +1 -1
- package/dist/signer/src/signers/nip01.js +6 -2
- package/dist/signer/src/signers/nip01.js.map +1 -1
- package/dist/signer/src/signers/nip07.d.ts +9 -9
- package/dist/signer/src/signers/nip07.d.ts.map +1 -1
- package/dist/signer/src/signers/nip07.js +15 -27
- package/dist/signer/src/signers/nip07.js.map +1 -1
- package/dist/signer/src/signers/nip46.d.ts +7 -3
- package/dist/signer/src/signers/nip46.d.ts.map +1 -1
- package/dist/signer/src/signers/nip46.js +12 -8
- package/dist/signer/src/signers/nip46.js.map +1 -1
- package/dist/signer/src/signers/nip55.d.ts +7 -7
- package/dist/signer/src/signers/nip55.d.ts.map +1 -1
- package/dist/signer/src/signers/nip55.js +33 -40
- package/dist/signer/src/signers/nip55.js.map +1 -1
- package/dist/signer/src/util.d.ts +27 -15
- package/dist/signer/src/util.d.ts.map +1 -1
- package/dist/signer/src/util.js +47 -14
- package/dist/signer/src/util.js.map +1 -1
- package/dist/store/src/misc.d.ts +18 -0
- package/dist/store/src/misc.d.ts.map +1 -1
- package/dist/store/src/misc.js +14 -0
- package/dist/store/src/misc.js.map +1 -1
- package/dist/store/src/repository.d.ts +29 -12
- package/dist/store/src/repository.d.ts.map +1 -1
- package/dist/store/src/repository.js +270 -206
- package/dist/store/src/repository.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/util/src/Bolt12.d.ts.map +1 -1
- package/dist/util/src/Bolt12.js +11 -8
- package/dist/util/src/Bolt12.js.map +1 -1
- package/dist/util/src/Events.d.ts +1 -0
- package/dist/util/src/Events.d.ts.map +1 -1
- package/dist/util/src/Events.js +10 -1
- package/dist/util/src/Events.js.map +1 -1
- package/dist/util/src/Lightning.d.ts +1 -0
- package/dist/util/src/Lightning.d.ts.map +1 -1
- package/dist/util/src/Lightning.js +1 -0
- package/dist/util/src/Lightning.js.map +1 -1
- package/package.json +15 -15
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { readable } from "svelte/store";
|
|
1
|
+
import { derived, readable } from "svelte/store";
|
|
2
2
|
import { on, gt, now, noop, mapPop, LRUCache, call, sortBy, first, } from "@welshman/lib";
|
|
3
3
|
import { matchFilters, getIdFilters, sortEventsAsc, sortEventsDesc, getIdOrAddress, } from "@welshman/util";
|
|
4
|
-
import { deriveDeduplicated } from "./misc.js";
|
|
4
|
+
import { deriveDeduplicated, projection, projectFrom } from "./misc.js";
|
|
5
5
|
export const getEventsById = ({ filters, repository, includeDeleted }) => {
|
|
6
6
|
const eventsById = new Map();
|
|
7
7
|
for (const event of repository.query(filters, { includeDeleted })) {
|
|
@@ -9,38 +9,42 @@ export const getEventsById = ({ filters, repository, includeDeleted }) => {
|
|
|
9
9
|
}
|
|
10
10
|
return eventsById;
|
|
11
11
|
};
|
|
12
|
-
export const deriveEventsById = (
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
if (!includeDeleted) {
|
|
24
|
-
for (const id of removed) {
|
|
25
|
-
if (mapPop(id, eventsById)) {
|
|
12
|
+
export const deriveEventsById = (options) => {
|
|
13
|
+
const { filters, repository, includeDeleted } = options;
|
|
14
|
+
const store = readable(new Map(), set => {
|
|
15
|
+
const eventsById = getEventsById(options);
|
|
16
|
+
set(eventsById);
|
|
17
|
+
return on(repository, "update", ({ added, removed }) => {
|
|
18
|
+
let dirty = false;
|
|
19
|
+
for (const event of added) {
|
|
20
|
+
if (matchFilters(filters, event)) {
|
|
26
21
|
dirty = true;
|
|
22
|
+
eventsById.set(event.id, event);
|
|
27
23
|
}
|
|
28
24
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
25
|
+
if (!includeDeleted) {
|
|
26
|
+
for (const id of removed) {
|
|
27
|
+
if (mapPop(id, eventsById)) {
|
|
28
|
+
dirty = true;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
if (dirty) {
|
|
33
|
+
set(eventsById);
|
|
34
|
+
}
|
|
35
|
+
});
|
|
33
36
|
});
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
export const
|
|
37
|
-
export const
|
|
37
|
+
return projection(store, () => getEventsById(options));
|
|
38
|
+
};
|
|
39
|
+
export const deriveArray = (itemsById) => projectFrom(itemsById, $itemsById => Array.from($itemsById.values()));
|
|
40
|
+
export const deriveEventsAsc = (eventsById) => projectFrom(eventsById, $eventsById => sortEventsAsc($eventsById.values()));
|
|
41
|
+
export const deriveEventsDesc = (eventsById) => projectFrom(eventsById, $eventsById => sortEventsDesc($eventsById.values()));
|
|
38
42
|
export const deriveEvents = (options) => deriveArray(deriveEventsById(options));
|
|
39
43
|
export const makeDeriveEvent = ({ repository, includeDeleted = false, onDerive }) => {
|
|
40
44
|
return (idOrAddress, ...args) => {
|
|
41
45
|
const filters = getIdFilters([idOrAddress]);
|
|
42
46
|
onDerive?.(filters, ...args);
|
|
43
|
-
|
|
47
|
+
const store = readable(undefined, set => {
|
|
44
48
|
let event = first(repository.query(filters, { includeDeleted }));
|
|
45
49
|
set(event);
|
|
46
50
|
return on(repository, "update", ({ added, removed }) => {
|
|
@@ -59,6 +63,7 @@ export const makeDeriveEvent = ({ repository, includeDeleted = false, onDerive }
|
|
|
59
63
|
}
|
|
60
64
|
});
|
|
61
65
|
});
|
|
66
|
+
return projection(store, () => first(repository.query(filters, { includeDeleted })));
|
|
62
67
|
};
|
|
63
68
|
};
|
|
64
69
|
export const getEventsByIdByUrl = ({ filters, tracker, repository, includeDeleted, }) => {
|
|
@@ -75,97 +80,107 @@ export const getEventsByIdByUrl = ({ filters, tracker, repository, includeDelete
|
|
|
75
80
|
}
|
|
76
81
|
return eventsByIdByUrl;
|
|
77
82
|
};
|
|
78
|
-
export const deriveEventsByIdByUrl = (
|
|
79
|
-
const
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
const removeEvent = (url, id) => {
|
|
94
|
-
const eventsById = eventsByIdByUrl.get(url);
|
|
95
|
-
if (eventsById?.has(id)) {
|
|
96
|
-
eventsById.delete(id);
|
|
97
|
-
if (eventsById.size === 0) {
|
|
98
|
-
eventsByIdByUrl.delete(url);
|
|
99
|
-
}
|
|
100
|
-
else {
|
|
101
|
-
// Create a new map so we can detect which key changed
|
|
102
|
-
eventsByIdByUrl.set(url, new Map(eventsById));
|
|
103
|
-
}
|
|
83
|
+
export const deriveEventsByIdByUrl = (options) => {
|
|
84
|
+
const { filters, tracker, repository, includeDeleted } = options;
|
|
85
|
+
const store = readable(new Map(), set => {
|
|
86
|
+
const eventsByIdByUrl = getEventsByIdByUrl(options);
|
|
87
|
+
const addEvent = (url, event) => {
|
|
88
|
+
if (!matchFilters(filters, event))
|
|
89
|
+
return false;
|
|
90
|
+
const eventsById = eventsByIdByUrl.get(url);
|
|
91
|
+
// The repository swaps a changed copy of a held event in under the same id.
|
|
92
|
+
if (eventsById?.get(event.id) === event)
|
|
93
|
+
return false;
|
|
94
|
+
// Create a new map so we can detect which key changed
|
|
95
|
+
const newEventsById = new Map(eventsById);
|
|
96
|
+
newEventsById.set(event.id, event);
|
|
97
|
+
eventsByIdByUrl.set(url, newEventsById);
|
|
104
98
|
return true;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
for (const event of added) {
|
|
113
|
-
for (const url of tracker.getRelays(event.id)) {
|
|
114
|
-
dirty = dirty || addEvent(url, event);
|
|
99
|
+
};
|
|
100
|
+
const removeEvent = (url, id) => {
|
|
101
|
+
const eventsById = eventsByIdByUrl.get(url);
|
|
102
|
+
if (eventsById?.has(id)) {
|
|
103
|
+
eventsById.delete(id);
|
|
104
|
+
if (eventsById.size === 0) {
|
|
105
|
+
eventsByIdByUrl.delete(url);
|
|
115
106
|
}
|
|
107
|
+
else {
|
|
108
|
+
// Create a new map so we can detect which key changed
|
|
109
|
+
eventsByIdByUrl.set(url, new Map(eventsById));
|
|
110
|
+
}
|
|
111
|
+
return true;
|
|
116
112
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
113
|
+
return false;
|
|
114
|
+
};
|
|
115
|
+
set(eventsByIdByUrl);
|
|
116
|
+
const unsubscribers = [
|
|
117
|
+
on(repository, "update", ({ added, removed }) => {
|
|
118
|
+
let dirty = false;
|
|
119
|
+
for (const event of added) {
|
|
120
|
+
for (const url of tracker.getRelays(event.id)) {
|
|
121
|
+
dirty = addEvent(url, event) || dirty;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
if (!includeDeleted) {
|
|
125
|
+
for (const id of removed) {
|
|
126
|
+
for (const url of tracker.getRelays(id)) {
|
|
127
|
+
dirty = removeEvent(url, id) || dirty;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
if (dirty) {
|
|
132
|
+
set(eventsByIdByUrl);
|
|
133
|
+
}
|
|
134
|
+
}),
|
|
135
|
+
on(tracker, "add", (id, url) => {
|
|
136
|
+
const event = repository.getEvent(id);
|
|
137
|
+
if (event && addEvent(url, event)) {
|
|
138
|
+
set(eventsByIdByUrl);
|
|
139
|
+
}
|
|
140
|
+
}),
|
|
141
|
+
on(tracker, "remove", (id, url) => {
|
|
142
|
+
if (removeEvent(url, id)) {
|
|
143
|
+
set(eventsByIdByUrl);
|
|
144
|
+
}
|
|
145
|
+
}),
|
|
146
|
+
on(tracker, "load", () => {
|
|
147
|
+
eventsByIdByUrl.clear();
|
|
148
|
+
for (const event of repository.query(filters, { includeDeleted })) {
|
|
149
|
+
for (const url of tracker.getRelays(event.id)) {
|
|
150
|
+
addEvent(url, event);
|
|
121
151
|
}
|
|
122
152
|
}
|
|
123
|
-
}
|
|
124
|
-
if (dirty) {
|
|
125
|
-
set(eventsByIdByUrl);
|
|
126
|
-
}
|
|
127
|
-
}),
|
|
128
|
-
on(tracker, "add", (id, url) => {
|
|
129
|
-
const event = repository.getEvent(id);
|
|
130
|
-
if (event && addEvent(url, event)) {
|
|
131
153
|
set(eventsByIdByUrl);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
if (removeEvent(url, id)) {
|
|
154
|
+
}),
|
|
155
|
+
on(tracker, "clear", () => {
|
|
156
|
+
eventsByIdByUrl.clear();
|
|
136
157
|
set(eventsByIdByUrl);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
on(tracker, "clear", () => {
|
|
149
|
-
eventsByIdByUrl.clear();
|
|
150
|
-
set(eventsByIdByUrl);
|
|
151
|
-
}),
|
|
152
|
-
];
|
|
153
|
-
return () => unsubscribers.forEach(call);
|
|
154
|
-
});
|
|
158
|
+
}),
|
|
159
|
+
];
|
|
160
|
+
return () => unsubscribers.forEach(call);
|
|
161
|
+
});
|
|
162
|
+
return projection(store, () => getEventsByIdByUrl(options));
|
|
163
|
+
};
|
|
164
|
+
/**
|
|
165
|
+
* The events one relay has been seen to hold, narrowed by the filters. The filters choose the
|
|
166
|
+
* index and the tracker answers provenance per event, so the cost tracks what the caller asked
|
|
167
|
+
* for, and a limit counts only events on the relay.
|
|
168
|
+
*/
|
|
155
169
|
export const getEventsByIdForUrl = ({ url, filters, tracker, repository, includeDeleted, }) => {
|
|
156
|
-
const initialIds = Array.from(tracker.getIds(url));
|
|
157
|
-
const initialFilters = filters.map(filter => ({ ids: initialIds, ...filter }));
|
|
158
170
|
const eventsById = new Map();
|
|
159
|
-
|
|
171
|
+
const where = (event) => tracker.hasRelay(event.id, url);
|
|
172
|
+
for (const event of repository.query(filters, { includeDeleted, where })) {
|
|
160
173
|
eventsById.set(event.id, event);
|
|
161
174
|
}
|
|
162
175
|
return eventsById;
|
|
163
176
|
};
|
|
164
|
-
export const deriveEventsByIdForUrl = (
|
|
165
|
-
|
|
166
|
-
|
|
177
|
+
export const deriveEventsByIdForUrl = (options) => {
|
|
178
|
+
const { url, filters, tracker, repository, includeDeleted } = options;
|
|
179
|
+
const belongs = (event) => tracker.hasRelay(event.id, url) && matchFilters(filters, event);
|
|
180
|
+
let eventsById = getEventsByIdForUrl(options);
|
|
181
|
+
const store = readable(eventsById, set => {
|
|
167
182
|
const reset = () => {
|
|
168
|
-
eventsById = getEventsByIdForUrl(
|
|
183
|
+
eventsById = getEventsByIdForUrl(options);
|
|
169
184
|
set(eventsById);
|
|
170
185
|
};
|
|
171
186
|
reset();
|
|
@@ -173,7 +188,7 @@ export const deriveEventsByIdForUrl = ({ url, filters, tracker, repository, incl
|
|
|
173
188
|
on(repository, "update", ({ added, removed }) => {
|
|
174
189
|
let dirty = false;
|
|
175
190
|
for (const event of added) {
|
|
176
|
-
if (
|
|
191
|
+
if (belongs(event)) {
|
|
177
192
|
eventsById.set(event.id, event);
|
|
178
193
|
dirty = true;
|
|
179
194
|
}
|
|
@@ -193,7 +208,7 @@ export const deriveEventsByIdForUrl = ({ url, filters, tracker, repository, incl
|
|
|
193
208
|
on(tracker, "add", (id, trackedUrl) => {
|
|
194
209
|
if (trackedUrl === url) {
|
|
195
210
|
const event = repository.getEvent(id);
|
|
196
|
-
if (event &&
|
|
211
|
+
if (event && belongs(event)) {
|
|
197
212
|
eventsById.set(id, event);
|
|
198
213
|
set(eventsById);
|
|
199
214
|
}
|
|
@@ -210,50 +225,95 @@ export const deriveEventsByIdForUrl = ({ url, filters, tracker, repository, incl
|
|
|
210
225
|
];
|
|
211
226
|
return () => unsubscribers.forEach(call);
|
|
212
227
|
});
|
|
228
|
+
return projection(store, () => getEventsByIdForUrl(options));
|
|
229
|
+
};
|
|
230
|
+
const asCollection = (store, pending) => {
|
|
231
|
+
const self = projection(store);
|
|
232
|
+
// Subscribing queues the parses, so a key the index lacks is read, drained, and read again
|
|
233
|
+
const read = (key) => self.get().get(key) ?? Promise.all(pending.values()).then(() => self.get().get(key));
|
|
234
|
+
return { ...self, read };
|
|
235
|
+
};
|
|
236
|
+
const onParseError = (error) => console.warn("Failed to build an item from an event", error);
|
|
237
|
+
/**
|
|
238
|
+
* Build `event`'s item and pass it to `commit`, synchronously when the parse needs no IO.
|
|
239
|
+
* An async parse waits in `pending`, and deleting its entry there cancels the commit.
|
|
240
|
+
*/
|
|
241
|
+
const buildItem = (event, eventToItem, pending, commit) => {
|
|
242
|
+
let changed = false;
|
|
243
|
+
try {
|
|
244
|
+
const itemOrPromise = eventToItem(event);
|
|
245
|
+
if (itemOrPromise instanceof Promise) {
|
|
246
|
+
const isPending = () => pending.get(event.id) === parse;
|
|
247
|
+
const parse = itemOrPromise
|
|
248
|
+
.then(item => {
|
|
249
|
+
if (isPending())
|
|
250
|
+
commit(item);
|
|
251
|
+
})
|
|
252
|
+
.catch(onParseError)
|
|
253
|
+
.finally(() => {
|
|
254
|
+
if (isPending())
|
|
255
|
+
pending.delete(event.id);
|
|
256
|
+
});
|
|
257
|
+
pending.set(event.id, parse);
|
|
258
|
+
}
|
|
259
|
+
else {
|
|
260
|
+
changed = Boolean(commit(itemOrPromise));
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
catch (error) {
|
|
264
|
+
onParseError(error);
|
|
265
|
+
}
|
|
266
|
+
return changed;
|
|
213
267
|
};
|
|
214
268
|
export const deriveItemsByKey = ({ getKey, filters, repository, eventToItem, includeDeleted, }) => {
|
|
215
|
-
const
|
|
269
|
+
const pending = new Map();
|
|
216
270
|
const itemsByKey = new Map();
|
|
217
|
-
|
|
218
|
-
const
|
|
219
|
-
|
|
220
|
-
|
|
271
|
+
// The event owning each key, so removing a superseded event leaves its successor's entry
|
|
272
|
+
const ownerByKey = new Map();
|
|
273
|
+
// The key each event contributed, for teardown.
|
|
274
|
+
const keyById = new Map();
|
|
275
|
+
const store = readable(itemsByKey, set => {
|
|
276
|
+
const commit = (id, item) => {
|
|
277
|
+
if (item) {
|
|
278
|
+
const key = getKey(item);
|
|
279
|
+
itemsByKey.set(key, item);
|
|
280
|
+
ownerByKey.set(key, id);
|
|
281
|
+
keyById.set(id, key);
|
|
282
|
+
set(itemsByKey);
|
|
283
|
+
}
|
|
284
|
+
};
|
|
221
285
|
const addEvent = (event) => {
|
|
222
|
-
if (
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
.finally(() => deferred.delete(event.id));
|
|
245
|
-
}
|
|
246
|
-
else {
|
|
247
|
-
commit(itemOrPromise);
|
|
286
|
+
if (!pending.has(event.id) && !keyById.has(event.id)) {
|
|
287
|
+
buildItem(event, eventToItem, pending, item => commit(event.id, item));
|
|
288
|
+
}
|
|
289
|
+
};
|
|
290
|
+
const removeEvent = (id) => {
|
|
291
|
+
const key = mapPop(id, keyById);
|
|
292
|
+
const owns = key !== undefined && ownerByKey.get(key) === id;
|
|
293
|
+
pending.delete(id);
|
|
294
|
+
if (owns) {
|
|
295
|
+
ownerByKey.delete(key);
|
|
296
|
+
itemsByKey.delete(key);
|
|
297
|
+
}
|
|
298
|
+
return owns;
|
|
299
|
+
};
|
|
300
|
+
// The index outlives a subscription, so a subscribe drops what left the repository meanwhile
|
|
301
|
+
const catchUp = () => {
|
|
302
|
+
const events = repository.query(filters, { includeDeleted });
|
|
303
|
+
const ids = new Set(events.map(event => event.id));
|
|
304
|
+
let dirty = false;
|
|
305
|
+
for (const id of Array.from(keyById.keys())) {
|
|
306
|
+
if (!ids.has(id)) {
|
|
307
|
+
dirty = removeEvent(id) || dirty;
|
|
248
308
|
}
|
|
249
309
|
}
|
|
250
|
-
|
|
251
|
-
|
|
310
|
+
if (dirty)
|
|
311
|
+
set(itemsByKey);
|
|
312
|
+
for (const event of events) {
|
|
313
|
+
addEvent(event);
|
|
252
314
|
}
|
|
253
315
|
};
|
|
254
|
-
|
|
255
|
-
addEvent(event);
|
|
256
|
-
}
|
|
316
|
+
catchUp();
|
|
257
317
|
return on(repository, "update", ({ added, removed }) => {
|
|
258
318
|
for (const event of added) {
|
|
259
319
|
if (matchFilters(filters, event)) {
|
|
@@ -263,15 +323,7 @@ export const deriveItemsByKey = ({ getKey, filters, repository, eventToItem, inc
|
|
|
263
323
|
if (!includeDeleted) {
|
|
264
324
|
let dirty = false;
|
|
265
325
|
for (const id of removed) {
|
|
266
|
-
|
|
267
|
-
// Only remove if this id still owns the key — replacing a replaceable event
|
|
268
|
-
// reports the old id as removed in the same update that adds the new one,
|
|
269
|
-
// and the newer event has already taken the key over.
|
|
270
|
-
if (key && idsByKey.get(key) === id) {
|
|
271
|
-
idsByKey.delete(key);
|
|
272
|
-
itemsByKey.delete(key);
|
|
273
|
-
dirty = true;
|
|
274
|
-
}
|
|
326
|
+
dirty = removeEvent(id) || dirty;
|
|
275
327
|
}
|
|
276
328
|
if (dirty) {
|
|
277
329
|
set(itemsByKey);
|
|
@@ -279,6 +331,7 @@ export const deriveItemsByKey = ({ getKey, filters, repository, eventToItem, inc
|
|
|
279
331
|
}
|
|
280
332
|
});
|
|
281
333
|
});
|
|
334
|
+
return asCollection(store, pending);
|
|
282
335
|
};
|
|
283
336
|
/**
|
|
284
337
|
* Like `deriveItemsByKey`, but relay-scoped: an event is keyed once per relay
|
|
@@ -288,14 +341,17 @@ export const deriveItemsByKey = ({ getKey, filters, repository, eventToItem, inc
|
|
|
288
341
|
* on multiple relays.
|
|
289
342
|
*/
|
|
290
343
|
export const deriveItemsByKeyByUrl = ({ getKey, filters, repository, tracker, eventToItem, includeDeleted, revalidateOn, }) => {
|
|
291
|
-
const
|
|
344
|
+
const pending = new Map();
|
|
292
345
|
const itemsByKey = new Map();
|
|
293
|
-
// Which event currently owns each
|
|
294
|
-
// doesn't clobber the entry a newer replaceable event has taken over.
|
|
346
|
+
// Which event currently owns each key, as in `deriveItemsByKey`.
|
|
295
347
|
const ownerByKey = new Map();
|
|
296
|
-
// The
|
|
348
|
+
// The key each event contributed on each relay url, for teardown.
|
|
297
349
|
const keysById = new Map();
|
|
298
|
-
|
|
350
|
+
// What each event parsed to, so a rebuild re-keys it without parsing it again.
|
|
351
|
+
const itemsById = new Map();
|
|
352
|
+
const store = readable(itemsByKey, set => {
|
|
353
|
+
// Held while a catch-up keys its events, so a rebuild emits once rather than per event
|
|
354
|
+
let holding = false;
|
|
299
355
|
const setKey = (key, id, url, item) => {
|
|
300
356
|
itemsByKey.set(key, item);
|
|
301
357
|
ownerByKey.set(key, id);
|
|
@@ -316,49 +372,42 @@ export const deriveItemsByKeyByUrl = ({ getKey, filters, repository, tracker, ev
|
|
|
316
372
|
}
|
|
317
373
|
return false;
|
|
318
374
|
};
|
|
319
|
-
|
|
320
|
-
const
|
|
321
|
-
|
|
322
|
-
if (
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
const key = getKey(item, url);
|
|
330
|
-
if (key !== undefined) {
|
|
331
|
-
setKey(key, event.id, url, item);
|
|
332
|
-
}
|
|
375
|
+
// Keys the item on each tracked relay it lacks a key for, including relays seen mid-parse
|
|
376
|
+
const commit = (id, item) => {
|
|
377
|
+
let keyed = false;
|
|
378
|
+
if (item) {
|
|
379
|
+
itemsById.set(id, item);
|
|
380
|
+
for (const url of tracker.getRelays(id)) {
|
|
381
|
+
const key = keysById.get(id)?.has(url) ? undefined : getKey(item, url);
|
|
382
|
+
if (key !== undefined) {
|
|
383
|
+
setKey(key, id, url, item);
|
|
384
|
+
keyed = true;
|
|
333
385
|
}
|
|
334
|
-
set(itemsByKey);
|
|
335
|
-
}
|
|
336
|
-
};
|
|
337
|
-
try {
|
|
338
|
-
const itemOrPromise = eventToItem(event);
|
|
339
|
-
// Commit synchronously when `eventToItem` doesn't need IO, so items are in
|
|
340
|
-
// place before the initial subscription returns rather than a microtask later
|
|
341
|
-
if (itemOrPromise instanceof Promise) {
|
|
342
|
-
deferred.add(event.id);
|
|
343
|
-
itemOrPromise
|
|
344
|
-
.then(commit)
|
|
345
|
-
.catch(onError)
|
|
346
|
-
.finally(() => deferred.delete(event.id));
|
|
347
|
-
}
|
|
348
|
-
else {
|
|
349
|
-
commit(itemOrPromise);
|
|
350
386
|
}
|
|
387
|
+
// Emit only when some url keyed the item
|
|
388
|
+
if (keyed && !holding)
|
|
389
|
+
set(itemsByKey);
|
|
390
|
+
}
|
|
391
|
+
return keyed;
|
|
392
|
+
};
|
|
393
|
+
const addEvent = (event) => {
|
|
394
|
+
const parsed = itemsById.get(event.id);
|
|
395
|
+
let keyed = false;
|
|
396
|
+
// A rebuild clears the keys and keeps the items, so re-keying needs no parse
|
|
397
|
+
if (parsed) {
|
|
398
|
+
keyed = commit(event.id, parsed);
|
|
351
399
|
}
|
|
352
|
-
|
|
353
|
-
|
|
400
|
+
else if (!pending.has(event.id)) {
|
|
401
|
+
keyed = buildItem(event, eventToItem, pending, item => commit(event.id, item));
|
|
354
402
|
}
|
|
403
|
+
return keyed;
|
|
355
404
|
};
|
|
356
405
|
const removeEvent = (id) => {
|
|
357
406
|
const byUrl = mapPop(id, keysById);
|
|
358
|
-
if (!byUrl)
|
|
359
|
-
return false;
|
|
360
407
|
let dirty = false;
|
|
361
|
-
|
|
408
|
+
pending.delete(id);
|
|
409
|
+
itemsById.delete(id);
|
|
410
|
+
for (const key of byUrl?.values() ?? []) {
|
|
362
411
|
dirty = dropKey(key, id) || dirty;
|
|
363
412
|
}
|
|
364
413
|
return dirty;
|
|
@@ -374,21 +423,37 @@ export const deriveItemsByKeyByUrl = ({ getKey, filters, repository, tracker, ev
|
|
|
374
423
|
}
|
|
375
424
|
return dropKey(key, id);
|
|
376
425
|
};
|
|
377
|
-
const
|
|
426
|
+
const catchUp = (cleared = false) => {
|
|
427
|
+
const events = repository.query(filters, { includeDeleted });
|
|
428
|
+
const ids = new Set(events.map(event => event.id));
|
|
429
|
+
let dirty = cleared;
|
|
430
|
+
for (const id of Array.from(keysById.keys())) {
|
|
431
|
+
if (!ids.has(id)) {
|
|
432
|
+
dirty = removeEvent(id) || dirty;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
holding = true;
|
|
436
|
+
for (const event of events) {
|
|
437
|
+
dirty = addEvent(event) || dirty;
|
|
438
|
+
}
|
|
439
|
+
holding = false;
|
|
440
|
+
if (dirty)
|
|
441
|
+
set(itemsByKey);
|
|
442
|
+
};
|
|
443
|
+
const clear = () => {
|
|
444
|
+
const dirty = itemsByKey.size > 0;
|
|
378
445
|
itemsByKey.clear();
|
|
379
446
|
ownerByKey.clear();
|
|
380
447
|
keysById.clear();
|
|
381
|
-
|
|
382
|
-
addEvent(event, tracker.getRelays(event.id));
|
|
383
|
-
}
|
|
384
|
-
set(itemsByKey);
|
|
448
|
+
return dirty;
|
|
385
449
|
};
|
|
386
|
-
rebuild();
|
|
450
|
+
const rebuild = () => catchUp(clear());
|
|
451
|
+
catchUp();
|
|
387
452
|
const unsubscribers = [
|
|
388
453
|
on(repository, "update", ({ added, removed }) => {
|
|
389
454
|
for (const event of added) {
|
|
390
455
|
if (matchFilters(filters, event)) {
|
|
391
|
-
addEvent(event
|
|
456
|
+
addEvent(event);
|
|
392
457
|
}
|
|
393
458
|
}
|
|
394
459
|
if (!includeDeleted) {
|
|
@@ -403,7 +468,7 @@ export const deriveItemsByKeyByUrl = ({ getKey, filters, repository, tracker, ev
|
|
|
403
468
|
on(tracker, "add", (id, url) => {
|
|
404
469
|
const event = repository.getEvent(id);
|
|
405
470
|
if (event && matchFilters(filters, event)) {
|
|
406
|
-
addEvent(event
|
|
471
|
+
addEvent(event);
|
|
407
472
|
}
|
|
408
473
|
}),
|
|
409
474
|
on(tracker, "remove", (id, url) => {
|
|
@@ -413,10 +478,8 @@ export const deriveItemsByKeyByUrl = ({ getKey, filters, repository, tracker, ev
|
|
|
413
478
|
}),
|
|
414
479
|
on(tracker, "load", rebuild),
|
|
415
480
|
on(tracker, "clear", () => {
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
keysById.clear();
|
|
419
|
-
set(itemsByKey);
|
|
481
|
+
if (clear())
|
|
482
|
+
set(itemsByKey);
|
|
420
483
|
}),
|
|
421
484
|
];
|
|
422
485
|
// Re-evaluate everything when external key state (e.g. relay self pubkeys)
|
|
@@ -435,9 +498,10 @@ export const deriveItemsByKeyByUrl = ({ getKey, filters, repository, tracker, ev
|
|
|
435
498
|
}
|
|
436
499
|
return () => unsubscribers.forEach(call);
|
|
437
500
|
});
|
|
501
|
+
return asCollection(store, pending);
|
|
438
502
|
};
|
|
439
|
-
export const deriveItems = (itemsByKeyStore) =>
|
|
440
|
-
export const deriveItemsSorted = (sortFn, itemsStore) =>
|
|
503
|
+
export const deriveItems = (itemsByKeyStore) => derived(itemsByKeyStore, itemsByKey => Array.from(itemsByKey.values()));
|
|
504
|
+
export const deriveItemsSorted = (sortFn, itemsStore) => derived(itemsStore, items => sortBy(sortFn, items));
|
|
441
505
|
export const makeDeriveItem = (itemsByKeyStore, onDerive) => {
|
|
442
506
|
return (key, ...args) => {
|
|
443
507
|
if (!key)
|
|
@@ -464,7 +528,7 @@ export const makeLoadItem = (loadItem, getItem, options = {}) => {
|
|
|
464
528
|
const attempts = new LRUCache(maxSize);
|
|
465
529
|
const pending = new Map();
|
|
466
530
|
return async (key, ...args) => {
|
|
467
|
-
const stale = getItem(key);
|
|
531
|
+
const stale = await getItem(key);
|
|
468
532
|
// If we have an item, reload if it's relatively recent
|
|
469
533
|
if (stale && getFetched(key) > now() - timeout) {
|
|
470
534
|
return stale;
|
|
@@ -499,7 +563,7 @@ export const makeLoadItem = (loadItem, getItem, options = {}) => {
|
|
|
499
563
|
};
|
|
500
564
|
};
|
|
501
565
|
// Miscellaneous other stuff
|
|
502
|
-
export const deriveIsDeleted = (repository, event) => readable(false, set => {
|
|
566
|
+
export const deriveIsDeleted = (repository, event) => projection(readable(false, set => {
|
|
503
567
|
const idOrAddress = getIdOrAddress(event);
|
|
504
568
|
set(repository.isDeleted(event));
|
|
505
569
|
return on(repository, "update", ({ removed, added }) => {
|
|
@@ -512,5 +576,5 @@ export const deriveIsDeleted = (repository, event) => readable(false, set => {
|
|
|
512
576
|
}
|
|
513
577
|
}
|
|
514
578
|
});
|
|
515
|
-
});
|
|
579
|
+
}), () => repository.isDeleted(event));
|
|
516
580
|
//# sourceMappingURL=repository.js.map
|