@qntx/nostr 0.6.0 → 0.8.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/{abort-Ba8tDrOI.mjs → abort-DBq2STPj.mjs} +13 -6
- package/dist/abort-DBq2STPj.mjs.map +1 -0
- package/dist/{builder-sSflu6nB.d.mts → builder-CTwkB2zM.d.mts} +14 -15
- package/dist/{builder-9tjI6WQ3.mjs → builder-aNU2gGFP.mjs} +11 -17
- package/dist/builder-aNU2gGFP.mjs.map +1 -0
- package/dist/{client-CadO5fAX.mjs → client-Cj2lUaVh.mjs} +141 -353
- package/dist/client-Cj2lUaVh.mjs.map +1 -0
- package/dist/client.d.mts +2 -2
- package/dist/client.mjs +2 -2
- package/dist/collections-DtwMc1NU.mjs +33 -0
- package/dist/collections-DtwMc1NU.mjs.map +1 -0
- package/dist/core.d.mts +9 -8
- package/dist/core.mjs +7 -7
- package/dist/emitter-DkCY6NkU.mjs +32 -0
- package/dist/emitter-DkCY6NkU.mjs.map +1 -0
- package/dist/{error-BW7re1UN.d.mts → error-BD_0QFKT.d.mts} +2 -2
- package/dist/{error-DrEIM7FO.mjs → error-BILMe3Gr.mjs} +2 -2
- package/dist/{error-DrEIM7FO.mjs.map → error-BILMe3Gr.mjs.map} +1 -1
- package/dist/{error-CR8Urc84.d.mts → error-BquXDmIN.d.mts} +4 -4
- package/dist/{error-B__OMBRY.mjs → error-DlhGW4mJ.mjs} +2 -2
- package/dist/{error-B__OMBRY.mjs.map → error-DlhGW4mJ.mjs.map} +1 -1
- package/dist/{event-D8Nfoh4K.mjs → event-CHf47dPM.mjs} +16 -10
- package/dist/event-CHf47dPM.mjs.map +1 -0
- package/dist/{event-fU3Y01PR.d.mts → event-DJeb_DIL.d.mts} +4 -2
- package/dist/{filter-C0IMByE3.d.mts → filter-jI_9htF7.d.mts} +2 -2
- package/dist/{gossip-oloDMWEj.mjs → gossip-DFxIBlsr.mjs} +23 -33
- package/dist/gossip-DFxIBlsr.mjs.map +1 -0
- package/dist/{gossip-DpIvkBuj.d.mts → gossip-OOeeFzG5.d.mts} +37 -28
- package/dist/gossip.d.mts +1 -1
- package/dist/gossip.mjs +1 -1
- package/dist/{index-D1bqFHKB.d.mts → index-BxCBX-8R.d.mts} +18 -18
- package/dist/{index-lvXeER5t.d.mts → index-CPVEyzNX.d.mts} +32 -50
- package/dist/{index-MxC28S4P.d.mts → index-C_w2WfVz.d.mts} +27 -29
- package/dist/{index-CNl2q67H.d.mts → index-Cl_1XdYP.d.mts} +111 -180
- package/dist/{index-CvkvqB16.d.mts → index-DU9tRFTZ.d.mts} +7 -20
- package/dist/{index-q4MDce_r.d.mts → index-DyKwQnbt.d.mts} +6 -8
- package/dist/index.d.mts +23 -21
- package/dist/index.mjs +21 -19
- package/dist/{instance-DQE8BoWt.mjs → instance-C62w3cEt.mjs} +26 -27
- package/dist/instance-C62w3cEt.mjs.map +1 -0
- package/dist/{instance-CIca-ynn.d.mts → instance-DjsL8h84.d.mts} +5 -5
- package/dist/{key-Cv4_pN3x.d.mts → key-D_5OgGT7.d.mts} +11 -7
- package/dist/{key-Bps-LqX7.mjs → key-DnVpchl6.mjs} +13 -9
- package/dist/key-DnVpchl6.mjs.map +1 -0
- package/dist/{loaders-o6YXB_Ri.mjs → loaders-BmPkQfzI.mjs} +73 -82
- package/dist/loaders-BmPkQfzI.mjs.map +1 -0
- package/dist/loaders.d.mts +3 -3
- package/dist/loaders.mjs +2 -2
- package/dist/{memory-C2EVx0_O.mjs → memory-CdJ07kub.mjs} +2 -2
- package/dist/memory-CdJ07kub.mjs.map +1 -0
- package/dist/{memory-index-Do1mz0WF.mjs → memory-index-Cbc83vOZ.mjs} +30 -247
- package/dist/memory-index-Cbc83vOZ.mjs.map +1 -0
- package/dist/message-oNr7t0SJ.mjs +194 -0
- package/dist/message-oNr7t0SJ.mjs.map +1 -0
- package/dist/{message-iGPIqnn0.d.mts → message-tclYCVNc.d.mts} +6 -6
- package/dist/{nip17-CKIufV98.d.mts → nip17-B5WgW4C4.d.mts} +6 -7
- package/dist/{nip19-BevCJZsp.d.mts → nip19-DpPN17bY.d.mts} +25 -31
- package/dist/{nip46-DDV4dC56.d.mts → nip46-BHaxC9TZ.d.mts} +19 -21
- package/dist/nip51-CR0Q8eym.d.mts +87 -0
- package/dist/{nip59-zQgdLcEr.d.mts → nip59-C-RWFQIv.d.mts} +11 -5
- package/dist/nip65-D1fbmhOg.d.mts +23 -0
- package/dist/{nip77-DH4RhS5r.d.mts → nip77-DzUwUxHq.d.mts} +8 -9
- package/dist/nips/blossom.d.mts +17 -13
- package/dist/nips/blossom.mjs +30 -9
- package/dist/nips/blossom.mjs.map +1 -1
- package/dist/nips/nip04.mjs +17 -7
- package/dist/nips/nip04.mjs.map +1 -1
- package/dist/nips/nip05.d.mts +9 -10
- package/dist/nips/nip05.mjs +1 -4
- package/dist/nips/nip05.mjs.map +1 -1
- package/dist/nips/nip10.d.mts +8 -8
- package/dist/nips/nip10.mjs +34 -32
- package/dist/nips/nip10.mjs.map +1 -1
- package/dist/nips/nip11.d.mts +28 -28
- package/dist/nips/nip11.mjs +4 -4
- package/dist/nips/nip11.mjs.map +1 -1
- package/dist/nips/nip13.d.mts +7 -7
- package/dist/nips/nip13.mjs +32 -10
- package/dist/nips/nip13.mjs.map +1 -1
- package/dist/nips/nip17.d.mts +1 -1
- package/dist/nips/nip17.mjs +16 -34
- package/dist/nips/nip17.mjs.map +1 -1
- package/dist/nips/nip19.d.mts +2 -2
- package/dist/nips/nip19.mjs +16 -28
- package/dist/nips/nip19.mjs.map +1 -1
- package/dist/nips/nip21.d.mts +9 -4
- package/dist/nips/nip21.mjs +15 -5
- package/dist/nips/nip21.mjs.map +1 -1
- package/dist/nips/nip27.d.mts +22 -22
- package/dist/nips/nip27.mjs +2 -2
- package/dist/nips/nip27.mjs.map +1 -1
- package/dist/nips/nip42.d.mts +1 -1
- package/dist/nips/nip42.mjs +2 -1
- package/dist/nips/nip42.mjs.map +1 -1
- package/dist/nips/nip44.mjs +2 -2
- package/dist/nips/nip44.mjs.map +1 -1
- package/dist/nips/nip46.d.mts +2 -2
- package/dist/nips/nip46.mjs +15 -19
- package/dist/nips/nip46.mjs.map +1 -1
- package/dist/nips/nip49.d.mts +9 -9
- package/dist/nips/nip49.mjs +4 -4
- package/dist/nips/nip49.mjs.map +1 -1
- package/dist/nips/nip51.d.mts +2 -86
- package/dist/nips/nip51.mjs +7 -23
- package/dist/nips/nip51.mjs.map +1 -1
- package/dist/nips/nip57.d.mts +25 -23
- package/dist/nips/nip57.mjs +12 -17
- package/dist/nips/nip57.mjs.map +1 -1
- package/dist/nips/nip59.d.mts +1 -1
- package/dist/nips/nip59.mjs +27 -19
- package/dist/nips/nip59.mjs.map +1 -1
- package/dist/nips/nip65.d.mts +2 -2
- package/dist/nips/nip65.mjs +14 -37
- package/dist/nips/nip65.mjs.map +1 -1
- package/dist/nips/nip77.d.mts +1 -1
- package/dist/nips/nip77.mjs +33 -32
- package/dist/nips/nip77.mjs.map +1 -1
- package/dist/nips/nip98.d.mts +5 -5
- package/dist/nips/nip98.mjs +8 -8
- package/dist/nips/nip98.mjs.map +1 -1
- package/dist/{pool-DBIYMtwy.d.mts → pool-CqQvUnsq.d.mts} +132 -108
- package/dist/pool-vlw74C4t.mjs +606 -0
- package/dist/pool-vlw74C4t.mjs.map +1 -0
- package/dist/put-w13ci3sC.mjs +187 -0
- package/dist/put-w13ci3sC.mjs.map +1 -0
- package/dist/{reactive-BfhPp9a3.mjs → reactive-Tz0otDIP.mjs} +125 -88
- package/dist/reactive-Tz0otDIP.mjs.map +1 -0
- package/dist/{reactive-7aqeip4A.d.mts → reactive-gGqUrzW8.d.mts} +20 -26
- package/dist/relay-quCs7MHD.mjs +1811 -0
- package/dist/relay-quCs7MHD.mjs.map +1 -0
- package/dist/relay.d.mts +4 -4
- package/dist/relay.mjs +3 -2
- package/dist/serial-Bzpw-xz3.mjs +21 -0
- package/dist/serial-Bzpw-xz3.mjs.map +1 -0
- package/dist/{signer-CYQutDzD.mjs → signer-poTGe6Er.mjs} +12 -14
- package/dist/signer-poTGe6Er.mjs.map +1 -0
- package/dist/signer.d.mts +2 -2
- package/dist/signer.mjs +2 -2
- package/dist/{storage-Dky3wuoH.mjs → storage-B5IXTVuS.mjs} +28 -51
- package/dist/storage-B5IXTVuS.mjs.map +1 -0
- package/dist/storage.d.mts +3 -3
- package/dist/storage.mjs +4 -4
- package/dist/store.d.mts +2 -2
- package/dist/store.mjs +1 -1
- package/dist/testing.d.mts +19 -19
- package/dist/testing.mjs +9 -9
- package/dist/testing.mjs.map +1 -1
- package/dist/{types-2pCUprRU.d.mts → types-BacwnDtU.d.mts} +10 -10
- package/dist/{types-CRQEk0Oi.d.mts → types-DNmiscfd.d.mts} +2 -2
- package/dist/{util-LfQirgDk.mjs → util-DMF9AIO0.mjs} +33 -7
- package/dist/util-DMF9AIO0.mjs.map +1 -0
- package/dist/{verifier-t5WoWbtY.mjs → verifier-B51Wkt5H.mjs} +3 -3
- package/dist/verifier-B51Wkt5H.mjs.map +1 -0
- package/dist/verifier-CgTFpgsC.d.mts +22 -0
- package/dist/wasm.browser.d.mts +3 -3
- package/dist/wasm.browser.mjs +3 -3
- package/dist/wasm.d.mts +3 -3
- package/dist/wasm.mjs +3 -3
- package/dist/wasm.mjs.map +1 -1
- package/package.json +5 -9
- package/dist/abort-Ba8tDrOI.mjs.map +0 -1
- package/dist/builder-9tjI6WQ3.mjs.map +0 -1
- package/dist/client-CadO5fAX.mjs.map +0 -1
- package/dist/event-D8Nfoh4K.mjs.map +0 -1
- package/dist/gossip-oloDMWEj.mjs.map +0 -1
- package/dist/instance-DQE8BoWt.mjs.map +0 -1
- package/dist/key-Bps-LqX7.mjs.map +0 -1
- package/dist/loaders-o6YXB_Ri.mjs.map +0 -1
- package/dist/memory-C2EVx0_O.mjs.map +0 -1
- package/dist/memory-index-Do1mz0WF.mjs.map +0 -1
- package/dist/message-DcY6Fi9o.mjs +0 -193
- package/dist/message-DcY6Fi9o.mjs.map +0 -1
- package/dist/nip65-CjgmdpPB.d.mts +0 -26
- package/dist/nips/nip96.d.mts +0 -40
- package/dist/nips/nip96.mjs +0 -118
- package/dist/nips/nip96.mjs.map +0 -1
- package/dist/pool-As20OGxB.mjs +0 -2166
- package/dist/pool-As20OGxB.mjs.map +0 -1
- package/dist/reactive-BfhPp9a3.mjs.map +0 -1
- package/dist/signer-CYQutDzD.mjs.map +0 -1
- package/dist/storage-Dky3wuoH.mjs.map +0 -1
- package/dist/util-LfQirgDk.mjs.map +0 -1
- package/dist/verifier-t5WoWbtY.mjs.map +0 -1
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { u as normalizeURL } from "./util-DMF9AIO0.mjs";
|
|
2
|
+
import { t as Kind } from "./kind-Cxwhhkx8.mjs";
|
|
3
|
+
import { g as eventAddress, o as itemCompare, v as formatEventAddress, x as parseEventAddress } from "./event-CHf47dPM.mjs";
|
|
3
4
|
import { o as matchFilters, r as filterFingerprint } from "./filter-BQl3GlHt.mjs";
|
|
4
5
|
import { t as invokeSafely } from "./report-CHld4uWj.mjs";
|
|
5
|
-
import { t as
|
|
6
|
+
import { t as Emitter } from "./emitter-DkCY6NkU.mjs";
|
|
7
|
+
import { i as trimOldest, n as removeFromSetMap, t as addToSetMap } from "./collections-DtwMc1NU.mjs";
|
|
8
|
+
import { t as MemoryIndex } from "./memory-index-Cbc83vOZ.mjs";
|
|
6
9
|
//#region src/store/reactive.ts
|
|
7
10
|
const SEEN_ON_PER_ID = 16;
|
|
8
11
|
var WatchImpl = class {
|
|
9
|
-
|
|
12
|
+
host;
|
|
10
13
|
kind;
|
|
11
14
|
key;
|
|
12
15
|
filters;
|
|
@@ -18,8 +21,8 @@ var WatchImpl = class {
|
|
|
18
21
|
#version = -1;
|
|
19
22
|
#dirty = false;
|
|
20
23
|
#pendingRemove = false;
|
|
21
|
-
constructor(
|
|
22
|
-
this.
|
|
24
|
+
constructor(host, kind, key, compute, equal, snapshotIds, filters) {
|
|
25
|
+
this.host = host;
|
|
23
26
|
this.kind = kind;
|
|
24
27
|
this.key = key;
|
|
25
28
|
this.filters = filters;
|
|
@@ -27,7 +30,7 @@ var WatchImpl = class {
|
|
|
27
30
|
this.equal = equal;
|
|
28
31
|
this.snapshotIds = snapshotIds;
|
|
29
32
|
this.#snapshot = compute();
|
|
30
|
-
this.#version =
|
|
33
|
+
this.#version = host.version();
|
|
31
34
|
}
|
|
32
35
|
get subscribed() {
|
|
33
36
|
return this.#subscribers.size > 0;
|
|
@@ -39,30 +42,33 @@ var WatchImpl = class {
|
|
|
39
42
|
const wasUnsubscribed = this.#subscribers.size === 0;
|
|
40
43
|
this.#subscribers.add(onChange);
|
|
41
44
|
this.#pendingRemove = false;
|
|
42
|
-
if (wasUnsubscribed && this.#version !== this.
|
|
43
|
-
this.
|
|
45
|
+
if (wasUnsubscribed && this.#version !== this.host.version()) this.#dirty = true;
|
|
46
|
+
this.host.register(this);
|
|
44
47
|
return () => {
|
|
45
48
|
this.#subscribers.delete(onChange);
|
|
46
49
|
if (this.#subscribers.size > 0 || this.#pendingRemove) return;
|
|
47
50
|
this.#pendingRemove = true;
|
|
48
51
|
queueMicrotask(() => {
|
|
49
|
-
if (this.#pendingRemove) this.
|
|
52
|
+
if (this.#pendingRemove) this.host.unregister(this);
|
|
50
53
|
});
|
|
51
54
|
};
|
|
52
55
|
}
|
|
53
56
|
getSnapshot() {
|
|
54
|
-
if (this.subscribed ? this.#dirty : this.#version !== this.
|
|
57
|
+
if (this.subscribed ? this.#dirty : this.#version !== this.host.version()) {
|
|
55
58
|
const next = this.compute();
|
|
56
|
-
if (!this.equal(next, this.#snapshot))
|
|
57
|
-
|
|
59
|
+
if (!this.equal(next, this.#snapshot)) {
|
|
60
|
+
this.#snapshot = next;
|
|
61
|
+
this.host.repin(this);
|
|
62
|
+
}
|
|
63
|
+
this.#version = this.host.version();
|
|
58
64
|
this.#dirty = false;
|
|
59
65
|
}
|
|
60
66
|
return this.#snapshot;
|
|
61
67
|
}
|
|
62
|
-
|
|
68
|
+
markDirty() {
|
|
63
69
|
this.#dirty = true;
|
|
64
70
|
}
|
|
65
|
-
|
|
71
|
+
notify() {
|
|
66
72
|
for (const onChange of this.#subscribers) invokeSafely(onChange);
|
|
67
73
|
}
|
|
68
74
|
};
|
|
@@ -86,7 +92,7 @@ var ReactiveEventStore = class {
|
|
|
86
92
|
#index;
|
|
87
93
|
#maxEvents;
|
|
88
94
|
#maxSeenOnEntries;
|
|
89
|
-
|
|
95
|
+
#version = 0;
|
|
90
96
|
#recency = /* @__PURE__ */ new Set();
|
|
91
97
|
#seenOn = /* @__PURE__ */ new Map();
|
|
92
98
|
#idWatches = /* @__PURE__ */ new Map();
|
|
@@ -94,11 +100,41 @@ var ReactiveEventStore = class {
|
|
|
94
100
|
#eventCache = /* @__PURE__ */ new Map();
|
|
95
101
|
#addressCache = /* @__PURE__ */ new Map();
|
|
96
102
|
#queryCache = /* @__PURE__ */ new Map();
|
|
97
|
-
#
|
|
103
|
+
#queryByKind = /* @__PURE__ */ new Map();
|
|
104
|
+
#queryAnyKind = /* @__PURE__ */ new Set();
|
|
105
|
+
#pinned = /* @__PURE__ */ new Map();
|
|
106
|
+
#watchPins = /* @__PURE__ */ new Map();
|
|
98
107
|
#dirty = /* @__PURE__ */ new Set();
|
|
99
108
|
#flushScheduled = false;
|
|
100
|
-
#
|
|
101
|
-
#
|
|
109
|
+
#events = new Emitter();
|
|
110
|
+
#watchHost = {
|
|
111
|
+
version: () => this.#version,
|
|
112
|
+
register: (watch) => {
|
|
113
|
+
this.#registerWatch(watch);
|
|
114
|
+
if (!this.#watchPins.has(watch)) {
|
|
115
|
+
const ids = watch.pinnedIds;
|
|
116
|
+
this.#watchPins.set(watch, ids);
|
|
117
|
+
this.#pin(ids);
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
unregister: (watch) => {
|
|
121
|
+
if (watch.subscribed) return;
|
|
122
|
+
this.#unregisterWatch(watch);
|
|
123
|
+
const ids = this.#watchPins.get(watch);
|
|
124
|
+
if (ids !== void 0) {
|
|
125
|
+
this.#watchPins.delete(watch);
|
|
126
|
+
this.#unpin(ids);
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
repin: (watch) => {
|
|
130
|
+
const old = this.#watchPins.get(watch);
|
|
131
|
+
if (old === void 0) return;
|
|
132
|
+
const next = watch.pinnedIds;
|
|
133
|
+
this.#unpin(old);
|
|
134
|
+
this.#pin(next);
|
|
135
|
+
this.#watchPins.set(watch, next);
|
|
136
|
+
}
|
|
137
|
+
};
|
|
102
138
|
constructor(opts) {
|
|
103
139
|
this.#maxEvents = opts?.maxEvents ?? 5e4;
|
|
104
140
|
this.#maxSeenOnEntries = opts?.maxSeenOnEntries ?? 2e4;
|
|
@@ -141,7 +177,7 @@ var ReactiveEventStore = class {
|
|
|
141
177
|
this.#index.clear();
|
|
142
178
|
this.#seenOn.clear();
|
|
143
179
|
this.#recency.clear();
|
|
144
|
-
this
|
|
180
|
+
this.#version += 1;
|
|
145
181
|
this.#invalidateAll();
|
|
146
182
|
}
|
|
147
183
|
get(id) {
|
|
@@ -175,7 +211,7 @@ var ReactiveEventStore = class {
|
|
|
175
211
|
const key = id.toLowerCase();
|
|
176
212
|
let watch = this.#eventCache.get(key);
|
|
177
213
|
if (!watch) {
|
|
178
|
-
watch = new WatchImpl(this, "event", key, () => this.get(key), sameRef, EVENT_IDS);
|
|
214
|
+
watch = new WatchImpl(this.#watchHost, "event", key, () => this.get(key), sameRef, EVENT_IDS);
|
|
179
215
|
this.#eventCache.set(key, watch);
|
|
180
216
|
}
|
|
181
217
|
return watch;
|
|
@@ -184,7 +220,7 @@ var ReactiveEventStore = class {
|
|
|
184
220
|
const address = formatEventAddress(kind, pubkey, d ?? "");
|
|
185
221
|
let watch = this.#addressCache.get(address);
|
|
186
222
|
if (!watch) {
|
|
187
|
-
watch = new WatchImpl(this, "replaceable", address, () => this.getByAddress(address), sameRef, EVENT_IDS);
|
|
223
|
+
watch = new WatchImpl(this.#watchHost, "replaceable", address, () => this.getByAddress(address), sameRef, EVENT_IDS);
|
|
188
224
|
this.#addressCache.set(address, watch);
|
|
189
225
|
}
|
|
190
226
|
return watch;
|
|
@@ -194,55 +230,70 @@ var ReactiveEventStore = class {
|
|
|
194
230
|
let watch = this.#queryCache.get(key);
|
|
195
231
|
if (!watch) {
|
|
196
232
|
const list = [...filters];
|
|
197
|
-
watch = new WatchImpl(this, "query", key, () => this.query(list), sameList, LIST_IDS, list);
|
|
233
|
+
watch = new WatchImpl(this.#watchHost, "query", key, () => this.query(list), sameList, LIST_IDS, list);
|
|
198
234
|
this.#queryCache.set(key, watch);
|
|
199
235
|
}
|
|
200
236
|
return watch;
|
|
201
237
|
}
|
|
202
|
-
/**
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
238
|
+
/**
|
|
239
|
+
* Listen for a store event. Multiple listeners per type are allowed and fire in registration
|
|
240
|
+
* order; a throwing listener is reported and does not break the dispatch. Returns an unsubscribe
|
|
241
|
+
* function.
|
|
242
|
+
*/
|
|
243
|
+
on(type, listener) {
|
|
244
|
+
return this.#events.on(type, listener);
|
|
208
245
|
}
|
|
209
|
-
|
|
210
|
-
onRemove(listener) {
|
|
211
|
-
this.#removeListeners.add(listener);
|
|
212
|
-
return () => {
|
|
213
|
-
this.#removeListeners.delete(listener);
|
|
214
|
-
};
|
|
215
|
-
}
|
|
216
|
-
_register(watch) {
|
|
246
|
+
#registerWatch(watch) {
|
|
217
247
|
switch (watch.kind) {
|
|
218
248
|
case "event":
|
|
219
|
-
|
|
249
|
+
addToSetMap(this.#idWatches, watch.key, watch);
|
|
220
250
|
return;
|
|
221
251
|
case "replaceable":
|
|
222
|
-
|
|
252
|
+
addToSetMap(this.#addressWatches, watch.key, watch);
|
|
223
253
|
return;
|
|
224
|
-
case "query":
|
|
254
|
+
case "query": {
|
|
255
|
+
const kinds = this.#queryKinds(watch);
|
|
256
|
+
if (kinds === void 0) {
|
|
257
|
+
this.#queryAnyKind.add(watch);
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
for (const kind of kinds) addToSetMap(this.#queryByKind, kind, watch);
|
|
261
|
+
}
|
|
225
262
|
}
|
|
226
263
|
}
|
|
227
|
-
|
|
228
|
-
if (watch.subscribed) return;
|
|
264
|
+
#unregisterWatch(watch) {
|
|
229
265
|
switch (watch.kind) {
|
|
230
266
|
case "event":
|
|
231
|
-
|
|
267
|
+
removeFromSetMap(this.#idWatches, watch.key, watch);
|
|
232
268
|
if (this.#eventCache.get(watch.key) === watch) this.#eventCache.delete(watch.key);
|
|
233
269
|
return;
|
|
234
270
|
case "replaceable":
|
|
235
|
-
|
|
271
|
+
removeFromSetMap(this.#addressWatches, watch.key, watch);
|
|
236
272
|
if (this.#addressCache.get(watch.key) === watch) this.#addressCache.delete(watch.key);
|
|
237
273
|
return;
|
|
238
|
-
case "query":
|
|
239
|
-
this.#
|
|
274
|
+
case "query": {
|
|
275
|
+
const kinds = this.#queryKinds(watch);
|
|
276
|
+
if (kinds === void 0) this.#queryAnyKind.delete(watch);
|
|
277
|
+
else for (const kind of kinds) removeFromSetMap(this.#queryByKind, kind, watch);
|
|
240
278
|
if (this.#queryCache.get(watch.key) === watch) this.#queryCache.delete(watch.key);
|
|
279
|
+
}
|
|
241
280
|
}
|
|
242
281
|
}
|
|
282
|
+
/**
|
|
283
|
+
* Kind buckets a query watch belongs to (deduped across filters), or undefined when any filter
|
|
284
|
+
* lacks a non-empty `kinds` and so can match every kind.
|
|
285
|
+
*/
|
|
286
|
+
#queryKinds(watch) {
|
|
287
|
+
const kinds = /* @__PURE__ */ new Set();
|
|
288
|
+
for (const filter of watch.filters ?? []) {
|
|
289
|
+
if (filter.kinds === void 0 || filter.kinds.length === 0) return;
|
|
290
|
+
for (const kind of filter.kinds) kinds.add(kind);
|
|
291
|
+
}
|
|
292
|
+
return kinds;
|
|
293
|
+
}
|
|
243
294
|
#touch(id) {
|
|
244
|
-
|
|
245
|
-
|
|
295
|
+
this.#recency.delete(id);
|
|
296
|
+
this.#recency.add(id);
|
|
246
297
|
}
|
|
247
298
|
#recordSeen(id, relayUrl) {
|
|
248
299
|
const url = normalizeURL(relayUrl);
|
|
@@ -252,23 +303,19 @@ var ReactiveEventStore = class {
|
|
|
252
303
|
this.#seenOn.set(id, urls);
|
|
253
304
|
}
|
|
254
305
|
if (!urls.includes(url) && urls.length < SEEN_ON_PER_ID) urls.push(url);
|
|
255
|
-
|
|
256
|
-
const oldest = this.#seenOn.keys().next().value;
|
|
257
|
-
if (oldest === void 0) break;
|
|
258
|
-
this.#seenOn.delete(oldest);
|
|
259
|
-
}
|
|
306
|
+
trimOldest(this.#seenOn, this.#maxSeenOnEntries);
|
|
260
307
|
}
|
|
261
308
|
#onInsert(event) {
|
|
262
|
-
this
|
|
309
|
+
this.#version += 1;
|
|
263
310
|
this.#touch(event.id);
|
|
264
311
|
this.#invalidateByEvent(event);
|
|
265
|
-
|
|
312
|
+
this.#events.emit("insert", event);
|
|
266
313
|
}
|
|
267
314
|
#onRemove(event) {
|
|
268
|
-
this
|
|
315
|
+
this.#version += 1;
|
|
269
316
|
this.#recency.delete(event.id);
|
|
270
317
|
this.#invalidateByEvent(event);
|
|
271
|
-
|
|
318
|
+
this.#events.emit("remove", event);
|
|
272
319
|
}
|
|
273
320
|
#invalidateByEvent(event) {
|
|
274
321
|
const byId = this.#idWatches.get(event.id);
|
|
@@ -278,7 +325,7 @@ var ReactiveEventStore = class {
|
|
|
278
325
|
const byAddress = this.#addressWatches.get(address);
|
|
279
326
|
if (byAddress) for (const watch of byAddress) this.#markDirty(watch);
|
|
280
327
|
}
|
|
281
|
-
if (event.kind ===
|
|
328
|
+
if (event.kind === Kind.EventDeletion) {
|
|
282
329
|
for (const tag of event.tags) if (tag[0] === "e" && tag[1] !== void 0) {
|
|
283
330
|
const watches = this.#idWatches.get(tag[1].toLowerCase());
|
|
284
331
|
if (watches) for (const watch of watches) this.#markDirty(watch);
|
|
@@ -289,16 +336,21 @@ var ReactiveEventStore = class {
|
|
|
289
336
|
if (watches) for (const watch of watches) this.#markDirty(watch);
|
|
290
337
|
}
|
|
291
338
|
}
|
|
292
|
-
|
|
339
|
+
const byKind = this.#queryByKind.get(event.kind);
|
|
340
|
+
if (byKind) {
|
|
341
|
+
for (const watch of byKind) if (watch.filters !== void 0 && matchFilters(watch.filters, event)) this.#markDirty(watch);
|
|
342
|
+
}
|
|
343
|
+
for (const watch of this.#queryAnyKind) if (watch.filters !== void 0 && matchFilters(watch.filters, event)) this.#markDirty(watch);
|
|
293
344
|
}
|
|
294
345
|
#invalidateAll() {
|
|
295
346
|
for (const watches of this.#idWatches.values()) for (const watch of watches) this.#markDirty(watch);
|
|
296
347
|
for (const watches of this.#addressWatches.values()) for (const watch of watches) this.#markDirty(watch);
|
|
297
|
-
for (const
|
|
348
|
+
for (const watches of this.#queryByKind.values()) for (const watch of watches) this.#markDirty(watch);
|
|
349
|
+
for (const watch of this.#queryAnyKind) this.#markDirty(watch);
|
|
298
350
|
this.#scheduleFlush();
|
|
299
351
|
}
|
|
300
352
|
#markDirty(watch) {
|
|
301
|
-
watch.
|
|
353
|
+
watch.markDirty();
|
|
302
354
|
this.#dirty.add(watch);
|
|
303
355
|
this.#scheduleFlush();
|
|
304
356
|
}
|
|
@@ -309,28 +361,27 @@ var ReactiveEventStore = class {
|
|
|
309
361
|
while (this.#dirty.size > 0) {
|
|
310
362
|
const batch = [...this.#dirty];
|
|
311
363
|
this.#dirty.clear();
|
|
312
|
-
for (const watch of batch) watch.
|
|
364
|
+
for (const watch of batch) watch.notify();
|
|
313
365
|
}
|
|
314
366
|
this.#flushScheduled = false;
|
|
315
367
|
});
|
|
316
368
|
}
|
|
317
|
-
#
|
|
318
|
-
const
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
369
|
+
#pin(ids) {
|
|
370
|
+
for (const id of ids) this.#pinned.set(id, (this.#pinned.get(id) ?? 0) + 1);
|
|
371
|
+
}
|
|
372
|
+
#unpin(ids) {
|
|
373
|
+
for (const id of ids) {
|
|
374
|
+
const count = (this.#pinned.get(id) ?? 0) - 1;
|
|
375
|
+
if (count <= 0) this.#pinned.delete(id);
|
|
376
|
+
else this.#pinned.set(id, count);
|
|
377
|
+
}
|
|
326
378
|
}
|
|
327
379
|
#evictIfNeeded(protectedId) {
|
|
328
380
|
if (this.#index.size <= this.#maxEvents) return;
|
|
329
|
-
const pinned = this.#pinnedIds();
|
|
330
381
|
const evicting = [];
|
|
331
382
|
for (const id of this.#recency) {
|
|
332
383
|
if (this.#index.size - evicting.length <= this.#maxEvents) break;
|
|
333
|
-
if (pinned.has(id) || id === protectedId) continue;
|
|
384
|
+
if (this.#pinned.has(id) || id === protectedId) continue;
|
|
334
385
|
if (this.#index.get(id) === void 0) continue;
|
|
335
386
|
evicting.push(id);
|
|
336
387
|
}
|
|
@@ -338,21 +389,7 @@ var ReactiveEventStore = class {
|
|
|
338
389
|
for (const id of evicting) this.#recency.delete(id);
|
|
339
390
|
}
|
|
340
391
|
};
|
|
341
|
-
function addWatch(map, key, watch) {
|
|
342
|
-
let set = map.get(key);
|
|
343
|
-
if (!set) {
|
|
344
|
-
set = /* @__PURE__ */ new Set();
|
|
345
|
-
map.set(key, set);
|
|
346
|
-
}
|
|
347
|
-
set.add(watch);
|
|
348
|
-
}
|
|
349
|
-
function removeWatch(map, key, watch) {
|
|
350
|
-
const set = map.get(key);
|
|
351
|
-
if (!set) return;
|
|
352
|
-
set.delete(watch);
|
|
353
|
-
if (set.size === 0) map.delete(key);
|
|
354
|
-
}
|
|
355
392
|
//#endregion
|
|
356
393
|
export { ReactiveEventStore as t };
|
|
357
394
|
|
|
358
|
-
//# sourceMappingURL=reactive-
|
|
395
|
+
//# sourceMappingURL=reactive-Tz0otDIP.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reactive-Tz0otDIP.mjs","names":[],"sources":["../src/store/reactive.ts"],"sourcesContent":["import { addToSetMap, removeFromSetMap, trimOldest } from \"../core/collections.ts\";\nimport { Emitter } from \"../core/emitter.ts\";\nimport { itemCompare } from \"../core/event.ts\";\nimport type { Event } from \"../core/event.ts\";\nimport type { Filter } from \"../core/filter.ts\";\nimport { filterFingerprint, matchFilters } from \"../core/filter.ts\";\nimport { Kind } from \"../core/kind.ts\";\nimport { invokeSafely } from \"../core/report.ts\";\nimport { formatEventAddress, eventAddress, parseEventAddress } from \"../core/tag.ts\";\nimport { normalizeURL } from \"../core/util.ts\";\nimport { MemoryIndex } from \"../storage/memory-index.ts\";\nimport type { PutResult } from \"../storage/types.ts\";\n\n/** A reactive snapshot source compatible with `useSyncExternalStore`. */\nexport type Watch<T> = {\n subscribe: (onChange: () => void) => () => void;\n getSnapshot: () => T;\n};\n\n/** Capacity options for {@link ReactiveEventStore}. */\nexport type ReactiveEventStoreOptions = {\n /** Max stored events before LRU eviction. Default 50_000. */\n maxEvents?: number | undefined;\n /** Max ids tracked by `seenOn`. Default 20_000. */\n maxSeenOnEntries?: number | undefined;\n /** FIFO cap on tombstoned deletion ids. Default 100_000. */\n maxTombstones?: number | undefined;\n};\n\n/** Typed event payloads for {@link ReactiveEventStore.on}. */\nexport type ReactiveEventStoreEventMap = {\n /** Every physical index insert, fired synchronously after the update. */\n insert: Event;\n /** Every physical index remove, fired synchronously after watch invalidation. */\n remove: Event;\n};\n\nconst SEEN_ON_PER_ID = 16;\n\n/** Category of a {@link Watch} subscription. */\ntype WatchKind = \"event\" | \"replaceable\" | \"query\";\n\n/** Structural handle the store needs for invalidation; implemented by WatchImpl. */\ntype WatchHandle = {\n readonly kind: WatchKind;\n readonly key: string;\n readonly filters: ReadonlyArray<Filter> | undefined;\n readonly subscribed: boolean;\n readonly pinnedIds: ReadonlyArray<string>;\n markDirty: () => void;\n notify: () => void;\n};\n\n/** Store internals exposed to a {@link WatchImpl}: version clock and registry/pin bookkeeping. */\ntype WatchHost = {\n version: () => number;\n register: (watch: WatchHandle) => void;\n unregister: (watch: WatchHandle) => void;\n /** Refresh pinned ids after a registered watch's snapshot changed. No-op when unregistered. */\n repin: (watch: WatchHandle) => void;\n};\n\nclass WatchImpl<T> implements Watch<T>, WatchHandle {\n readonly host: WatchHost;\n readonly kind: WatchKind;\n readonly key: string;\n readonly filters: ReadonlyArray<Filter> | undefined;\n readonly compute: () => T;\n readonly equal: (a: T, b: T) => boolean;\n readonly snapshotIds: (snapshot: T) => ReadonlyArray<string>;\n readonly #subscribers = new Set<() => void>();\n #snapshot: T;\n #version = -1;\n #dirty = false;\n #pendingRemove = false;\n\n constructor(\n host: WatchHost,\n kind: WatchKind,\n key: string,\n compute: () => T,\n equal: (a: T, b: T) => boolean,\n snapshotIds: (snapshot: T) => ReadonlyArray<string>,\n filters?: ReadonlyArray<Filter>,\n ) {\n this.host = host;\n this.kind = kind;\n this.key = key;\n this.filters = filters;\n this.compute = compute;\n this.equal = equal;\n this.snapshotIds = snapshotIds;\n this.#snapshot = compute();\n this.#version = host.version();\n }\n\n get subscribed(): boolean {\n return this.#subscribers.size > 0;\n }\n\n get pinnedIds(): ReadonlyArray<string> {\n return this.snapshotIds(this.#snapshot);\n }\n\n subscribe(onChange: () => void): () => void {\n const wasUnsubscribed = this.#subscribers.size === 0;\n this.#subscribers.add(onChange);\n this.#pendingRemove = false;\n // Writes that landed while unregistered must not be lost.\n if (wasUnsubscribed && this.#version !== this.host.version()) {\n this.#dirty = true;\n }\n this.host.register(this);\n return () => {\n this.#subscribers.delete(onChange);\n if (this.#subscribers.size > 0 || this.#pendingRemove) {\n return;\n }\n this.#pendingRemove = true;\n queueMicrotask(() => {\n if (this.#pendingRemove) {\n this.host.unregister(this);\n }\n });\n };\n }\n\n getSnapshot(): T {\n if (this.subscribed ? this.#dirty : this.#version !== this.host.version()) {\n const next = this.compute();\n if (!this.equal(next, this.#snapshot)) {\n this.#snapshot = next;\n this.host.repin(this);\n }\n this.#version = this.host.version();\n this.#dirty = false;\n }\n return this.#snapshot;\n }\n\n markDirty(): void {\n this.#dirty = true;\n }\n\n notify(): void {\n // Do not sync #version here: subscribers will call getSnapshot, which\n // recomputes against the bumped store version and keeps the reference\n // when the result is element-wise identical. A throwing subscriber is\n // reported and never aborts the remaining notifications.\n for (const onChange of this.#subscribers) {\n invokeSafely(onChange);\n }\n }\n}\n\nconst EVENT_IDS = (e: Event | undefined): ReadonlyArray<string> => (e ? [e.id] : []);\nconst LIST_IDS = (events: ReadonlyArray<Event>): ReadonlyArray<string> => events.map((e) => e.id);\n\nfunction sameRef(a: Event | undefined, b: Event | undefined): boolean {\n return a === b;\n}\n\nfunction sameList(a: ReadonlyArray<Event>, b: ReadonlyArray<Event>): boolean {\n if (a.length !== b.length) {\n return false;\n }\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) {\n return false;\n }\n }\n return true;\n}\n\n/**\n * Synchronous reactive in-memory event store backed by {@link MemoryIndex}. The single read source\n * for Nostr events on the UI side: `Watch` snapshots keep referential stability for\n * `useSyncExternalStore` and are invalidated on matching writes, deletions and tombstones. Writes\n * batch notifications into one microtask flush.\n */\nexport class ReactiveEventStore {\n readonly #index: MemoryIndex;\n readonly #maxEvents: number;\n readonly #maxSeenOnEntries: number;\n\n #version = 0;\n\n // id -> recency-ordered access order (delete+add moves to the newest end)\n readonly #recency = new Set<string>();\n // id -> relay urls (≤ SEEN_ON_PER_ID); Map insertion order for eviction\n readonly #seenOn = new Map<string, string[]>();\n\n readonly #idWatches = new Map<string, Set<WatchHandle>>();\n readonly #addressWatches = new Map<string, Set<WatchHandle>>();\n readonly #eventCache = new Map<string, WatchImpl<Event | undefined>>();\n readonly #addressCache = new Map<string, WatchImpl<Event | undefined>>();\n readonly #queryCache = new Map<string, WatchImpl<ReadonlyArray<Event>>>();\n // Query watches indexed by filter kinds; a filter without kinds matches any kind.\n readonly #queryByKind = new Map<number, Set<WatchHandle>>();\n readonly #queryAnyKind = new Set<WatchHandle>();\n\n // Event-id → pin refcount across registered watch snapshots; eviction skips pinned ids.\n readonly #pinned = new Map<string, number>();\n // Registered watch → ids it currently pins (repin/unpin need the old set).\n readonly #watchPins = new Map<WatchHandle, ReadonlyArray<string>>();\n\n readonly #dirty = new Set<WatchHandle>();\n #flushScheduled = false;\n readonly #events = new Emitter<ReactiveEventStoreEventMap>();\n\n readonly #watchHost: WatchHost = {\n version: () => this.#version,\n register: (watch) => {\n this.#registerWatch(watch);\n if (!this.#watchPins.has(watch)) {\n const ids = watch.pinnedIds;\n this.#watchPins.set(watch, ids);\n this.#pin(ids);\n }\n },\n unregister: (watch) => {\n if (watch.subscribed) {\n return;\n }\n this.#unregisterWatch(watch);\n const ids = this.#watchPins.get(watch);\n if (ids !== undefined) {\n this.#watchPins.delete(watch);\n this.#unpin(ids);\n }\n },\n repin: (watch) => {\n const old = this.#watchPins.get(watch);\n if (old === undefined) {\n return;\n }\n const next = watch.pinnedIds;\n this.#unpin(old);\n this.#pin(next);\n this.#watchPins.set(watch, next);\n },\n };\n\n constructor(opts?: ReactiveEventStoreOptions) {\n this.#maxEvents = opts?.maxEvents ?? 50_000;\n this.#maxSeenOnEntries = opts?.maxSeenOnEntries ?? 20_000;\n this.#index = new MemoryIndex({\n maxTombstones: opts?.maxTombstones ?? 100_000,\n // Keep evicted replaceable winners rejectable while their body is gone.\n maxWatermarks: this.#maxEvents,\n onInsert: (event) => this.#onInsert(event),\n onRemove: (event) => this.#onRemove(event),\n });\n }\n\n add(event: Event, relayUrl?: string): PutResult {\n const result = this.#index.put(event);\n // Stored events are canonical; seenOn keys are their lowercase ids.\n const { id } = event;\n if (\n relayUrl !== undefined &&\n result !== \"ephemeral\" &&\n result !== \"rejected\" &&\n result !== \"invalid\"\n ) {\n this.#recordSeen(id, relayUrl);\n }\n // The just-inserted event must survive its own eviction pass even when\n // every older entry is pinned by a subscribed watch snapshot.\n this.#evictIfNeeded(id);\n return result;\n }\n\n addMany(events: ReadonlyArray<Event>, relayUrl?: string): PutResult[] {\n const results: PutResult[] = [];\n for (const event of events) {\n results.push(this.add(event, relayUrl));\n }\n return results;\n }\n\n /** Record a relay sighting for an id already in the index. No notification. */\n markSeen(id: string, relayUrl: string): boolean {\n const key = id.toLowerCase();\n if (this.#index.get(key) === undefined) {\n return false;\n }\n this.#recordSeen(key, relayUrl);\n return true;\n }\n\n /** Bulk load (initial hydration): no seenOn, one batched notification. */\n hydrate(events: ReadonlyArray<Event>): void {\n // Insert oldest-first so recency ends with the newest entries hottest.\n const sorted = [...events].sort(itemCompare);\n for (const event of sorted) {\n this.#index.put(event);\n }\n this.#evictIfNeeded();\n }\n\n remove(ids: ReadonlyArray<string>): number {\n return this.#index.remove(ids);\n }\n\n clear(): void {\n this.#index.clear();\n this.#seenOn.clear();\n this.#recency.clear();\n this.#version += 1;\n this.#invalidateAll();\n }\n\n get(id: string): Event | undefined {\n const event = this.#index.get(id);\n if (event) {\n this.#touch(event.id);\n }\n return event;\n }\n\n getReplaceable(kind: number, pubkey: string, d?: string): Event | undefined {\n return this.getByAddress(formatEventAddress(kind, pubkey, d ?? \"\"));\n }\n\n getByAddress(address: string): Event | undefined {\n const event = this.#index.getByAddress(address);\n if (event) {\n this.#touch(event.id);\n }\n return event;\n }\n\n query(filters: ReadonlyArray<Filter>): ReadonlyArray<Event> {\n const events = this.#index.query(filters);\n // Results come back newest-first; touch oldest→newest so the newest\n // entries end up hottest in the recency order.\n for (const event of [...events].reverse()) {\n this.#touch(event.id);\n }\n return events;\n }\n\n isDeleted(idOrAddress: string): boolean {\n return this.#index.isDeleted(idOrAddress);\n }\n\n seenOn(id: string): ReadonlyArray<string> {\n return this.#seenOn.get(id.toLowerCase()) ?? [];\n }\n\n get size(): number {\n return this.#index.size;\n }\n\n watchEvent(id: string): Watch<Event | undefined> {\n const key = id.toLowerCase();\n let watch = this.#eventCache.get(key);\n if (!watch) {\n watch = new WatchImpl(this.#watchHost, \"event\", key, () => this.get(key), sameRef, EVENT_IDS);\n this.#eventCache.set(key, watch);\n }\n return watch;\n }\n\n watchReplaceable(kind: number, pubkey: string, d?: string): Watch<Event | undefined> {\n const address = formatEventAddress(kind, pubkey, d ?? \"\");\n let watch = this.#addressCache.get(address);\n if (!watch) {\n watch = new WatchImpl(\n this.#watchHost,\n \"replaceable\",\n address,\n () => this.getByAddress(address),\n sameRef,\n EVENT_IDS,\n );\n this.#addressCache.set(address, watch);\n }\n return watch;\n }\n\n watchQuery(filters: ReadonlyArray<Filter>): Watch<ReadonlyArray<Event>> {\n const key = filterFingerprint(filters);\n let watch = this.#queryCache.get(key);\n if (!watch) {\n const list = [...filters];\n watch = new WatchImpl(\n this.#watchHost,\n \"query\",\n key,\n () => this.query(list),\n sameList,\n LIST_IDS,\n list,\n );\n this.#queryCache.set(key, watch);\n }\n return watch;\n }\n\n /**\n * Listen for a store event. Multiple listeners per type are allowed and fire in registration\n * order; a throwing listener is reported and does not break the dispatch. Returns an unsubscribe\n * function.\n */\n on<K extends keyof ReactiveEventStoreEventMap>(\n type: K,\n listener: (payload: ReactiveEventStoreEventMap[K]) => void,\n ): () => void {\n return this.#events.on(type, listener);\n }\n\n #registerWatch(watch: WatchHandle): void {\n switch (watch.kind) {\n case \"event\":\n addToSetMap(this.#idWatches, watch.key, watch);\n return;\n case \"replaceable\":\n addToSetMap(this.#addressWatches, watch.key, watch);\n return;\n case \"query\": {\n const kinds = this.#queryKinds(watch);\n if (kinds === undefined) {\n this.#queryAnyKind.add(watch);\n return;\n }\n for (const kind of kinds) {\n addToSetMap(this.#queryByKind, kind, watch);\n }\n }\n }\n }\n\n #unregisterWatch(watch: WatchHandle): void {\n switch (watch.kind) {\n case \"event\":\n removeFromSetMap(this.#idWatches, watch.key, watch);\n if (this.#eventCache.get(watch.key) === watch) {\n this.#eventCache.delete(watch.key);\n }\n return;\n case \"replaceable\":\n removeFromSetMap(this.#addressWatches, watch.key, watch);\n if (this.#addressCache.get(watch.key) === watch) {\n this.#addressCache.delete(watch.key);\n }\n return;\n case \"query\": {\n const kinds = this.#queryKinds(watch);\n if (kinds === undefined) {\n this.#queryAnyKind.delete(watch);\n } else {\n for (const kind of kinds) {\n removeFromSetMap(this.#queryByKind, kind, watch);\n }\n }\n if (this.#queryCache.get(watch.key) === watch) {\n this.#queryCache.delete(watch.key);\n }\n }\n }\n }\n\n /**\n * Kind buckets a query watch belongs to (deduped across filters), or undefined when any filter\n * lacks a non-empty `kinds` and so can match every kind.\n */\n #queryKinds(watch: WatchHandle): Set<number> | undefined {\n const kinds = new Set<number>();\n for (const filter of watch.filters ?? []) {\n if (filter.kinds === undefined || filter.kinds.length === 0) {\n return undefined;\n }\n for (const kind of filter.kinds) {\n kinds.add(kind);\n }\n }\n return kinds;\n }\n\n #touch(id: string): void {\n this.#recency.delete(id);\n this.#recency.add(id);\n }\n\n #recordSeen(id: string, relayUrl: string): void {\n const url = normalizeURL(relayUrl);\n let urls = this.#seenOn.get(id);\n if (!urls) {\n urls = [];\n this.#seenOn.set(id, urls);\n }\n if (!urls.includes(url) && urls.length < SEEN_ON_PER_ID) {\n urls.push(url);\n }\n trimOldest(this.#seenOn, this.#maxSeenOnEntries);\n }\n\n #onInsert(event: Event): void {\n this.#version += 1;\n this.#touch(event.id);\n this.#invalidateByEvent(event);\n this.#events.emit(\"insert\", event);\n }\n\n #onRemove(event: Event): void {\n this.#version += 1;\n this.#recency.delete(event.id);\n this.#invalidateByEvent(event);\n this.#events.emit(\"remove\", event);\n }\n\n #invalidateByEvent(event: Event): void {\n const byId = this.#idWatches.get(event.id);\n if (byId) {\n for (const watch of byId) {\n this.#markDirty(watch);\n }\n }\n const address = eventAddress(event);\n if (address !== undefined) {\n const byAddress = this.#addressWatches.get(address);\n if (byAddress) {\n for (const watch of byAddress) {\n this.#markDirty(watch);\n }\n }\n }\n // A kind-5 deletion marks its targets tombstoned even when they are not in\n // the index, so nothing else invalidates a watch keyed on the target.\n if (event.kind === Kind.EventDeletion) {\n for (const tag of event.tags) {\n if (tag[0] === \"e\" && tag[1] !== undefined) {\n const watches = this.#idWatches.get(tag[1].toLowerCase());\n if (watches) {\n for (const watch of watches) {\n this.#markDirty(watch);\n }\n }\n } else if (tag[0] === \"a\" && tag[1] !== undefined) {\n const coord = parseEventAddress(tag[1]);\n if (coord === undefined) {\n continue;\n }\n const watches = this.#addressWatches.get(\n formatEventAddress(coord.kind, coord.pubkey, coord.identifier),\n );\n if (watches) {\n for (const watch of watches) {\n this.#markDirty(watch);\n }\n }\n }\n }\n }\n // Candidates are the event's kind bucket plus any-kind watches — a watch sits\n // in at most one bucket per kind, so it is checked at most once per event.\n const byKind = this.#queryByKind.get(event.kind);\n if (byKind) {\n for (const watch of byKind) {\n if (watch.filters !== undefined && matchFilters(watch.filters, event)) {\n this.#markDirty(watch);\n }\n }\n }\n for (const watch of this.#queryAnyKind) {\n if (watch.filters !== undefined && matchFilters(watch.filters, event)) {\n this.#markDirty(watch);\n }\n }\n }\n\n #invalidateAll(): void {\n for (const watches of this.#idWatches.values()) {\n for (const watch of watches) {\n this.#markDirty(watch);\n }\n }\n for (const watches of this.#addressWatches.values()) {\n for (const watch of watches) {\n this.#markDirty(watch);\n }\n }\n for (const watches of this.#queryByKind.values()) {\n for (const watch of watches) {\n this.#markDirty(watch);\n }\n }\n for (const watch of this.#queryAnyKind) {\n this.#markDirty(watch);\n }\n this.#scheduleFlush();\n }\n\n #markDirty(watch: WatchHandle): void {\n watch.markDirty();\n this.#dirty.add(watch);\n this.#scheduleFlush();\n }\n\n #scheduleFlush(): void {\n if (this.#flushScheduled) {\n return;\n }\n this.#flushScheduled = true;\n queueMicrotask(() => {\n // Keep the flag set while flushing: writes re-entered from a\n // subscriber land in #dirty and are notified in the same pass.\n while (this.#dirty.size > 0) {\n const batch = [...this.#dirty];\n this.#dirty.clear();\n for (const watch of batch) {\n watch.notify();\n }\n }\n this.#flushScheduled = false;\n });\n }\n\n #pin(ids: ReadonlyArray<string>): void {\n for (const id of ids) {\n this.#pinned.set(id, (this.#pinned.get(id) ?? 0) + 1);\n }\n }\n\n #unpin(ids: ReadonlyArray<string>): void {\n for (const id of ids) {\n const count = (this.#pinned.get(id) ?? 0) - 1;\n if (count <= 0) {\n this.#pinned.delete(id);\n } else {\n this.#pinned.set(id, count);\n }\n }\n }\n\n #evictIfNeeded(protectedId?: string): void {\n if (this.#index.size <= this.#maxEvents) {\n return;\n }\n const evicting: string[] = [];\n for (const id of this.#recency) {\n if (this.#index.size - evicting.length <= this.#maxEvents) {\n break;\n }\n if (this.#pinned.has(id) || id === protectedId) {\n continue;\n }\n const event = this.#index.get(id);\n if (event === undefined) {\n continue;\n }\n // Replaceable/addressable winners evict like any other event; the index\n // records a watermark so stale versions stay rejected afterwards.\n evicting.push(id);\n }\n this.#index.evict(evicting);\n for (const id of evicting) {\n this.#recency.delete(id);\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { t as Event } from "./event-
|
|
2
|
-
import { t as Filter } from "./filter-
|
|
3
|
-
import { i as PutResult } from "./types-
|
|
1
|
+
import { t as Event } from "./event-DJeb_DIL.mjs";
|
|
2
|
+
import { t as Filter } from "./filter-jI_9htF7.mjs";
|
|
3
|
+
import { i as PutResult } from "./types-BacwnDtU.mjs";
|
|
4
4
|
//#region src/store/reactive.d.ts
|
|
5
5
|
/** A reactive snapshot source compatible with `useSyncExternalStore`. */
|
|
6
6
|
type Watch<T> = {
|
|
@@ -10,23 +10,18 @@ type Watch<T> = {
|
|
|
10
10
|
/** Capacity options for {@link ReactiveEventStore}. */
|
|
11
11
|
type ReactiveEventStoreOptions = {
|
|
12
12
|
/** Max stored events before LRU eviction. Default 50_000. */
|
|
13
|
-
maxEvents?: number;
|
|
13
|
+
maxEvents?: number | undefined;
|
|
14
14
|
/** Max ids tracked by `seenOn`. Default 20_000. */
|
|
15
|
-
maxSeenOnEntries?: number;
|
|
15
|
+
maxSeenOnEntries?: number | undefined;
|
|
16
16
|
/** FIFO cap on tombstoned deletion ids. Default 100_000. */
|
|
17
|
-
maxTombstones?: number;
|
|
17
|
+
maxTombstones?: number | undefined;
|
|
18
18
|
};
|
|
19
|
-
/**
|
|
20
|
-
type
|
|
21
|
-
/**
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
readonly filters: ReadonlyArray<Filter> | undefined;
|
|
26
|
-
readonly subscribed: boolean;
|
|
27
|
-
readonly pinnedIds: ReadonlyArray<string>;
|
|
28
|
-
_markDirty: () => void;
|
|
29
|
-
_notify: () => void;
|
|
19
|
+
/** Typed event payloads for {@link ReactiveEventStore.on}. */
|
|
20
|
+
type ReactiveEventStoreEventMap = {
|
|
21
|
+
/** Every physical index insert, fired synchronously after the update. */
|
|
22
|
+
insert: Event;
|
|
23
|
+
/** Every physical index remove, fired synchronously after watch invalidation. */
|
|
24
|
+
remove: Event;
|
|
30
25
|
};
|
|
31
26
|
/**
|
|
32
27
|
* Synchronous reactive in-memory event store backed by {@link MemoryIndex}. The single read source
|
|
@@ -36,7 +31,6 @@ type WatchHandle = {
|
|
|
36
31
|
*/
|
|
37
32
|
declare class ReactiveEventStore {
|
|
38
33
|
#private;
|
|
39
|
-
_version: number;
|
|
40
34
|
constructor(opts?: ReactiveEventStoreOptions);
|
|
41
35
|
add(event: Event, relayUrl?: string): PutResult;
|
|
42
36
|
addMany(events: ReadonlyArray<Event>, relayUrl?: string): PutResult[];
|
|
@@ -56,13 +50,13 @@ declare class ReactiveEventStore {
|
|
|
56
50
|
watchEvent(id: string): Watch<Event | undefined>;
|
|
57
51
|
watchReplaceable(kind: number, pubkey: string, d?: string): Watch<Event | undefined>;
|
|
58
52
|
watchQuery(filters: ReadonlyArray<Filter>): Watch<ReadonlyArray<Event>>;
|
|
59
|
-
/**
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
53
|
+
/**
|
|
54
|
+
* Listen for a store event. Multiple listeners per type are allowed and fire in registration
|
|
55
|
+
* order; a throwing listener is reported and does not break the dispatch. Returns an unsubscribe
|
|
56
|
+
* function.
|
|
57
|
+
*/
|
|
58
|
+
on<K extends keyof ReactiveEventStoreEventMap>(type: K, listener: (payload: ReactiveEventStoreEventMap[K]) => void): () => void;
|
|
65
59
|
}
|
|
66
60
|
//#endregion
|
|
67
|
-
export {
|
|
68
|
-
//# sourceMappingURL=reactive-
|
|
61
|
+
export { Watch as i, ReactiveEventStoreEventMap as n, ReactiveEventStoreOptions as r, ReactiveEventStore as t };
|
|
62
|
+
//# sourceMappingURL=reactive-gGqUrzW8.d.mts.map
|