@qntx/nostr 0.8.0 → 0.10.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/LICENSE-APACHE +201 -0
- package/README.md +9 -19
- package/dist/{builder-aNU2gGFP.mjs → builder-CVRmUeNm.mjs} +4 -4
- package/dist/{builder-aNU2gGFP.mjs.map → builder-CVRmUeNm.mjs.map} +1 -1
- package/dist/{builder-CTwkB2zM.d.mts → builder-GBddxj8i.d.mts} +3 -3
- package/dist/{client-Cj2lUaVh.mjs → client-CeyDLoyO.mjs} +50 -28
- package/dist/client-CeyDLoyO.mjs.map +1 -0
- package/dist/client.d.mts +1 -1
- package/dist/client.mjs +1 -1
- package/dist/core.d.mts +7 -8
- package/dist/core.mjs +8 -8
- package/dist/{event-CHf47dPM.mjs → event-C2eLiPpV.mjs} +15 -5
- package/dist/event-C2eLiPpV.mjs.map +1 -0
- package/dist/{event-DJeb_DIL.d.mts → event-j3BwI5dF.d.mts} +2 -4
- package/dist/{filter-jI_9htF7.d.mts → filter-CfEgQBXt.d.mts} +3 -5
- package/dist/{filter-BQl3GlHt.mjs → filter-TrF2LEoy.mjs} +3 -36
- package/dist/filter-TrF2LEoy.mjs.map +1 -0
- package/dist/{gossip-DFxIBlsr.mjs → gossip-5ezg0Quo.mjs} +3 -3
- package/dist/gossip-5ezg0Quo.mjs.map +1 -0
- package/dist/{gossip-OOeeFzG5.d.mts → gossip-BWb9HmfK.d.mts} +8 -5
- package/dist/gossip.d.mts +1 -1
- package/dist/gossip.mjs +1 -1
- package/dist/http-CuazNRIP.mjs.map +1 -1
- package/dist/{http-C4HwIu4B.d.mts → http-kwWG-V1X.d.mts} +9 -3
- package/dist/{index-CPVEyzNX.d.mts → index-B1fLejg4.d.mts} +9 -9
- package/dist/{index-C_w2WfVz.d.mts → index-C0mFpelb.d.mts} +6 -6
- package/dist/{index-DyKwQnbt.d.mts → index-CLJEKFGd.d.mts} +4 -4
- package/dist/{index-BxCBX-8R.d.mts → index-CoX7SnO7.d.mts} +7 -4
- package/dist/{index-DU9tRFTZ.d.mts → index-Hp26bgYG.d.mts} +11 -4
- package/dist/{index-Cl_1XdYP.d.mts → index-uCYwXaaP.d.mts} +22 -14
- package/dist/index.d.mts +18 -19
- package/dist/index.mjs +17 -17
- package/dist/{key-D_5OgGT7.d.mts → key-CyKN1RTi.d.mts} +2 -2
- package/dist/{key-DnVpchl6.mjs → key-DY_HEIpY.mjs} +5 -4
- package/dist/key-DY_HEIpY.mjs.map +1 -0
- package/dist/{kind-Cxwhhkx8.mjs → kind-D8fENiiL.mjs} +11 -5
- package/dist/kind-D8fENiiL.mjs.map +1 -0
- package/dist/{loaders-BmPkQfzI.mjs → loaders-DifimjJ7.mjs} +9 -8
- package/dist/{loaders-BmPkQfzI.mjs.map → loaders-DifimjJ7.mjs.map} +1 -1
- package/dist/loaders.d.mts +2 -2
- package/dist/loaders.mjs +1 -1
- package/dist/{memory-CdJ07kub.mjs → memory-DENGQ_f6.mjs} +2 -2
- package/dist/{memory-CdJ07kub.mjs.map → memory-DENGQ_f6.mjs.map} +1 -1
- package/dist/{memory-index-Cbc83vOZ.mjs → memory-index-D_lvlYAy.mjs} +4 -4
- package/dist/{memory-index-Cbc83vOZ.mjs.map → memory-index-D_lvlYAy.mjs.map} +1 -1
- package/dist/{message-oNr7t0SJ.mjs → message-Rd5Z_17h.mjs} +5 -4
- package/dist/{message-oNr7t0SJ.mjs.map → message-Rd5Z_17h.mjs.map} +1 -1
- package/dist/{nip17-B5WgW4C4.d.mts → nip17-B7MI82Iq.d.mts} +4 -4
- package/dist/{nip51-CR0Q8eym.d.mts → nip51-O_vhOiK2.d.mts} +3 -3
- package/dist/{nip59-C-RWFQIv.d.mts → nip59-CdDoJptA.d.mts} +2 -2
- package/dist/{nip65-D1fbmhOg.d.mts → nip65-BL79HI8N.d.mts} +3 -3
- package/dist/{nip77-DzUwUxHq.d.mts → nip77-wHA_nEV5.d.mts} +2 -2
- package/dist/nips/blossom.d.mts +3 -3
- package/dist/nips/blossom.mjs +2 -2
- package/dist/nips/nip05.d.mts +1 -1
- package/dist/nips/nip10.d.mts +2 -2
- package/dist/nips/nip10.mjs +3 -3
- package/dist/nips/nip11.d.mts +1 -1
- package/dist/nips/nip13.d.mts +1 -1
- package/dist/nips/nip17.d.mts +1 -1
- package/dist/nips/nip17.mjs +3 -3
- package/dist/nips/nip27.d.mts +1 -1
- package/dist/nips/nip42.d.mts +1 -1
- package/dist/nips/nip42.mjs +1 -1
- package/dist/nips/nip51.d.mts +1 -1
- package/dist/nips/nip51.mjs +3 -3
- package/dist/nips/nip57.d.mts +1 -1
- package/dist/nips/nip57.mjs +3 -3
- package/dist/nips/nip59.d.mts +1 -1
- package/dist/nips/nip59.mjs +4 -4
- package/dist/nips/nip65.d.mts +1 -1
- package/dist/nips/nip65.mjs +2 -2
- package/dist/nips/nip77.d.mts +1 -1
- package/dist/nips/nip77.mjs +8 -5
- package/dist/nips/nip77.mjs.map +1 -1
- package/dist/nips/nip98.d.mts +1 -1
- package/dist/nips/nip98.mjs +3 -3
- package/dist/{pool-CqQvUnsq.d.mts → pool-Bfe3Tu40.d.mts} +7 -7
- package/dist/{pool-vlw74C4t.mjs → pool-jok2-iBJ.mjs} +28 -21
- package/dist/pool-jok2-iBJ.mjs.map +1 -0
- package/dist/{put-w13ci3sC.mjs → put-JsiCKMyZ.mjs} +4 -4
- package/dist/put-JsiCKMyZ.mjs.map +1 -0
- package/dist/{reactive-Tz0otDIP.mjs → reactive-6Wn9qf_d.mjs} +5 -5
- package/dist/{reactive-Tz0otDIP.mjs.map → reactive-6Wn9qf_d.mjs.map} +1 -1
- package/dist/{reactive-gGqUrzW8.d.mts → reactive-X4p6nABy.d.mts} +4 -4
- package/dist/{relay-quCs7MHD.mjs → relay-__QtO33h.mjs} +18 -10
- package/dist/relay-__QtO33h.mjs.map +1 -0
- package/dist/relay.d.mts +3 -3
- package/dist/relay.mjs +2 -2
- package/dist/{signer-poTGe6Er.mjs → signer-D7PtVvQn.mjs} +14 -7
- package/dist/signer-D7PtVvQn.mjs.map +1 -0
- package/dist/signer.d.mts +2 -2
- package/dist/signer.mjs +1 -1
- package/dist/{storage-B5IXTVuS.mjs → storage-oihjE0_x.mjs} +10 -10
- package/dist/{storage-B5IXTVuS.mjs.map → storage-oihjE0_x.mjs.map} +1 -1
- package/dist/storage.d.mts +2 -2
- package/dist/storage.mjs +3 -3
- package/dist/store.d.mts +1 -1
- package/dist/store.mjs +1 -1
- package/dist/testing.d.mts +8 -2
- package/dist/testing.mjs +32 -10
- package/dist/testing.mjs.map +1 -1
- package/dist/{types-DNmiscfd.d.mts → types-BJ4wZ7JJ.d.mts} +2 -2
- package/dist/{types-BacwnDtU.d.mts → types-Ccox7-5v.d.mts} +3 -3
- package/dist/{message-tclYCVNc.d.mts → verifier-9c-bINrv.d.mts} +23 -4
- package/dist/{verifier-B51Wkt5H.mjs → verifier-uC_jd-Nw.mjs} +3 -3
- package/dist/verifier-uC_jd-Nw.mjs.map +1 -0
- package/package.json +25 -50
- package/dist/client-Cj2lUaVh.mjs.map +0 -1
- package/dist/event-CHf47dPM.mjs.map +0 -1
- package/dist/filter-BQl3GlHt.mjs.map +0 -1
- package/dist/gossip-DFxIBlsr.mjs.map +0 -1
- package/dist/instance-C62w3cEt.mjs +0 -220
- package/dist/instance-C62w3cEt.mjs.map +0 -1
- package/dist/instance-DjsL8h84.d.mts +0 -15
- package/dist/key-DnVpchl6.mjs.map +0 -1
- package/dist/kind-Cxwhhkx8.mjs.map +0 -1
- package/dist/nostr_crypto_wasm_bg-Czrdty7Q.mjs +0 -4
- package/dist/nostr_crypto_wasm_bg.wasm +0 -0
- package/dist/pool-vlw74C4t.mjs.map +0 -1
- package/dist/put-w13ci3sC.mjs.map +0 -1
- package/dist/relay-quCs7MHD.mjs.map +0 -1
- package/dist/signer-poTGe6Er.mjs.map +0 -1
- package/dist/verifier-B51Wkt5H.mjs.map +0 -1
- package/dist/verifier-CgTFpgsC.d.mts +0 -22
- package/dist/wasm.browser.d.mts +0 -8
- package/dist/wasm.browser.mjs +0 -19
- package/dist/wasm.browser.mjs.map +0 -1
- package/dist/wasm.d.mts +0 -8
- package/dist/wasm.mjs +0 -28
- package/dist/wasm.mjs.map +0 -1
- /package/{LICENSE → LICENSE-MIT} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory-
|
|
1
|
+
{"version":3,"file":"memory-DENGQ_f6.mjs","names":[],"sources":["../src/storage/memory.ts"],"sourcesContent":["import type { Event } from \"../core/event.ts\";\nimport type { Filter } from \"../core/filter.ts\";\nimport { MemoryIndex } from \"./memory-index.ts\";\nimport type { EventStore, NegentropyItem, OutboxBound, PutResult } from \"./types.ts\";\n\n/** In-memory event store: async {@link EventStore} facade over the synchronous {@link MemoryIndex}. */\nexport class MemoryEventStore implements EventStore {\n readonly #index = new MemoryIndex();\n\n async put(raw: Event): Promise<PutResult> {\n return this.#index.put(raw);\n }\n\n /** Sequential `put` in input order. No transaction: a throw leaves earlier events applied. */\n async putMany(events: ReadonlyArray<Event>): Promise<PutResult[]> {\n const results: PutResult[] = [];\n for (const event of events) {\n // oxlint-disable-next-line no-await-in-loop -- putMany applies puts sequentially in input order\n results.push(await this.put(event));\n }\n return results;\n }\n\n async get(id: string): Promise<Event | undefined> {\n return this.#index.get(id);\n }\n\n async query(filters: ReadonlyArray<Filter>): Promise<Event[]> {\n return this.#index.query(filters);\n }\n\n async count(filters: ReadonlyArray<Filter>): Promise<number> {\n return this.#index.count(filters);\n }\n\n async negentropyItems(filter: Filter): Promise<NegentropyItem[]> {\n return this.#index.negentropyItems(filter);\n }\n\n async remove(ids: ReadonlyArray<string>): Promise<number> {\n return this.#index.remove(ids);\n }\n\n async getOutboxBound(pubkey: string, kind: number): Promise<OutboxBound | undefined> {\n return this.#index.getOutboxBound(pubkey, kind);\n }\n\n async setOutboxBound(pubkey: string, kind: number, bound: OutboxBound): Promise<void> {\n this.#index.setOutboxBound(pubkey, kind, bound);\n }\n\n async clear(): Promise<void> {\n this.#index.clear();\n }\n\n get size(): number {\n return this.#index.size;\n }\n}\n"],"mappings":";;;AAMA,IAAa,mBAAb,MAAoD;CAClD,SAAkB,IAAI,YAAY;CAElC,MAAM,IAAI,KAAgC;EACxC,OAAO,KAAK,OAAO,IAAI,GAAG;CAC5B;;CAGA,MAAM,QAAQ,QAAoD;EAChE,MAAM,UAAuB,CAAC;EAC9B,KAAK,MAAM,SAAS,QAElB,QAAQ,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC;EAEpC,OAAO;CACT;CAEA,MAAM,IAAI,IAAwC;EAChD,OAAO,KAAK,OAAO,IAAI,EAAE;CAC3B;CAEA,MAAM,MAAM,SAAkD;EAC5D,OAAO,KAAK,OAAO,MAAM,OAAO;CAClC;CAEA,MAAM,MAAM,SAAiD;EAC3D,OAAO,KAAK,OAAO,MAAM,OAAO;CAClC;CAEA,MAAM,gBAAgB,QAA2C;EAC/D,OAAO,KAAK,OAAO,gBAAgB,MAAM;CAC3C;CAEA,MAAM,OAAO,KAA6C;EACxD,OAAO,KAAK,OAAO,OAAO,GAAG;CAC/B;CAEA,MAAM,eAAe,QAAgB,MAAgD;EACnF,OAAO,KAAK,OAAO,eAAe,QAAQ,IAAI;CAChD;CAEA,MAAM,eAAe,QAAgB,MAAc,OAAmC;EACpF,KAAK,OAAO,eAAe,QAAQ,MAAM,KAAK;CAChD;CAEA,MAAM,QAAuB;EAC3B,KAAK,OAAO,MAAM;CACpB;CAEA,IAAI,OAAe;EACjB,OAAO,KAAK,OAAO;CACrB;AACF"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as matchFilter } from "./filter-
|
|
1
|
+
import { S as parseEventAddress, _ as eventAddress, f as sortEvents, o as itemCompare, t as compareEventsDesc, y as formatEventAddress } from "./event-C2eLiPpV.mjs";
|
|
2
|
+
import { a as matchFilter } from "./filter-TrF2LEoy.mjs";
|
|
3
3
|
import { i as trimOldest, n as removeFromSetMap, t as addToSetMap } from "./collections-DtwMc1NU.mjs";
|
|
4
|
-
import { i as DeletionState, n as decidePut, r as outboxBoundKey, t as applyPutMemory } from "./put-
|
|
4
|
+
import { i as DeletionState, n as decidePut, r as outboxBoundKey, t as applyPutMemory } from "./put-JsiCKMyZ.mjs";
|
|
5
5
|
//#region src/storage/memory-index.ts
|
|
6
6
|
/**
|
|
7
7
|
* Synchronous in-memory event index with NIP-01 replaceable / addressable / ephemeral handling and
|
|
@@ -371,4 +371,4 @@ function visitEpTagIds(byEpTag, byId, name, values, seen, visit) {
|
|
|
371
371
|
//#endregion
|
|
372
372
|
export { MemoryIndex as t };
|
|
373
373
|
|
|
374
|
-
//# sourceMappingURL=memory-index-
|
|
374
|
+
//# sourceMappingURL=memory-index-D_lvlYAy.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory-index-Cbc83vOZ.mjs","names":[],"sources":["../src/storage/memory-index.ts"],"sourcesContent":["import { addToSetMap, removeFromSetMap, trimOldest } from \"../core/collections.ts\";\nimport type { Event } from \"../core/event.ts\";\nimport { compareEventsDesc, itemCompare, sortEvents } from \"../core/event.ts\";\nimport type { Filter } from \"../core/filter.ts\";\nimport { matchFilter } from \"../core/filter.ts\";\nimport { eventAddress, formatEventAddress, parseEventAddress } from \"../core/tag.ts\";\nimport { DeletionState } from \"./deletion.ts\";\nimport { applyPutMemory, decidePut, outboxBoundKey } from \"./put.ts\";\nimport type { PutLookup } from \"./put.ts\";\nimport type { NegentropyItem, OutboxBound, PutResult } from \"./types.ts\";\n\nexport type MemoryIndexOptions = {\n /**\n * FIFO cap applied independently to each deletion-state collection: tombstoned event ids, pending\n * e-tag ids, and coordinate tombstones. Default unbounded. Trade-off: once an entry is trimmed, a\n * re-arriving old deleted event or replaceable version can be accepted again.\n */\n maxTombstones?: number | undefined;\n /**\n * FIFO cap on replaceable/addressable winner watermarks recorded by {@link evict}. A watermark\n * keeps only `{ id, created_at }` per address so stale versions stay rejected after the winner's\n * body is evicted, and a re-put of the watermarked id re-inserts it. Default 0 (no watermark\n * retention); callers that evict should pass a bound. Once a watermark is trimmed, an older\n * evicted version can be accepted again — the same trade-off as deletion tombstones.\n */\n maxWatermarks?: number | undefined;\n /** Fires after every physical index insert (accept, replace, deletion event). */\n onInsert?: ((event: Event) => void) | undefined;\n /** Fires after every physical index remove (replace, delete, evict, remove, clear). */\n onRemove?: ((event: Event) => void) | undefined;\n};\n\n/**\n * Synchronous in-memory event index with NIP-01 replaceable / addressable / ephemeral handling and\n * NIP-09 deletion (kind 5) application. Shared by {@link MemoryEventStore} (async facade) and\n * `ReactiveEventStore`.\n */\nexport class MemoryIndex {\n readonly #byId = new Map<string, Event>();\n readonly #byPubkey = new Map<string, Set<string>>();\n readonly #byKind = new Map<number, Set<string>>();\n readonly #byKindPubkey = new Map<string, Set<string>>(); // `${kind}:${pubkey}` → ids\n readonly #byEpTag = new Map<string, Set<string>>(); // `${\"e\"|\"p\"}:${value.toLowerCase()}` → ids\n readonly #replaceable = new Map<string, string>(); // address -> event id\n // address -> last evicted winner; insertion order is the FIFO trim order\n readonly #watermarks = new Map<string, { id: string; created_at: number }>();\n // winner id -> address reverse index for O(1) watermark drops on deletion\n readonly #watermarkIds = new Map<string, string>();\n readonly #deletion = new DeletionState();\n readonly #outboxBounds = new Map<string, OutboxBound>();\n readonly #maxTombstones: number | undefined;\n readonly #maxWatermarks: number;\n readonly #onInsert: ((event: Event) => void) | undefined;\n readonly #onRemove: ((event: Event) => void) | undefined;\n\n constructor(opts?: MemoryIndexOptions) {\n this.#maxTombstones = opts?.maxTombstones;\n this.#maxWatermarks = opts?.maxWatermarks ?? 0;\n this.#onInsert = opts?.onInsert;\n this.#onRemove = opts?.onRemove;\n }\n\n put(raw: Event): PutResult {\n const lookup: PutLookup = {\n deletion: this.#deletion,\n getById: (id) => this.#byId.get(id),\n getReplaceable: (addr) => {\n const id = this.#replaceable.get(addr);\n const ev = id === undefined ? undefined : this.#byId.get(id);\n if (ev) {\n return { id: ev.id, created_at: ev.created_at };\n }\n const watermark = this.#watermarks.get(addr);\n return watermark === undefined ? undefined : { ...watermark, evicted: true };\n },\n };\n const decision = decidePut(raw, lookup);\n if (decision.action === \"delete\") {\n // Pending e-tag targets and coordinate tombstones never reach\n // indexRemove — drop their watermarks here.\n for (const p of decision.plan.pendingIds) {\n this.#dropWatermarkId(p.id);\n }\n for (const c of decision.plan.coordinates) {\n this.#dropWatermark(c.key);\n }\n }\n const result = applyPutMemory(\n {\n deletion: this.#deletion,\n indexInsert: (e) => this.#indexInsert(e),\n indexRemove: (id) => this.#indexRemove(id),\n },\n decision,\n );\n this.#trimTombstones();\n return result;\n }\n\n /** Sequential `put` in input order. */\n putMany(events: ReadonlyArray<Event>): PutResult[] {\n const results: PutResult[] = [];\n for (const event of events) {\n results.push(this.put(event));\n }\n return results;\n }\n\n get(id: string): Event | undefined {\n const key = id.toLowerCase();\n if (this.#deletion.ids.has(key)) {\n return undefined;\n }\n return this.#byId.get(key);\n }\n\n /** Current event at a `kind:pubkey:d` coordinate (replaceable or addressable). */\n getByAddress(address: string): Event | undefined {\n const coord = parseEventAddress(address);\n if (!coord) {\n return undefined;\n }\n const id = this.#replaceable.get(\n formatEventAddress(coord.kind, coord.pubkey, coord.identifier),\n );\n if (id === undefined) {\n return undefined;\n }\n if (this.#deletion.ids.has(id)) {\n return undefined;\n }\n return this.#byId.get(id);\n }\n\n query(filters: ReadonlyArray<Filter>): Event[] {\n const seen = new Set<string>();\n const events: Event[] = [];\n for (const filter of filters) {\n for (const event of this.#matchedEvents(filter)) {\n if (seen.has(event.id)) {\n continue;\n }\n seen.add(event.id);\n events.push(event);\n }\n }\n sortEvents(events);\n return events;\n }\n\n count(filters: ReadonlyArray<Filter>): number {\n const seen = new Set<string>();\n for (const filter of filters) {\n for (const event of this.#matchedEvents(filter)) {\n seen.add(event.id);\n }\n }\n return seen.size;\n }\n\n negentropyItems(filter: Filter): NegentropyItem[] {\n if (filter.limit === 0) {\n return [];\n }\n const items: NegentropyItem[] = [];\n this.#eachCandidate(filter, (event) => {\n if (this.#deletion.covers(event)) {\n return;\n }\n if (!matchFilter(filter, event)) {\n return;\n }\n items.push({ id: event.id, created_at: event.created_at });\n });\n if (filter.limit !== undefined) {\n items.sort(compareEventsDesc);\n if (items.length > filter.limit) {\n items.length = filter.limit;\n }\n }\n items.sort(itemCompare);\n return items;\n }\n\n /** Remove by id and tombstone (like a local NIP-09). Returns removed count. */\n remove(ids: ReadonlyArray<string>): number {\n let n = 0;\n for (const raw of ids) {\n const id = raw.toLowerCase();\n if (this.#indexRemove(id)) {\n n += 1;\n }\n this.#deletion.ids.add(id);\n this.#deletion.pending.delete(id);\n }\n this.#trimTombstones();\n return n;\n }\n\n /**\n * Remove by id without writing a tombstone (LRU eviction). When the evicted event is the current\n * winner of a replaceable/addressable address, a `{ id, created_at }` watermark is recorded so\n * stale versions stay rejected while the body is gone; the watermarks are FIFO-bounded by\n * `maxWatermarks`.\n */\n evict(ids: ReadonlyArray<string>): number {\n let n = 0;\n for (const raw of ids) {\n const id = raw.toLowerCase();\n const event = this.#byId.get(id);\n if (event === undefined) {\n continue;\n }\n const addr = eventAddress(event);\n const winner = addr !== undefined && this.#replaceable.get(addr) === id;\n if (this.#indexRemove(id)) {\n n += 1;\n }\n if (winner) {\n this.#setWatermark(addr, { id, created_at: event.created_at });\n }\n }\n return n;\n }\n\n /**\n * True when the id is tombstoned, or the coordinate has a deletion marker that still covers the\n * current event at that address: a replacement published after the marker's `until` clears the\n * deletion. Coordinates are matched on the canonical lowercase pubkey.\n */\n isDeleted(idOrAddress: string): boolean {\n if (this.#deletion.ids.has(idOrAddress.toLowerCase())) {\n return true;\n }\n const coord = parseEventAddress(idOrAddress);\n if (!coord) {\n return false;\n }\n const address = formatEventAddress(coord.kind, coord.pubkey, coord.identifier);\n const until = this.#deletion.coordinates.get(address);\n if (until === undefined) {\n return false;\n }\n const id = this.#replaceable.get(address);\n if (id === undefined) {\n return true;\n }\n const event = this.#byId.get(id);\n return event === undefined || event.created_at <= until;\n }\n\n getOutboxBound(pubkey: string, kind: number): OutboxBound | undefined {\n const persisted = this.#outboxBounds.get(outboxBoundKey(pubkey, kind));\n if (persisted) {\n return { oldest: persisted.oldest, newest: persisted.newest };\n }\n return this.#deriveOutboxBound(pubkey, kind);\n }\n\n setOutboxBound(pubkey: string, kind: number, bound: OutboxBound): void {\n this.#outboxBounds.set(outboxBoundKey(pubkey, kind), {\n oldest: bound.oldest,\n newest: bound.newest,\n });\n }\n\n clear(): void {\n if (this.#onRemove) {\n for (const event of this.#byId.values()) {\n this.#onRemove(event);\n }\n }\n this.#byId.clear();\n this.#byPubkey.clear();\n this.#byKind.clear();\n this.#byKindPubkey.clear();\n this.#byEpTag.clear();\n this.#replaceable.clear();\n this.#watermarks.clear();\n this.#watermarkIds.clear();\n this.#deletion.clear();\n this.#outboxBounds.clear();\n }\n\n get size(): number {\n return this.#byId.size;\n }\n\n #indexInsert(event: Event): void {\n this.#byId.set(event.id, event);\n const { pubkey } = event;\n addToSetMap(this.#byPubkey, pubkey, event.id);\n addToSetMap(this.#byKind, event.kind, event.id);\n addToSetMap(this.#byKindPubkey, `${event.kind}:${pubkey}`, event.id);\n for (const tag of event.tags) {\n if ((tag[0] !== \"e\" && tag[0] !== \"p\") || tag[1] === undefined) {\n continue;\n }\n addToSetMap(this.#byEpTag, `${tag[0]}:${tag[1].toLowerCase()}`, event.id);\n }\n const addr = eventAddress(event);\n if (addr !== undefined) {\n this.#replaceable.set(addr, event.id);\n this.#dropWatermark(addr);\n }\n this.#onInsert?.(event);\n }\n\n #indexRemove(id: string): boolean {\n // A removed/deleted id must not keep a stale watermark alive; eviction\n // re-records its winner watermark right after this call.\n this.#dropWatermarkId(id);\n const event = this.#byId.get(id);\n if (!event) {\n return false;\n }\n this.#byId.delete(id);\n const { pubkey } = event;\n removeFromSetMap(this.#byPubkey, pubkey, id);\n removeFromSetMap(this.#byKind, event.kind, id);\n removeFromSetMap(this.#byKindPubkey, `${event.kind}:${pubkey}`, id);\n for (const tag of event.tags) {\n if ((tag[0] !== \"e\" && tag[0] !== \"p\") || tag[1] === undefined) {\n continue;\n }\n removeFromSetMap(this.#byEpTag, `${tag[0]}:${tag[1].toLowerCase()}`, id);\n }\n const addr = eventAddress(event);\n if (addr !== undefined && this.#replaceable.get(addr) === id) {\n this.#replaceable.delete(addr);\n }\n this.#onRemove?.(event);\n return true;\n }\n\n #matchedEvents(filter: Filter): Event[] {\n if (filter.limit === 0) {\n return [];\n }\n const matched: Event[] = [];\n this.#eachCandidate(filter, (event) => {\n if (this.#deletion.covers(event)) {\n return;\n }\n if (!matchFilter(filter, event)) {\n return;\n }\n matched.push(event);\n });\n sortEvents(matched);\n return filter.limit === undefined ? matched : matched.slice(0, filter.limit);\n }\n\n #deriveOutboxBound(pubkey: string, kind: number): OutboxBound | undefined {\n const byPk = this.#byPubkey.get(pubkey.toLowerCase());\n const byKind = this.#byKind.get(kind);\n if (!byPk || !byKind) {\n return undefined;\n }\n let oldest: number | undefined;\n let newest: number | undefined;\n for (const id of byPk) {\n if (!byKind.has(id) || this.#deletion.ids.has(id)) {\n continue;\n }\n const event = this.#byId.get(id);\n if (!event || this.#deletion.covers(event)) {\n continue;\n }\n if (oldest === undefined || event.created_at < oldest) {\n oldest = event.created_at;\n }\n if (newest === undefined || event.created_at > newest) {\n newest = event.created_at;\n }\n }\n if (oldest === undefined || newest === undefined) {\n return undefined;\n }\n return { oldest, newest };\n }\n\n #eachCandidate(filter: Filter, visit: (event: Event) => void): void {\n if (filter.ids) {\n const seen = new Set<string>();\n for (const raw of filter.ids) {\n const event = this.#byId.get(raw.toLowerCase());\n if (!event || seen.has(event.id)) {\n continue;\n }\n seen.add(event.id);\n visit(event);\n }\n return;\n }\n\n if (filter.authors && filter.kinds) {\n const seen = new Set<string>();\n for (const pk of filter.authors) {\n const pubkey = pk.toLowerCase();\n for (const kind of filter.kinds) {\n const ids = this.#byKindPubkey.get(`${kind}:${pubkey}`);\n if (!ids) {\n continue;\n }\n for (const id of ids) {\n if (seen.has(id)) {\n continue;\n }\n seen.add(id);\n const event = this.#byId.get(id);\n if (event) {\n visit(event);\n }\n }\n }\n }\n return;\n }\n\n if (filter.authors) {\n const seen = new Set<string>();\n for (const pk of filter.authors) {\n const byPk = this.#byPubkey.get(pk.toLowerCase());\n if (!byPk) {\n continue;\n }\n for (const id of byPk) {\n if (seen.has(id)) {\n continue;\n }\n seen.add(id);\n const event = this.#byId.get(id);\n if (event) {\n visit(event);\n }\n }\n }\n return;\n }\n\n if (filter.kinds) {\n const seen = new Set<string>();\n for (const kind of filter.kinds) {\n const byKind = this.#byKind.get(kind);\n if (!byKind) {\n continue;\n }\n for (const id of byKind) {\n if (seen.has(id)) {\n continue;\n }\n seen.add(id);\n const event = this.#byId.get(id);\n if (event) {\n visit(event);\n }\n }\n }\n return;\n }\n\n const eTags = filter[\"#e\"];\n const pTags = filter[\"#p\"];\n if (eTags !== undefined || pTags !== undefined) {\n const seen = new Set<string>();\n visitEpTagIds(this.#byEpTag, this.#byId, \"e\", eTags, seen, visit);\n visitEpTagIds(this.#byEpTag, this.#byId, \"p\", pTags, seen, visit);\n return;\n }\n\n // #t/#d and other non-e/p tags are not indexed (e/p only). A generic tag\n // store is extra put/remove amp; hashtag-only queries scan #byId.\n for (const event of this.#byId.values()) {\n visit(event);\n }\n }\n\n #setWatermark(addr: string, watermark: { id: string; created_at: number }): void {\n if (this.#maxWatermarks === 0) {\n return;\n }\n this.#dropWatermark(addr);\n this.#watermarks.set(addr, watermark);\n this.#watermarkIds.set(watermark.id, addr);\n trimOldest(this.#watermarks, this.#maxWatermarks, (a) => this.#dropWatermark(a));\n }\n\n #dropWatermark(addr: string): void {\n const watermark = this.#watermarks.get(addr);\n if (watermark === undefined) {\n return;\n }\n this.#watermarks.delete(addr);\n this.#watermarkIds.delete(watermark.id);\n }\n\n #dropWatermarkId(id: string): void {\n const addr = this.#watermarkIds.get(id);\n if (addr === undefined) {\n return;\n }\n this.#watermarkIds.delete(id);\n this.#watermarks.delete(addr);\n }\n\n #trimTombstones(): void {\n const cap = this.#maxTombstones;\n if (cap === undefined) {\n return;\n }\n trimOldest(this.#deletion.ids, cap, (id) => {\n this.#deletion.pending.delete(id);\n });\n trimOldest(this.#deletion.pending, cap);\n trimOldest(this.#deletion.coordinates, cap);\n }\n}\n\nfunction visitEpTagIds(\n byEpTag: Map<string, Set<string>>,\n byId: Map<string, Event>,\n name: \"e\" | \"p\",\n values: ReadonlyArray<string> | undefined,\n seen: Set<string>,\n visit: (event: Event) => void,\n): void {\n if (values === undefined) {\n return;\n }\n for (const value of values) {\n const ids = byEpTag.get(`${name}:${value.toLowerCase()}`);\n if (!ids) {\n continue;\n }\n for (const id of ids) {\n if (seen.has(id)) {\n continue;\n }\n seen.add(id);\n const event = byId.get(id);\n if (event) {\n visit(event);\n }\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"memory-index-D_lvlYAy.mjs","names":[],"sources":["../src/storage/memory-index.ts"],"sourcesContent":["import { addToSetMap, removeFromSetMap, trimOldest } from \"../core/collections.ts\";\nimport type { Event } from \"../core/event.ts\";\nimport { compareEventsDesc, itemCompare, sortEvents } from \"../core/event.ts\";\nimport type { Filter } from \"../core/filter.ts\";\nimport { matchFilter } from \"../core/filter.ts\";\nimport { eventAddress, formatEventAddress, parseEventAddress } from \"../core/tag.ts\";\nimport { DeletionState } from \"./deletion.ts\";\nimport { applyPutMemory, decidePut, outboxBoundKey } from \"./put.ts\";\nimport type { PutLookup } from \"./put.ts\";\nimport type { NegentropyItem, OutboxBound, PutResult } from \"./types.ts\";\n\nexport type MemoryIndexOptions = {\n /**\n * FIFO cap applied independently to each deletion-state collection: tombstoned event ids, pending\n * e-tag ids, and coordinate tombstones. Default unbounded. Trade-off: once an entry is trimmed, a\n * re-arriving old deleted event or replaceable version can be accepted again.\n */\n maxTombstones?: number | undefined;\n /**\n * FIFO cap on replaceable/addressable winner watermarks recorded by {@link evict}. A watermark\n * keeps only `{ id, created_at }` per address so stale versions stay rejected after the winner's\n * body is evicted, and a re-put of the watermarked id re-inserts it. Default 0 (no watermark\n * retention); callers that evict should pass a bound. Once a watermark is trimmed, an older\n * evicted version can be accepted again — the same trade-off as deletion tombstones.\n */\n maxWatermarks?: number | undefined;\n /** Fires after every physical index insert (accept, replace, deletion event). */\n onInsert?: ((event: Event) => void) | undefined;\n /** Fires after every physical index remove (replace, delete, evict, remove, clear). */\n onRemove?: ((event: Event) => void) | undefined;\n};\n\n/**\n * Synchronous in-memory event index with NIP-01 replaceable / addressable / ephemeral handling and\n * NIP-09 deletion (kind 5) application. Shared by {@link MemoryEventStore} (async facade) and\n * `ReactiveEventStore`.\n */\nexport class MemoryIndex {\n readonly #byId = new Map<string, Event>();\n readonly #byPubkey = new Map<string, Set<string>>();\n readonly #byKind = new Map<number, Set<string>>();\n readonly #byKindPubkey = new Map<string, Set<string>>(); // `${kind}:${pubkey}` → ids\n readonly #byEpTag = new Map<string, Set<string>>(); // `${\"e\"|\"p\"}:${value.toLowerCase()}` → ids\n readonly #replaceable = new Map<string, string>(); // address -> event id\n // address -> last evicted winner; insertion order is the FIFO trim order\n readonly #watermarks = new Map<string, { id: string; created_at: number }>();\n // winner id -> address reverse index for O(1) watermark drops on deletion\n readonly #watermarkIds = new Map<string, string>();\n readonly #deletion = new DeletionState();\n readonly #outboxBounds = new Map<string, OutboxBound>();\n readonly #maxTombstones: number | undefined;\n readonly #maxWatermarks: number;\n readonly #onInsert: ((event: Event) => void) | undefined;\n readonly #onRemove: ((event: Event) => void) | undefined;\n\n constructor(opts?: MemoryIndexOptions) {\n this.#maxTombstones = opts?.maxTombstones;\n this.#maxWatermarks = opts?.maxWatermarks ?? 0;\n this.#onInsert = opts?.onInsert;\n this.#onRemove = opts?.onRemove;\n }\n\n put(raw: Event): PutResult {\n const lookup: PutLookup = {\n deletion: this.#deletion,\n getById: (id) => this.#byId.get(id),\n getReplaceable: (addr) => {\n const id = this.#replaceable.get(addr);\n const ev = id === undefined ? undefined : this.#byId.get(id);\n if (ev) {\n return { id: ev.id, created_at: ev.created_at };\n }\n const watermark = this.#watermarks.get(addr);\n return watermark === undefined ? undefined : { ...watermark, evicted: true };\n },\n };\n const decision = decidePut(raw, lookup);\n if (decision.action === \"delete\") {\n // Pending e-tag targets and coordinate tombstones never reach\n // indexRemove — drop their watermarks here.\n for (const p of decision.plan.pendingIds) {\n this.#dropWatermarkId(p.id);\n }\n for (const c of decision.plan.coordinates) {\n this.#dropWatermark(c.key);\n }\n }\n const result = applyPutMemory(\n {\n deletion: this.#deletion,\n indexInsert: (e) => this.#indexInsert(e),\n indexRemove: (id) => this.#indexRemove(id),\n },\n decision,\n );\n this.#trimTombstones();\n return result;\n }\n\n /** Sequential `put` in input order. */\n putMany(events: ReadonlyArray<Event>): PutResult[] {\n const results: PutResult[] = [];\n for (const event of events) {\n results.push(this.put(event));\n }\n return results;\n }\n\n get(id: string): Event | undefined {\n const key = id.toLowerCase();\n if (this.#deletion.ids.has(key)) {\n return undefined;\n }\n return this.#byId.get(key);\n }\n\n /** Current event at a `kind:pubkey:d` coordinate (replaceable or addressable). */\n getByAddress(address: string): Event | undefined {\n const coord = parseEventAddress(address);\n if (!coord) {\n return undefined;\n }\n const id = this.#replaceable.get(\n formatEventAddress(coord.kind, coord.pubkey, coord.identifier),\n );\n if (id === undefined) {\n return undefined;\n }\n if (this.#deletion.ids.has(id)) {\n return undefined;\n }\n return this.#byId.get(id);\n }\n\n query(filters: ReadonlyArray<Filter>): Event[] {\n const seen = new Set<string>();\n const events: Event[] = [];\n for (const filter of filters) {\n for (const event of this.#matchedEvents(filter)) {\n if (seen.has(event.id)) {\n continue;\n }\n seen.add(event.id);\n events.push(event);\n }\n }\n sortEvents(events);\n return events;\n }\n\n count(filters: ReadonlyArray<Filter>): number {\n const seen = new Set<string>();\n for (const filter of filters) {\n for (const event of this.#matchedEvents(filter)) {\n seen.add(event.id);\n }\n }\n return seen.size;\n }\n\n negentropyItems(filter: Filter): NegentropyItem[] {\n if (filter.limit === 0) {\n return [];\n }\n const items: NegentropyItem[] = [];\n this.#eachCandidate(filter, (event) => {\n if (this.#deletion.covers(event)) {\n return;\n }\n if (!matchFilter(filter, event)) {\n return;\n }\n items.push({ id: event.id, created_at: event.created_at });\n });\n if (filter.limit !== undefined) {\n items.sort(compareEventsDesc);\n if (items.length > filter.limit) {\n items.length = filter.limit;\n }\n }\n items.sort(itemCompare);\n return items;\n }\n\n /** Remove by id and tombstone (like a local NIP-09). Returns removed count. */\n remove(ids: ReadonlyArray<string>): number {\n let n = 0;\n for (const raw of ids) {\n const id = raw.toLowerCase();\n if (this.#indexRemove(id)) {\n n += 1;\n }\n this.#deletion.ids.add(id);\n this.#deletion.pending.delete(id);\n }\n this.#trimTombstones();\n return n;\n }\n\n /**\n * Remove by id without writing a tombstone (LRU eviction). When the evicted event is the current\n * winner of a replaceable/addressable address, a `{ id, created_at }` watermark is recorded so\n * stale versions stay rejected while the body is gone; the watermarks are FIFO-bounded by\n * `maxWatermarks`.\n */\n evict(ids: ReadonlyArray<string>): number {\n let n = 0;\n for (const raw of ids) {\n const id = raw.toLowerCase();\n const event = this.#byId.get(id);\n if (event === undefined) {\n continue;\n }\n const addr = eventAddress(event);\n const winner = addr !== undefined && this.#replaceable.get(addr) === id;\n if (this.#indexRemove(id)) {\n n += 1;\n }\n if (winner) {\n this.#setWatermark(addr, { id, created_at: event.created_at });\n }\n }\n return n;\n }\n\n /**\n * True when the id is tombstoned, or the coordinate has a deletion marker that still covers the\n * current event at that address: a replacement published after the marker's `until` clears the\n * deletion. Coordinates are matched on the canonical lowercase pubkey.\n */\n isDeleted(idOrAddress: string): boolean {\n if (this.#deletion.ids.has(idOrAddress.toLowerCase())) {\n return true;\n }\n const coord = parseEventAddress(idOrAddress);\n if (!coord) {\n return false;\n }\n const address = formatEventAddress(coord.kind, coord.pubkey, coord.identifier);\n const until = this.#deletion.coordinates.get(address);\n if (until === undefined) {\n return false;\n }\n const id = this.#replaceable.get(address);\n if (id === undefined) {\n return true;\n }\n const event = this.#byId.get(id);\n return event === undefined || event.created_at <= until;\n }\n\n getOutboxBound(pubkey: string, kind: number): OutboxBound | undefined {\n const persisted = this.#outboxBounds.get(outboxBoundKey(pubkey, kind));\n if (persisted) {\n return { oldest: persisted.oldest, newest: persisted.newest };\n }\n return this.#deriveOutboxBound(pubkey, kind);\n }\n\n setOutboxBound(pubkey: string, kind: number, bound: OutboxBound): void {\n this.#outboxBounds.set(outboxBoundKey(pubkey, kind), {\n oldest: bound.oldest,\n newest: bound.newest,\n });\n }\n\n clear(): void {\n if (this.#onRemove) {\n for (const event of this.#byId.values()) {\n this.#onRemove(event);\n }\n }\n this.#byId.clear();\n this.#byPubkey.clear();\n this.#byKind.clear();\n this.#byKindPubkey.clear();\n this.#byEpTag.clear();\n this.#replaceable.clear();\n this.#watermarks.clear();\n this.#watermarkIds.clear();\n this.#deletion.clear();\n this.#outboxBounds.clear();\n }\n\n get size(): number {\n return this.#byId.size;\n }\n\n #indexInsert(event: Event): void {\n this.#byId.set(event.id, event);\n const { pubkey } = event;\n addToSetMap(this.#byPubkey, pubkey, event.id);\n addToSetMap(this.#byKind, event.kind, event.id);\n addToSetMap(this.#byKindPubkey, `${event.kind}:${pubkey}`, event.id);\n for (const tag of event.tags) {\n if ((tag[0] !== \"e\" && tag[0] !== \"p\") || tag[1] === undefined) {\n continue;\n }\n addToSetMap(this.#byEpTag, `${tag[0]}:${tag[1].toLowerCase()}`, event.id);\n }\n const addr = eventAddress(event);\n if (addr !== undefined) {\n this.#replaceable.set(addr, event.id);\n this.#dropWatermark(addr);\n }\n this.#onInsert?.(event);\n }\n\n #indexRemove(id: string): boolean {\n // A removed/deleted id must not keep a stale watermark alive; eviction\n // re-records its winner watermark right after this call.\n this.#dropWatermarkId(id);\n const event = this.#byId.get(id);\n if (!event) {\n return false;\n }\n this.#byId.delete(id);\n const { pubkey } = event;\n removeFromSetMap(this.#byPubkey, pubkey, id);\n removeFromSetMap(this.#byKind, event.kind, id);\n removeFromSetMap(this.#byKindPubkey, `${event.kind}:${pubkey}`, id);\n for (const tag of event.tags) {\n if ((tag[0] !== \"e\" && tag[0] !== \"p\") || tag[1] === undefined) {\n continue;\n }\n removeFromSetMap(this.#byEpTag, `${tag[0]}:${tag[1].toLowerCase()}`, id);\n }\n const addr = eventAddress(event);\n if (addr !== undefined && this.#replaceable.get(addr) === id) {\n this.#replaceable.delete(addr);\n }\n this.#onRemove?.(event);\n return true;\n }\n\n #matchedEvents(filter: Filter): Event[] {\n if (filter.limit === 0) {\n return [];\n }\n const matched: Event[] = [];\n this.#eachCandidate(filter, (event) => {\n if (this.#deletion.covers(event)) {\n return;\n }\n if (!matchFilter(filter, event)) {\n return;\n }\n matched.push(event);\n });\n sortEvents(matched);\n return filter.limit === undefined ? matched : matched.slice(0, filter.limit);\n }\n\n #deriveOutboxBound(pubkey: string, kind: number): OutboxBound | undefined {\n const byPk = this.#byPubkey.get(pubkey.toLowerCase());\n const byKind = this.#byKind.get(kind);\n if (!byPk || !byKind) {\n return undefined;\n }\n let oldest: number | undefined;\n let newest: number | undefined;\n for (const id of byPk) {\n if (!byKind.has(id) || this.#deletion.ids.has(id)) {\n continue;\n }\n const event = this.#byId.get(id);\n if (!event || this.#deletion.covers(event)) {\n continue;\n }\n if (oldest === undefined || event.created_at < oldest) {\n oldest = event.created_at;\n }\n if (newest === undefined || event.created_at > newest) {\n newest = event.created_at;\n }\n }\n if (oldest === undefined || newest === undefined) {\n return undefined;\n }\n return { oldest, newest };\n }\n\n #eachCandidate(filter: Filter, visit: (event: Event) => void): void {\n if (filter.ids) {\n const seen = new Set<string>();\n for (const raw of filter.ids) {\n const event = this.#byId.get(raw.toLowerCase());\n if (!event || seen.has(event.id)) {\n continue;\n }\n seen.add(event.id);\n visit(event);\n }\n return;\n }\n\n if (filter.authors && filter.kinds) {\n const seen = new Set<string>();\n for (const pk of filter.authors) {\n const pubkey = pk.toLowerCase();\n for (const kind of filter.kinds) {\n const ids = this.#byKindPubkey.get(`${kind}:${pubkey}`);\n if (!ids) {\n continue;\n }\n for (const id of ids) {\n if (seen.has(id)) {\n continue;\n }\n seen.add(id);\n const event = this.#byId.get(id);\n if (event) {\n visit(event);\n }\n }\n }\n }\n return;\n }\n\n if (filter.authors) {\n const seen = new Set<string>();\n for (const pk of filter.authors) {\n const byPk = this.#byPubkey.get(pk.toLowerCase());\n if (!byPk) {\n continue;\n }\n for (const id of byPk) {\n if (seen.has(id)) {\n continue;\n }\n seen.add(id);\n const event = this.#byId.get(id);\n if (event) {\n visit(event);\n }\n }\n }\n return;\n }\n\n if (filter.kinds) {\n const seen = new Set<string>();\n for (const kind of filter.kinds) {\n const byKind = this.#byKind.get(kind);\n if (!byKind) {\n continue;\n }\n for (const id of byKind) {\n if (seen.has(id)) {\n continue;\n }\n seen.add(id);\n const event = this.#byId.get(id);\n if (event) {\n visit(event);\n }\n }\n }\n return;\n }\n\n const eTags = filter[\"#e\"];\n const pTags = filter[\"#p\"];\n if (eTags !== undefined || pTags !== undefined) {\n const seen = new Set<string>();\n visitEpTagIds(this.#byEpTag, this.#byId, \"e\", eTags, seen, visit);\n visitEpTagIds(this.#byEpTag, this.#byId, \"p\", pTags, seen, visit);\n return;\n }\n\n // #t/#d and other non-e/p tags are not indexed (e/p only). A generic tag\n // store is extra put/remove amp; hashtag-only queries scan #byId.\n for (const event of this.#byId.values()) {\n visit(event);\n }\n }\n\n #setWatermark(addr: string, watermark: { id: string; created_at: number }): void {\n if (this.#maxWatermarks === 0) {\n return;\n }\n this.#dropWatermark(addr);\n this.#watermarks.set(addr, watermark);\n this.#watermarkIds.set(watermark.id, addr);\n trimOldest(this.#watermarks, this.#maxWatermarks, (a) => this.#dropWatermark(a));\n }\n\n #dropWatermark(addr: string): void {\n const watermark = this.#watermarks.get(addr);\n if (watermark === undefined) {\n return;\n }\n this.#watermarks.delete(addr);\n this.#watermarkIds.delete(watermark.id);\n }\n\n #dropWatermarkId(id: string): void {\n const addr = this.#watermarkIds.get(id);\n if (addr === undefined) {\n return;\n }\n this.#watermarkIds.delete(id);\n this.#watermarks.delete(addr);\n }\n\n #trimTombstones(): void {\n const cap = this.#maxTombstones;\n if (cap === undefined) {\n return;\n }\n trimOldest(this.#deletion.ids, cap, (id) => {\n this.#deletion.pending.delete(id);\n });\n trimOldest(this.#deletion.pending, cap);\n trimOldest(this.#deletion.coordinates, cap);\n }\n}\n\nfunction visitEpTagIds(\n byEpTag: Map<string, Set<string>>,\n byId: Map<string, Event>,\n name: \"e\" | \"p\",\n values: ReadonlyArray<string> | undefined,\n seen: Set<string>,\n visit: (event: Event) => void,\n): void {\n if (values === undefined) {\n return;\n }\n for (const value of values) {\n const ids = byEpTag.get(`${name}:${value.toLowerCase()}`);\n if (!ids) {\n continue;\n }\n for (const id of ids) {\n if (seen.has(id)) {\n continue;\n }\n seen.add(id);\n const event = byId.get(id);\n if (event) {\n visit(event);\n }\n }\n }\n}\n"],"mappings":";;;;;;;;;;AAqCA,IAAa,cAAb,MAAyB;CACvB,wBAAiB,IAAI,IAAmB;CACxC,4BAAqB,IAAI,IAAyB;CAClD,0BAAmB,IAAI,IAAyB;CAChD,gCAAyB,IAAI,IAAyB;CACtD,2BAAoB,IAAI,IAAyB;CACjD,+BAAwB,IAAI,IAAoB;CAEhD,8BAAuB,IAAI,IAAgD;CAE3E,gCAAyB,IAAI,IAAoB;CACjD,YAAqB,IAAI,cAAc;CACvC,gCAAyB,IAAI,IAAyB;CACtD;CACA;CACA;CACA;CAEA,YAAY,MAA2B;EACrC,KAAK,iBAAiB,MAAM;EAC5B,KAAK,iBAAiB,MAAM,iBAAiB;EAC7C,KAAK,YAAY,MAAM;EACvB,KAAK,YAAY,MAAM;CACzB;CAEA,IAAI,KAAuB;EACzB,MAAM,SAAoB;GACxB,UAAU,KAAK;GACf,UAAU,OAAO,KAAK,MAAM,IAAI,EAAE;GAClC,iBAAiB,SAAS;IACxB,MAAM,KAAK,KAAK,aAAa,IAAI,IAAI;IACrC,MAAM,KAAK,OAAO,KAAA,IAAY,KAAA,IAAY,KAAK,MAAM,IAAI,EAAE;IAC3D,IAAI,IACF,OAAO;KAAE,IAAI,GAAG;KAAI,YAAY,GAAG;IAAW;IAEhD,MAAM,YAAY,KAAK,YAAY,IAAI,IAAI;IAC3C,OAAO,cAAc,KAAA,IAAY,KAAA,IAAY;KAAE,GAAG;KAAW,SAAS;IAAK;GAC7E;EACF;EACA,MAAM,WAAW,UAAU,KAAK,MAAM;EACtC,IAAI,SAAS,WAAW,UAAU;GAGhC,KAAK,MAAM,KAAK,SAAS,KAAK,YAC5B,KAAK,iBAAiB,EAAE,EAAE;GAE5B,KAAK,MAAM,KAAK,SAAS,KAAK,aAC5B,KAAK,eAAe,EAAE,GAAG;EAE7B;EACA,MAAM,SAAS,eACb;GACE,UAAU,KAAK;GACf,cAAc,MAAM,KAAK,aAAa,CAAC;GACvC,cAAc,OAAO,KAAK,aAAa,EAAE;EAC3C,GACA,QACF;EACA,KAAK,gBAAgB;EACrB,OAAO;CACT;;CAGA,QAAQ,QAA2C;EACjD,MAAM,UAAuB,CAAC;EAC9B,KAAK,MAAM,SAAS,QAClB,QAAQ,KAAK,KAAK,IAAI,KAAK,CAAC;EAE9B,OAAO;CACT;CAEA,IAAI,IAA+B;EACjC,MAAM,MAAM,GAAG,YAAY;EAC3B,IAAI,KAAK,UAAU,IAAI,IAAI,GAAG,GAC5B;EAEF,OAAO,KAAK,MAAM,IAAI,GAAG;CAC3B;;CAGA,aAAa,SAAoC;EAC/C,MAAM,QAAQ,kBAAkB,OAAO;EACvC,IAAI,CAAC,OACH;EAEF,MAAM,KAAK,KAAK,aAAa,IAC3B,mBAAmB,MAAM,MAAM,MAAM,QAAQ,MAAM,UAAU,CAC/D;EACA,IAAI,OAAO,KAAA,GACT;EAEF,IAAI,KAAK,UAAU,IAAI,IAAI,EAAE,GAC3B;EAEF,OAAO,KAAK,MAAM,IAAI,EAAE;CAC1B;CAEA,MAAM,SAAyC;EAC7C,MAAM,uBAAO,IAAI,IAAY;EAC7B,MAAM,SAAkB,CAAC;EACzB,KAAK,MAAM,UAAU,SACnB,KAAK,MAAM,SAAS,KAAK,eAAe,MAAM,GAAG;GAC/C,IAAI,KAAK,IAAI,MAAM,EAAE,GACnB;GAEF,KAAK,IAAI,MAAM,EAAE;GACjB,OAAO,KAAK,KAAK;EACnB;EAEF,WAAW,MAAM;EACjB,OAAO;CACT;CAEA,MAAM,SAAwC;EAC5C,MAAM,uBAAO,IAAI,IAAY;EAC7B,KAAK,MAAM,UAAU,SACnB,KAAK,MAAM,SAAS,KAAK,eAAe,MAAM,GAC5C,KAAK,IAAI,MAAM,EAAE;EAGrB,OAAO,KAAK;CACd;CAEA,gBAAgB,QAAkC;EAChD,IAAI,OAAO,UAAU,GACnB,OAAO,CAAC;EAEV,MAAM,QAA0B,CAAC;EACjC,KAAK,eAAe,SAAS,UAAU;GACrC,IAAI,KAAK,UAAU,OAAO,KAAK,GAC7B;GAEF,IAAI,CAAC,YAAY,QAAQ,KAAK,GAC5B;GAEF,MAAM,KAAK;IAAE,IAAI,MAAM;IAAI,YAAY,MAAM;GAAW,CAAC;EAC3D,CAAC;EACD,IAAI,OAAO,UAAU,KAAA,GAAW;GAC9B,MAAM,KAAK,iBAAiB;GAC5B,IAAI,MAAM,SAAS,OAAO,OACxB,MAAM,SAAS,OAAO;EAE1B;EACA,MAAM,KAAK,WAAW;EACtB,OAAO;CACT;;CAGA,OAAO,KAAoC;EACzC,IAAI,IAAI;EACR,KAAK,MAAM,OAAO,KAAK;GACrB,MAAM,KAAK,IAAI,YAAY;GAC3B,IAAI,KAAK,aAAa,EAAE,GACtB,KAAK;GAEP,KAAK,UAAU,IAAI,IAAI,EAAE;GACzB,KAAK,UAAU,QAAQ,OAAO,EAAE;EAClC;EACA,KAAK,gBAAgB;EACrB,OAAO;CACT;;;;;;;CAQA,MAAM,KAAoC;EACxC,IAAI,IAAI;EACR,KAAK,MAAM,OAAO,KAAK;GACrB,MAAM,KAAK,IAAI,YAAY;GAC3B,MAAM,QAAQ,KAAK,MAAM,IAAI,EAAE;GAC/B,IAAI,UAAU,KAAA,GACZ;GAEF,MAAM,OAAO,aAAa,KAAK;GAC/B,MAAM,SAAS,SAAS,KAAA,KAAa,KAAK,aAAa,IAAI,IAAI,MAAM;GACrE,IAAI,KAAK,aAAa,EAAE,GACtB,KAAK;GAEP,IAAI,QACF,KAAK,cAAc,MAAM;IAAE;IAAI,YAAY,MAAM;GAAW,CAAC;EAEjE;EACA,OAAO;CACT;;;;;;CAOA,UAAU,aAA8B;EACtC,IAAI,KAAK,UAAU,IAAI,IAAI,YAAY,YAAY,CAAC,GAClD,OAAO;EAET,MAAM,QAAQ,kBAAkB,WAAW;EAC3C,IAAI,CAAC,OACH,OAAO;EAET,MAAM,UAAU,mBAAmB,MAAM,MAAM,MAAM,QAAQ,MAAM,UAAU;EAC7E,MAAM,QAAQ,KAAK,UAAU,YAAY,IAAI,OAAO;EACpD,IAAI,UAAU,KAAA,GACZ,OAAO;EAET,MAAM,KAAK,KAAK,aAAa,IAAI,OAAO;EACxC,IAAI,OAAO,KAAA,GACT,OAAO;EAET,MAAM,QAAQ,KAAK,MAAM,IAAI,EAAE;EAC/B,OAAO,UAAU,KAAA,KAAa,MAAM,cAAc;CACpD;CAEA,eAAe,QAAgB,MAAuC;EACpE,MAAM,YAAY,KAAK,cAAc,IAAI,eAAe,QAAQ,IAAI,CAAC;EACrE,IAAI,WACF,OAAO;GAAE,QAAQ,UAAU;GAAQ,QAAQ,UAAU;EAAO;EAE9D,OAAO,KAAK,mBAAmB,QAAQ,IAAI;CAC7C;CAEA,eAAe,QAAgB,MAAc,OAA0B;EACrE,KAAK,cAAc,IAAI,eAAe,QAAQ,IAAI,GAAG;GACnD,QAAQ,MAAM;GACd,QAAQ,MAAM;EAChB,CAAC;CACH;CAEA,QAAc;EACZ,IAAI,KAAK,WACP,KAAK,MAAM,SAAS,KAAK,MAAM,OAAO,GACpC,KAAK,UAAU,KAAK;EAGxB,KAAK,MAAM,MAAM;EACjB,KAAK,UAAU,MAAM;EACrB,KAAK,QAAQ,MAAM;EACnB,KAAK,cAAc,MAAM;EACzB,KAAK,SAAS,MAAM;EACpB,KAAK,aAAa,MAAM;EACxB,KAAK,YAAY,MAAM;EACvB,KAAK,cAAc,MAAM;EACzB,KAAK,UAAU,MAAM;EACrB,KAAK,cAAc,MAAM;CAC3B;CAEA,IAAI,OAAe;EACjB,OAAO,KAAK,MAAM;CACpB;CAEA,aAAa,OAAoB;EAC/B,KAAK,MAAM,IAAI,MAAM,IAAI,KAAK;EAC9B,MAAM,EAAE,WAAW;EACnB,YAAY,KAAK,WAAW,QAAQ,MAAM,EAAE;EAC5C,YAAY,KAAK,SAAS,MAAM,MAAM,MAAM,EAAE;EAC9C,YAAY,KAAK,eAAe,GAAG,MAAM,KAAK,GAAG,UAAU,MAAM,EAAE;EACnE,KAAK,MAAM,OAAO,MAAM,MAAM;GAC5B,IAAK,IAAI,OAAO,OAAO,IAAI,OAAO,OAAQ,IAAI,OAAO,KAAA,GACnD;GAEF,YAAY,KAAK,UAAU,GAAG,IAAI,GAAG,GAAG,IAAI,EAAE,CAAC,YAAY,KAAK,MAAM,EAAE;EAC1E;EACA,MAAM,OAAO,aAAa,KAAK;EAC/B,IAAI,SAAS,KAAA,GAAW;GACtB,KAAK,aAAa,IAAI,MAAM,MAAM,EAAE;GACpC,KAAK,eAAe,IAAI;EAC1B;EACA,KAAK,YAAY,KAAK;CACxB;CAEA,aAAa,IAAqB;EAGhC,KAAK,iBAAiB,EAAE;EACxB,MAAM,QAAQ,KAAK,MAAM,IAAI,EAAE;EAC/B,IAAI,CAAC,OACH,OAAO;EAET,KAAK,MAAM,OAAO,EAAE;EACpB,MAAM,EAAE,WAAW;EACnB,iBAAiB,KAAK,WAAW,QAAQ,EAAE;EAC3C,iBAAiB,KAAK,SAAS,MAAM,MAAM,EAAE;EAC7C,iBAAiB,KAAK,eAAe,GAAG,MAAM,KAAK,GAAG,UAAU,EAAE;EAClE,KAAK,MAAM,OAAO,MAAM,MAAM;GAC5B,IAAK,IAAI,OAAO,OAAO,IAAI,OAAO,OAAQ,IAAI,OAAO,KAAA,GACnD;GAEF,iBAAiB,KAAK,UAAU,GAAG,IAAI,GAAG,GAAG,IAAI,EAAE,CAAC,YAAY,KAAK,EAAE;EACzE;EACA,MAAM,OAAO,aAAa,KAAK;EAC/B,IAAI,SAAS,KAAA,KAAa,KAAK,aAAa,IAAI,IAAI,MAAM,IACxD,KAAK,aAAa,OAAO,IAAI;EAE/B,KAAK,YAAY,KAAK;EACtB,OAAO;CACT;CAEA,eAAe,QAAyB;EACtC,IAAI,OAAO,UAAU,GACnB,OAAO,CAAC;EAEV,MAAM,UAAmB,CAAC;EAC1B,KAAK,eAAe,SAAS,UAAU;GACrC,IAAI,KAAK,UAAU,OAAO,KAAK,GAC7B;GAEF,IAAI,CAAC,YAAY,QAAQ,KAAK,GAC5B;GAEF,QAAQ,KAAK,KAAK;EACpB,CAAC;EACD,WAAW,OAAO;EAClB,OAAO,OAAO,UAAU,KAAA,IAAY,UAAU,QAAQ,MAAM,GAAG,OAAO,KAAK;CAC7E;CAEA,mBAAmB,QAAgB,MAAuC;EACxE,MAAM,OAAO,KAAK,UAAU,IAAI,OAAO,YAAY,CAAC;EACpD,MAAM,SAAS,KAAK,QAAQ,IAAI,IAAI;EACpC,IAAI,CAAC,QAAQ,CAAC,QACZ;EAEF,IAAI;EACJ,IAAI;EACJ,KAAK,MAAM,MAAM,MAAM;GACrB,IAAI,CAAC,OAAO,IAAI,EAAE,KAAK,KAAK,UAAU,IAAI,IAAI,EAAE,GAC9C;GAEF,MAAM,QAAQ,KAAK,MAAM,IAAI,EAAE;GAC/B,IAAI,CAAC,SAAS,KAAK,UAAU,OAAO,KAAK,GACvC;GAEF,IAAI,WAAW,KAAA,KAAa,MAAM,aAAa,QAC7C,SAAS,MAAM;GAEjB,IAAI,WAAW,KAAA,KAAa,MAAM,aAAa,QAC7C,SAAS,MAAM;EAEnB;EACA,IAAI,WAAW,KAAA,KAAa,WAAW,KAAA,GACrC;EAEF,OAAO;GAAE;GAAQ;EAAO;CAC1B;CAEA,eAAe,QAAgB,OAAqC;EAClE,IAAI,OAAO,KAAK;GACd,MAAM,uBAAO,IAAI,IAAY;GAC7B,KAAK,MAAM,OAAO,OAAO,KAAK;IAC5B,MAAM,QAAQ,KAAK,MAAM,IAAI,IAAI,YAAY,CAAC;IAC9C,IAAI,CAAC,SAAS,KAAK,IAAI,MAAM,EAAE,GAC7B;IAEF,KAAK,IAAI,MAAM,EAAE;IACjB,MAAM,KAAK;GACb;GACA;EACF;EAEA,IAAI,OAAO,WAAW,OAAO,OAAO;GAClC,MAAM,uBAAO,IAAI,IAAY;GAC7B,KAAK,MAAM,MAAM,OAAO,SAAS;IAC/B,MAAM,SAAS,GAAG,YAAY;IAC9B,KAAK,MAAM,QAAQ,OAAO,OAAO;KAC/B,MAAM,MAAM,KAAK,cAAc,IAAI,GAAG,KAAK,GAAG,QAAQ;KACtD,IAAI,CAAC,KACH;KAEF,KAAK,MAAM,MAAM,KAAK;MACpB,IAAI,KAAK,IAAI,EAAE,GACb;MAEF,KAAK,IAAI,EAAE;MACX,MAAM,QAAQ,KAAK,MAAM,IAAI,EAAE;MAC/B,IAAI,OACF,MAAM,KAAK;KAEf;IACF;GACF;GACA;EACF;EAEA,IAAI,OAAO,SAAS;GAClB,MAAM,uBAAO,IAAI,IAAY;GAC7B,KAAK,MAAM,MAAM,OAAO,SAAS;IAC/B,MAAM,OAAO,KAAK,UAAU,IAAI,GAAG,YAAY,CAAC;IAChD,IAAI,CAAC,MACH;IAEF,KAAK,MAAM,MAAM,MAAM;KACrB,IAAI,KAAK,IAAI,EAAE,GACb;KAEF,KAAK,IAAI,EAAE;KACX,MAAM,QAAQ,KAAK,MAAM,IAAI,EAAE;KAC/B,IAAI,OACF,MAAM,KAAK;IAEf;GACF;GACA;EACF;EAEA,IAAI,OAAO,OAAO;GAChB,MAAM,uBAAO,IAAI,IAAY;GAC7B,KAAK,MAAM,QAAQ,OAAO,OAAO;IAC/B,MAAM,SAAS,KAAK,QAAQ,IAAI,IAAI;IACpC,IAAI,CAAC,QACH;IAEF,KAAK,MAAM,MAAM,QAAQ;KACvB,IAAI,KAAK,IAAI,EAAE,GACb;KAEF,KAAK,IAAI,EAAE;KACX,MAAM,QAAQ,KAAK,MAAM,IAAI,EAAE;KAC/B,IAAI,OACF,MAAM,KAAK;IAEf;GACF;GACA;EACF;EAEA,MAAM,QAAQ,OAAO;EACrB,MAAM,QAAQ,OAAO;EACrB,IAAI,UAAU,KAAA,KAAa,UAAU,KAAA,GAAW;GAC9C,MAAM,uBAAO,IAAI,IAAY;GAC7B,cAAc,KAAK,UAAU,KAAK,OAAO,KAAK,OAAO,MAAM,KAAK;GAChE,cAAc,KAAK,UAAU,KAAK,OAAO,KAAK,OAAO,MAAM,KAAK;GAChE;EACF;EAIA,KAAK,MAAM,SAAS,KAAK,MAAM,OAAO,GACpC,MAAM,KAAK;CAEf;CAEA,cAAc,MAAc,WAAqD;EAC/E,IAAI,KAAK,mBAAmB,GAC1B;EAEF,KAAK,eAAe,IAAI;EACxB,KAAK,YAAY,IAAI,MAAM,SAAS;EACpC,KAAK,cAAc,IAAI,UAAU,IAAI,IAAI;EACzC,WAAW,KAAK,aAAa,KAAK,iBAAiB,MAAM,KAAK,eAAe,CAAC,CAAC;CACjF;CAEA,eAAe,MAAoB;EACjC,MAAM,YAAY,KAAK,YAAY,IAAI,IAAI;EAC3C,IAAI,cAAc,KAAA,GAChB;EAEF,KAAK,YAAY,OAAO,IAAI;EAC5B,KAAK,cAAc,OAAO,UAAU,EAAE;CACxC;CAEA,iBAAiB,IAAkB;EACjC,MAAM,OAAO,KAAK,cAAc,IAAI,EAAE;EACtC,IAAI,SAAS,KAAA,GACX;EAEF,KAAK,cAAc,OAAO,EAAE;EAC5B,KAAK,YAAY,OAAO,IAAI;CAC9B;CAEA,kBAAwB;EACtB,MAAM,MAAM,KAAK;EACjB,IAAI,QAAQ,KAAA,GACV;EAEF,WAAW,KAAK,UAAU,KAAK,MAAM,OAAO;GAC1C,KAAK,UAAU,QAAQ,OAAO,EAAE;EAClC,CAAC;EACD,WAAW,KAAK,UAAU,SAAS,GAAG;EACtC,WAAW,KAAK,UAAU,aAAa,GAAG;CAC5C;AACF;AAEA,SAAS,cACP,SACA,MACA,MACA,QACA,MACA,OACM;CACN,IAAI,WAAW,KAAA,GACb;CAEF,KAAK,MAAM,SAAS,QAAQ;EAC1B,MAAM,MAAM,QAAQ,IAAI,GAAG,KAAK,GAAG,MAAM,YAAY,GAAG;EACxD,IAAI,CAAC,KACH;EAEF,KAAK,MAAM,MAAM,KAAK;GACpB,IAAI,KAAK,IAAI,EAAE,GACb;GAEF,KAAK,IAAI,EAAE;GACX,MAAM,QAAQ,KAAK,IAAI,EAAE;GACzB,IAAI,OACF,MAAM,KAAK;EAEf;CACF;AACF"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { _ as MessageError, a as hexToBytes, c as isRecord, i as bytesToHex } from "./util-DMF9AIO0.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { h as validateSignedEvent } from "./event-C2eLiPpV.mjs";
|
|
3
3
|
//#region src/core/message.ts
|
|
4
4
|
/** Validate a subscription id; throws {@link MessageError} unless 1..64 chars. */
|
|
5
5
|
function assertSubscriptionId(id) {
|
|
@@ -142,8 +142,9 @@ function parseRelayMessage(raw) {
|
|
|
142
142
|
return ["AUTH", items[1]];
|
|
143
143
|
case "COUNT": {
|
|
144
144
|
const payload = items.at(2);
|
|
145
|
-
|
|
146
|
-
|
|
145
|
+
const count = isRecord(payload) ? payload["count"] : void 0;
|
|
146
|
+
if (items.length !== 3 || typeof items[1] !== "string" || !isRecord(payload) || typeof count !== "number" || !Number.isSafeInteger(count) || count < 0) throw new MessageError("invalid COUNT relay message");
|
|
147
|
+
const result = { count };
|
|
147
148
|
if (typeof payload["approximate"] === "boolean") result.approximate = payload["approximate"];
|
|
148
149
|
const hll = parseCountHll(payload["hll"]);
|
|
149
150
|
if (hll !== void 0) result.hll = hll;
|
|
@@ -191,4 +192,4 @@ function isNegHex(value) {
|
|
|
191
192
|
//#endregion
|
|
192
193
|
export { mergeCountHll as a, encodeRelayMessage as i, createSubscriptionId as n, parseClientMessage as o, encodeClientMessage as r, parseRelayMessage as s, assertSubscriptionId as t };
|
|
193
194
|
|
|
194
|
-
//# sourceMappingURL=message-
|
|
195
|
+
//# sourceMappingURL=message-Rd5Z_17h.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message-oNr7t0SJ.mjs","names":[],"sources":["../src/core/message.ts"],"sourcesContent":["import { MessageError } from \"./error.ts\";\nimport type { Event } from \"./event.ts\";\nimport { validateSignedEvent } from \"./event.ts\";\nimport type { Filter } from \"./filter.ts\";\nimport { SUBSCRIPTION_ID_MAX_CHARS } from \"./limits.ts\";\nimport type { Mutable } from \"./util.ts\";\nimport { bytesToHex, hexToBytes, isRecord } from \"./util.ts\";\n\n/** NIP-01 subscription id: 1..64 chars. */\nexport type SubscriptionId = string;\n\n/** Validate a subscription id; throws {@link MessageError} unless 1..64 chars. */\nexport function assertSubscriptionId(id: string): SubscriptionId {\n if (id.length === 0 || id.length > SUBSCRIPTION_ID_MAX_CHARS) {\n throw new MessageError(`subscription id length must be 1..${SUBSCRIPTION_ID_MAX_CHARS}`);\n }\n return id;\n}\n\n/** Validate the given id, or mint a random 16-hex-char subscription id. */\nexport function createSubscriptionId(id?: string): SubscriptionId {\n if (id !== undefined) {\n return assertSubscriptionId(id);\n }\n const bytes = new Uint8Array(8);\n crypto.getRandomValues(bytes);\n return bytesToHex(bytes);\n}\n\n/** Client → relay messages (NIP-01 + NIP-42 AUTH + NIP-45 COUNT + NIP-77). */\nexport type ClientMessage =\n | [\"EVENT\", Event]\n | [\"REQ\", SubscriptionId, ...Filter[]]\n | [\"CLOSE\", SubscriptionId]\n | [\"AUTH\", Event]\n | [\"COUNT\", SubscriptionId, ...Filter[]]\n | [\"NEG-OPEN\", SubscriptionId, Filter, string]\n | [\"NEG-MSG\", SubscriptionId, string]\n | [\"NEG-CLOSE\", SubscriptionId];\n\n/** Relay → client messages. */\nexport type RelayMessage =\n | [\"EVENT\", SubscriptionId, Event]\n | [\"OK\", string, boolean, string]\n | [\"EOSE\", SubscriptionId]\n | [\"CLOSED\", SubscriptionId, string]\n | [\"NOTICE\", string]\n | [\"AUTH\", string]\n | [\"COUNT\", SubscriptionId, CountResult]\n | [\"NEG-MSG\", SubscriptionId, string]\n | [\"NEG-ERR\", SubscriptionId, string];\n\n/** NIP-45 COUNT reply payload. */\nexport type CountResult = {\n readonly count: number;\n readonly approximate?: boolean | undefined;\n /**\n * Optional 512-char hex HyperLogLog sketch (256 registers). Merge sketches with `mergeCountHll`.\n * Estimation is unspecified by NIP-45 and not provided.\n */\n readonly hll?: string | undefined;\n};\n\nconst HLL_BYTES = 256; // 512 hex chars (NIP-45; hex only, not base64)\nconst HLL_HEX_LEN = HLL_BYTES * 2;\nconst HEX_RE = /^[0-9a-fA-F]+$/;\n\n/**\n * Register-wise max of NIP-45 HyperLogLog sketches. Output is always lowercase 512 hex. Empty input\n * is the zero sketch (identity).\n */\nexport function mergeCountHll(hexes: ReadonlyArray<string>): string {\n const merged = new Uint8Array(HLL_BYTES);\n for (const hex of hexes) {\n if (hex.length !== HLL_HEX_LEN || !HEX_RE.test(hex)) {\n throw new MessageError(\"invalid NIP-45 HLL sketch: expected 512-char hex\");\n }\n const bytes = hexToBytes(hex);\n for (const [i, b] of bytes.entries()) {\n const m = merged[i];\n if (m !== undefined && b > m) {\n merged[i] = b;\n }\n }\n }\n return bytesToHex(merged);\n}\n\n/** Serialize a client->relay message to its NIP-01 JSON wire form. */\nexport function encodeClientMessage(message: ClientMessage): string {\n return JSON.stringify(message);\n}\n\n/** Serialize a relay->client message to its NIP-01 JSON wire form. */\nexport function encodeRelayMessage(message: RelayMessage): string {\n return JSON.stringify(message);\n}\n\n/** Parse a client->relay JSON message; throws {@link MessageError} on malformed input. */\nexport function parseClientMessage(raw: string): ClientMessage {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n throw new MessageError(\"client message is not valid JSON\");\n }\n if (!Array.isArray(parsed) || parsed.length === 0 || typeof parsed[0] !== \"string\") {\n throw new MessageError(\"client message must be a non-empty JSON array\");\n }\n const items: unknown[] = parsed;\n const [type] = items;\n switch (type) {\n case \"EVENT\":\n if (items.length !== 2 || !validateSignedEvent(items[1])) {\n throw new MessageError(\"invalid EVENT client message\");\n }\n return [\"EVENT\", items[1]];\n\n case \"REQ\":\n if (items.length < 3 || typeof items[1] !== \"string\") {\n throw new MessageError(\"invalid REQ client message\");\n }\n return [\"REQ\", items[1], ...parseWireFilters(items.slice(2), \"REQ\")];\n\n case \"CLOSE\":\n if (items.length !== 2 || typeof items[1] !== \"string\") {\n throw new MessageError(\"invalid CLOSE client message\");\n }\n return [\"CLOSE\", items[1]];\n\n case \"AUTH\":\n if (items.length !== 2 || !validateSignedEvent(items[1])) {\n throw new MessageError(\"invalid AUTH client message\");\n }\n return [\"AUTH\", items[1]];\n\n case \"COUNT\":\n if (items.length < 3 || typeof items[1] !== \"string\") {\n throw new MessageError(\"invalid COUNT client message\");\n }\n return [\"COUNT\", items[1], ...parseWireFilters(items.slice(2), \"COUNT\")];\n\n case \"NEG-OPEN\":\n if (items.length === 5) {\n throw new MessageError(\"obsolete 5-element NEG-OPEN; expected [NEG-OPEN, id, filter, hex]\");\n }\n if (\n items.length !== 4 ||\n typeof items[1] !== \"string\" ||\n !isWireFilter(items[2]) ||\n !isNegHex(items[3])\n ) {\n throw new MessageError(\"invalid NEG-OPEN client message\");\n }\n return [\"NEG-OPEN\", items[1], items[2], items[3].toLowerCase()];\n\n case \"NEG-MSG\":\n if (items.length !== 3 || typeof items[1] !== \"string\" || !isNegHex(items[2])) {\n throw new MessageError(\"invalid NEG-MSG client message\");\n }\n return [\"NEG-MSG\", items[1], items[2].toLowerCase()];\n\n case \"NEG-CLOSE\":\n if (items.length !== 2 || typeof items[1] !== \"string\") {\n throw new MessageError(\"invalid NEG-CLOSE client message\");\n }\n return [\"NEG-CLOSE\", items[1]];\n\n default:\n throw new MessageError(`unknown client message type: ${String(type)}`);\n }\n}\n\n/** Parse a relay->client JSON message; throws {@link MessageError} on malformed input. */\nexport function parseRelayMessage(raw: string): RelayMessage {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n throw new MessageError(\"relay message is not valid JSON\");\n }\n if (!Array.isArray(parsed) || parsed.length === 0 || typeof parsed[0] !== \"string\") {\n throw new MessageError(\"relay message must be a non-empty JSON array\");\n }\n const items: unknown[] = parsed;\n const [type] = items;\n switch (type) {\n case \"EVENT\":\n if (items.length !== 3 || typeof items[1] !== \"string\" || !validateSignedEvent(items[2])) {\n throw new MessageError(\"invalid EVENT relay message\");\n }\n return [\"EVENT\", items[1], items[2]];\n\n case \"OK\":\n if (\n items.length !== 4 ||\n typeof items[1] !== \"string\" ||\n typeof items[2] !== \"boolean\" ||\n typeof items[3] !== \"string\"\n ) {\n throw new MessageError(\"invalid OK relay message\");\n }\n return [\"OK\", items[1], items[2], items[3]];\n\n case \"EOSE\":\n if (items.length !== 2 || typeof items[1] !== \"string\") {\n throw new MessageError(\"invalid EOSE relay message\");\n }\n return [\"EOSE\", items[1]];\n\n case \"CLOSED\":\n if (items.length !== 3 || typeof items[1] !== \"string\" || typeof items[2] !== \"string\") {\n throw new MessageError(\"invalid CLOSED relay message\");\n }\n return [\"CLOSED\", items[1], items[2]];\n\n case \"NOTICE\":\n if (items.length !== 2 || typeof items[1] !== \"string\") {\n throw new MessageError(\"invalid NOTICE relay message\");\n }\n return [\"NOTICE\", items[1]];\n\n case \"AUTH\":\n if (items.length !== 2 || typeof items[1] !== \"string\") {\n throw new MessageError(\"invalid AUTH relay message\");\n }\n return [\"AUTH\", items[1]];\n\n case \"COUNT\": {\n const payload = items.at(2);\n if (\n items.length !== 3 ||\n typeof items[1] !== \"string\" ||\n !isRecord(payload) ||\n typeof payload[\"count\"] !== \"number\"\n ) {\n throw new MessageError(\"invalid COUNT relay message\");\n }\n const result: Mutable<CountResult> = { count: payload[\"count\"] };\n if (typeof payload[\"approximate\"] === \"boolean\") {\n result.approximate = payload[\"approximate\"];\n }\n const hll = parseCountHll(payload[\"hll\"]);\n if (hll !== undefined) {\n result.hll = hll;\n }\n return [\"COUNT\", items[1], result];\n }\n case \"NEG-MSG\":\n if (items.length !== 3 || typeof items[1] !== \"string\" || !isNegHex(items[2])) {\n throw new MessageError(\"invalid NEG-MSG relay message\");\n }\n return [\"NEG-MSG\", items[1], items[2].toLowerCase()];\n\n case \"NEG-ERR\":\n if (\n (items.length !== 3 && items.length !== 4) ||\n typeof items[1] !== \"string\" ||\n typeof items[2] !== \"string\"\n ) {\n throw new MessageError(\"invalid NEG-ERR relay message\");\n }\n return [\"NEG-ERR\", items[1], items[2]];\n\n default:\n throw new MessageError(`unknown relay message type: ${String(type)}`);\n }\n}\n\nfunction parseCountHll(value: unknown): string | undefined {\n if (typeof value !== \"string\" || value.length !== HLL_HEX_LEN || !HEX_RE.test(value)) {\n return undefined;\n }\n return value.toLowerCase();\n}\n\nfunction isWireFilter(value: unknown): value is Filter {\n return isRecord(value);\n}\n\nfunction parseWireFilters(items: unknown[], kind: string): Filter[] {\n const filters: Filter[] = [];\n for (const item of items) {\n if (!isWireFilter(item)) {\n throw new MessageError(`invalid ${kind} filter`);\n }\n filters.push(item);\n }\n return filters;\n}\n\nfunction isNegHex(value: unknown): value is string {\n return (\n typeof value === \"string\" && value.length > 0 && value.length % 2 === 0 && HEX_RE.test(value)\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"message-Rd5Z_17h.mjs","names":[],"sources":["../src/core/message.ts"],"sourcesContent":["import { MessageError } from \"./error.ts\";\nimport type { Event } from \"./event.ts\";\nimport { validateSignedEvent } from \"./event.ts\";\nimport type { Filter } from \"./filter.ts\";\nimport { SUBSCRIPTION_ID_MAX_CHARS } from \"./limits.ts\";\nimport type { Mutable } from \"./util.ts\";\nimport { bytesToHex, hexToBytes, isRecord } from \"./util.ts\";\n\n/** NIP-01 subscription id: 1..64 chars. */\nexport type SubscriptionId = string;\n\n/** Validate a subscription id; throws {@link MessageError} unless 1..64 chars. */\nexport function assertSubscriptionId(id: string): SubscriptionId {\n if (id.length === 0 || id.length > SUBSCRIPTION_ID_MAX_CHARS) {\n throw new MessageError(`subscription id length must be 1..${SUBSCRIPTION_ID_MAX_CHARS}`);\n }\n return id;\n}\n\n/** Validate the given id, or mint a random 16-hex-char subscription id. */\nexport function createSubscriptionId(id?: string): SubscriptionId {\n if (id !== undefined) {\n return assertSubscriptionId(id);\n }\n const bytes = new Uint8Array(8);\n crypto.getRandomValues(bytes);\n return bytesToHex(bytes);\n}\n\n/** Client → relay messages (NIP-01 + NIP-42 AUTH + NIP-45 COUNT + NIP-77). */\nexport type ClientMessage =\n | [\"EVENT\", Event]\n | [\"REQ\", SubscriptionId, ...Filter[]]\n | [\"CLOSE\", SubscriptionId]\n | [\"AUTH\", Event]\n | [\"COUNT\", SubscriptionId, ...Filter[]]\n | [\"NEG-OPEN\", SubscriptionId, Filter, string]\n | [\"NEG-MSG\", SubscriptionId, string]\n | [\"NEG-CLOSE\", SubscriptionId];\n\n/** Relay → client messages. */\nexport type RelayMessage =\n | [\"EVENT\", SubscriptionId, Event]\n | [\"OK\", string, boolean, string]\n | [\"EOSE\", SubscriptionId]\n | [\"CLOSED\", SubscriptionId, string]\n | [\"NOTICE\", string]\n | [\"AUTH\", string]\n | [\"COUNT\", SubscriptionId, CountResult]\n | [\"NEG-MSG\", SubscriptionId, string]\n | [\"NEG-ERR\", SubscriptionId, string];\n\n/** NIP-45 COUNT reply payload. */\nexport type CountResult = {\n readonly count: number;\n readonly approximate?: boolean | undefined;\n /**\n * Optional 512-char hex HyperLogLog sketch (256 registers). Merge sketches with `mergeCountHll`.\n * Estimation is unspecified by NIP-45 and not provided.\n */\n readonly hll?: string | undefined;\n};\n\nconst HLL_BYTES = 256; // 512 hex chars (NIP-45; hex only, not base64)\nconst HLL_HEX_LEN = HLL_BYTES * 2;\nconst HEX_RE = /^[0-9a-fA-F]+$/;\n\n/**\n * Register-wise max of NIP-45 HyperLogLog sketches. Output is always lowercase 512 hex. Empty input\n * is the zero sketch (identity).\n */\nexport function mergeCountHll(hexes: ReadonlyArray<string>): string {\n const merged = new Uint8Array(HLL_BYTES);\n for (const hex of hexes) {\n if (hex.length !== HLL_HEX_LEN || !HEX_RE.test(hex)) {\n throw new MessageError(\"invalid NIP-45 HLL sketch: expected 512-char hex\");\n }\n const bytes = hexToBytes(hex);\n for (const [i, b] of bytes.entries()) {\n const m = merged[i];\n if (m !== undefined && b > m) {\n merged[i] = b;\n }\n }\n }\n return bytesToHex(merged);\n}\n\n/** Serialize a client->relay message to its NIP-01 JSON wire form. */\nexport function encodeClientMessage(message: ClientMessage): string {\n return JSON.stringify(message);\n}\n\n/** Serialize a relay->client message to its NIP-01 JSON wire form. */\nexport function encodeRelayMessage(message: RelayMessage): string {\n return JSON.stringify(message);\n}\n\n/** Parse a client->relay JSON message; throws {@link MessageError} on malformed input. */\nexport function parseClientMessage(raw: string): ClientMessage {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n throw new MessageError(\"client message is not valid JSON\");\n }\n if (!Array.isArray(parsed) || parsed.length === 0 || typeof parsed[0] !== \"string\") {\n throw new MessageError(\"client message must be a non-empty JSON array\");\n }\n const items: unknown[] = parsed;\n const [type] = items;\n switch (type) {\n case \"EVENT\":\n if (items.length !== 2 || !validateSignedEvent(items[1])) {\n throw new MessageError(\"invalid EVENT client message\");\n }\n return [\"EVENT\", items[1]];\n\n case \"REQ\":\n if (items.length < 3 || typeof items[1] !== \"string\") {\n throw new MessageError(\"invalid REQ client message\");\n }\n return [\"REQ\", items[1], ...parseWireFilters(items.slice(2), \"REQ\")];\n\n case \"CLOSE\":\n if (items.length !== 2 || typeof items[1] !== \"string\") {\n throw new MessageError(\"invalid CLOSE client message\");\n }\n return [\"CLOSE\", items[1]];\n\n case \"AUTH\":\n if (items.length !== 2 || !validateSignedEvent(items[1])) {\n throw new MessageError(\"invalid AUTH client message\");\n }\n return [\"AUTH\", items[1]];\n\n case \"COUNT\":\n if (items.length < 3 || typeof items[1] !== \"string\") {\n throw new MessageError(\"invalid COUNT client message\");\n }\n return [\"COUNT\", items[1], ...parseWireFilters(items.slice(2), \"COUNT\")];\n\n case \"NEG-OPEN\":\n if (items.length === 5) {\n throw new MessageError(\"obsolete 5-element NEG-OPEN; expected [NEG-OPEN, id, filter, hex]\");\n }\n if (\n items.length !== 4 ||\n typeof items[1] !== \"string\" ||\n !isWireFilter(items[2]) ||\n !isNegHex(items[3])\n ) {\n throw new MessageError(\"invalid NEG-OPEN client message\");\n }\n return [\"NEG-OPEN\", items[1], items[2], items[3].toLowerCase()];\n\n case \"NEG-MSG\":\n if (items.length !== 3 || typeof items[1] !== \"string\" || !isNegHex(items[2])) {\n throw new MessageError(\"invalid NEG-MSG client message\");\n }\n return [\"NEG-MSG\", items[1], items[2].toLowerCase()];\n\n case \"NEG-CLOSE\":\n if (items.length !== 2 || typeof items[1] !== \"string\") {\n throw new MessageError(\"invalid NEG-CLOSE client message\");\n }\n return [\"NEG-CLOSE\", items[1]];\n\n default:\n throw new MessageError(`unknown client message type: ${String(type)}`);\n }\n}\n\n/** Parse a relay->client JSON message; throws {@link MessageError} on malformed input. */\nexport function parseRelayMessage(raw: string): RelayMessage {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n throw new MessageError(\"relay message is not valid JSON\");\n }\n if (!Array.isArray(parsed) || parsed.length === 0 || typeof parsed[0] !== \"string\") {\n throw new MessageError(\"relay message must be a non-empty JSON array\");\n }\n const items: unknown[] = parsed;\n const [type] = items;\n switch (type) {\n case \"EVENT\":\n if (items.length !== 3 || typeof items[1] !== \"string\" || !validateSignedEvent(items[2])) {\n throw new MessageError(\"invalid EVENT relay message\");\n }\n return [\"EVENT\", items[1], items[2]];\n\n case \"OK\":\n if (\n items.length !== 4 ||\n typeof items[1] !== \"string\" ||\n typeof items[2] !== \"boolean\" ||\n typeof items[3] !== \"string\"\n ) {\n throw new MessageError(\"invalid OK relay message\");\n }\n return [\"OK\", items[1], items[2], items[3]];\n\n case \"EOSE\":\n if (items.length !== 2 || typeof items[1] !== \"string\") {\n throw new MessageError(\"invalid EOSE relay message\");\n }\n return [\"EOSE\", items[1]];\n\n case \"CLOSED\":\n if (items.length !== 3 || typeof items[1] !== \"string\" || typeof items[2] !== \"string\") {\n throw new MessageError(\"invalid CLOSED relay message\");\n }\n return [\"CLOSED\", items[1], items[2]];\n\n case \"NOTICE\":\n if (items.length !== 2 || typeof items[1] !== \"string\") {\n throw new MessageError(\"invalid NOTICE relay message\");\n }\n return [\"NOTICE\", items[1]];\n\n case \"AUTH\":\n if (items.length !== 2 || typeof items[1] !== \"string\") {\n throw new MessageError(\"invalid AUTH relay message\");\n }\n return [\"AUTH\", items[1]];\n\n case \"COUNT\": {\n const payload = items.at(2);\n const count = isRecord(payload) ? payload[\"count\"] : undefined;\n if (\n items.length !== 3 ||\n typeof items[1] !== \"string\" ||\n !isRecord(payload) ||\n typeof count !== \"number\" ||\n !Number.isSafeInteger(count) ||\n count < 0\n ) {\n throw new MessageError(\"invalid COUNT relay message\");\n }\n const result: Mutable<CountResult> = { count };\n if (typeof payload[\"approximate\"] === \"boolean\") {\n result.approximate = payload[\"approximate\"];\n }\n const hll = parseCountHll(payload[\"hll\"]);\n if (hll !== undefined) {\n result.hll = hll;\n }\n return [\"COUNT\", items[1], result];\n }\n case \"NEG-MSG\":\n if (items.length !== 3 || typeof items[1] !== \"string\" || !isNegHex(items[2])) {\n throw new MessageError(\"invalid NEG-MSG relay message\");\n }\n return [\"NEG-MSG\", items[1], items[2].toLowerCase()];\n\n case \"NEG-ERR\":\n if (\n (items.length !== 3 && items.length !== 4) ||\n typeof items[1] !== \"string\" ||\n typeof items[2] !== \"string\"\n ) {\n throw new MessageError(\"invalid NEG-ERR relay message\");\n }\n return [\"NEG-ERR\", items[1], items[2]];\n\n default:\n throw new MessageError(`unknown relay message type: ${String(type)}`);\n }\n}\n\nfunction parseCountHll(value: unknown): string | undefined {\n if (typeof value !== \"string\" || value.length !== HLL_HEX_LEN || !HEX_RE.test(value)) {\n return undefined;\n }\n return value.toLowerCase();\n}\n\nfunction isWireFilter(value: unknown): value is Filter {\n return isRecord(value);\n}\n\nfunction parseWireFilters(items: unknown[], kind: string): Filter[] {\n const filters: Filter[] = [];\n for (const item of items) {\n if (!isWireFilter(item)) {\n throw new MessageError(`invalid ${kind} filter`);\n }\n filters.push(item);\n }\n return filters;\n}\n\nfunction isNegHex(value: unknown): value is string {\n return (\n typeof value === \"string\" && value.length > 0 && value.length % 2 === 0 && HEX_RE.test(value)\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as EventBuilder } from "./builder-
|
|
1
|
+
import { h as Tag, t as Event } from "./event-j3BwI5dF.mjs";
|
|
2
|
+
import { t as EventBuilder } from "./builder-GBddxj8i.mjs";
|
|
3
3
|
import { a as NostrError } from "./error-BquXDmIN.mjs";
|
|
4
|
-
import { a as Rumor, l as WrapOptions, r as Nip59Crypto } from "./nip59-
|
|
4
|
+
import { a as Rumor, l as WrapOptions, r as Nip59Crypto } from "./nip59-CdDoJptA.mjs";
|
|
5
5
|
//#region src/nips/nip17.d.ts
|
|
6
6
|
declare class Nip17Error extends NostrError {
|
|
7
7
|
name: string;
|
|
@@ -35,4 +35,4 @@ declare function wrapDirectMessage(crypto: Nip59Crypto, recipients: ReadonlyArra
|
|
|
35
35
|
declare function requireDmRelays(pubkey: string, relays: ReadonlyArray<string>): string[];
|
|
36
36
|
//#endregion
|
|
37
37
|
export { buildChatMessageRumor as a, normalizeRecipients as c, wrapDirectMessage as d, ReplyTo as i, parseDmRelayList as l, Nip17Error as n, dmRelayListEventBuilder as o, Recipient as r, dmRelayListToTags as s, ChatMessageOptions as t, requireDmRelays as u };
|
|
38
|
-
//# sourceMappingURL=nip17-
|
|
38
|
+
//# sourceMappingURL=nip17-B7MI82Iq.d.mts.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { t as Event } from "./event-
|
|
2
|
-
import { t as EventBuilder } from "./builder-
|
|
1
|
+
import { t as Event } from "./event-j3BwI5dF.mjs";
|
|
2
|
+
import { t as EventBuilder } from "./builder-GBddxj8i.mjs";
|
|
3
3
|
//#region src/nips/nip51.d.ts
|
|
4
4
|
/**
|
|
5
5
|
* Structural crypto used by NIP-51 private tags. Satisfied by NostrSigner when
|
|
@@ -84,4 +84,4 @@ declare function parseFollowPack(event: Pick<Event, "kind" | "tags">): {
|
|
|
84
84
|
};
|
|
85
85
|
//#endregion
|
|
86
86
|
export { encryptPrivateTags as a, parseEmojiSet as c, parseMuteList as d, parseMuteListPrivate as f, pinListEventBuilder as g, parseUserEmojiList as h, decryptPrivateTags as i, parseFavoriteRelays as l, parseRelaySet as m, Nip51Crypto as n, muteListEventBuilder as o, parsePinList as p, bookmarkListEventBuilder as r, parseBookmarkList as s, MuteItem as t, parseFollowPack as u };
|
|
87
|
-
//# sourceMappingURL=nip51-
|
|
87
|
+
//# sourceMappingURL=nip51-O_vhOiK2.d.mts.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { h as Tag, r as UnsignedEvent, t as Event } from "./event-j3BwI5dF.mjs";
|
|
2
2
|
import { a as NostrError } from "./error-BquXDmIN.mjs";
|
|
3
3
|
//#region src/nips/nip59.d.ts
|
|
4
4
|
/** Unsigned event with a computed id. Never has `sig`. */
|
|
@@ -82,4 +82,4 @@ declare function wrap(crypto: Nip59Crypto, recipient: string, rumor: Rumor, opts
|
|
|
82
82
|
declare function unwrap(crypto: Nip44Decryptor, giftWrap: Event): Promise<Rumor>;
|
|
83
83
|
//#endregion
|
|
84
84
|
export { requireNip59Crypto as _, Rumor as a, wrap as b, TimestampRandomize as c, createRumor as d, createSeal as f, requireNip44Decryptor as g, randomPastTimestamp as h, Nip59Error as i, WrapOptions as l, isGiftWrapKind as m, Nip44Decryptor as n, SealOptions as o, eventToJson as p, Nip59Crypto as r, TWO_DAYS_SECS as s, GiftWrapTimestamps as t, createGiftWrap as u, rumorToJson as v, unwrap as y };
|
|
85
|
-
//# sourceMappingURL=nip59-
|
|
85
|
+
//# sourceMappingURL=nip59-CdDoJptA.d.mts.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as EventBuilder } from "./builder-
|
|
1
|
+
import { h as Tag, t as Event } from "./event-j3BwI5dF.mjs";
|
|
2
|
+
import { t as EventBuilder } from "./builder-GBddxj8i.mjs";
|
|
3
3
|
//#region src/nips/nip65.d.ts
|
|
4
4
|
/** NIP-65 `r` tag marker: read-only, write-only, or unmarked (both). */
|
|
5
5
|
type RelayMarker = "read" | "write" | "both";
|
|
@@ -20,4 +20,4 @@ declare function readRelays(items: ReadonlyArray<RelayListItem>): string[];
|
|
|
20
20
|
declare function writeRelays(items: ReadonlyArray<RelayListItem>): string[];
|
|
21
21
|
//#endregion
|
|
22
22
|
export { relayListEventBuilder as a, readRelays as i, RelayMarker as n, relayListToTags as o, parseRelayList as r, writeRelays as s, RelayListItem as t };
|
|
23
|
-
//# sourceMappingURL=nip65-
|
|
23
|
+
//# sourceMappingURL=nip65-BL79HI8N.d.mts.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as Event } from "./event-
|
|
1
|
+
import { t as Event } from "./event-j3BwI5dF.mjs";
|
|
2
2
|
import { a as NostrError } from "./error-BquXDmIN.mjs";
|
|
3
3
|
//#region src/nips/nip77.d.ts
|
|
4
4
|
declare const PROTOCOL_VERSION = 97;
|
|
@@ -52,4 +52,4 @@ declare function runNegSession(opts: {
|
|
|
52
52
|
}>;
|
|
53
53
|
//#endregion
|
|
54
54
|
export { NegentropyStorageVector as a, ReconcileOutcome as c, storageFromItems as d, Negentropy as i, runNegSession as l, MAX_NEG_ROUNDS as n, Nip77Error as o, NegItem as r, PROTOCOL_VERSION as s, DEFAULT_FRAME_SIZE_LIMIT as t, storageFromEvents as u };
|
|
55
|
-
//# sourceMappingURL=nip77-
|
|
55
|
+
//# sourceMappingURL=nip77-wHA_nEV5.d.mts.map
|
package/dist/nips/blossom.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { n as EventTemplate, t as Event } from "../event-
|
|
2
|
-
import { t as EventBuilder } from "../builder-
|
|
1
|
+
import { n as EventTemplate, t as Event } from "../event-j3BwI5dF.mjs";
|
|
2
|
+
import { t as EventBuilder } from "../builder-GBddxj8i.mjs";
|
|
3
3
|
import { a as NostrError } from "../error-BquXDmIN.mjs";
|
|
4
|
-
import { t as ManualFetch } from "../http-
|
|
4
|
+
import { t as ManualFetch } from "../http-kwWG-V1X.mjs";
|
|
5
5
|
//#region src/nips/blossom.d.ts
|
|
6
6
|
export type BlobDescriptor = {
|
|
7
7
|
readonly url: string;
|
package/dist/nips/blossom.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { c as isRecord, d as nowSeconds, h as EventValidationError, i as bytesToHex, n as assertHex32, p as utf8Encoder, v as NostrError } from "../util-DMF9AIO0.mjs";
|
|
2
|
-
import { t as Kind } from "../kind-
|
|
3
|
-
import { t as EventBuilder } from "../builder-
|
|
2
|
+
import { t as Kind } from "../kind-D8fENiiL.mjs";
|
|
3
|
+
import { t as EventBuilder } from "../builder-CVRmUeNm.mjs";
|
|
4
4
|
import { n as requireGlobalFetch, r as sendManual, t as fetchManual } from "../http-CuazNRIP.mjs";
|
|
5
5
|
import { sha256 } from "@noble/hashes/sha2.js";
|
|
6
6
|
import { base64urlnopad } from "@scure/base";
|
package/dist/nips/nip05.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { a as NostrError } from "../error-BquXDmIN.mjs";
|
|
2
2
|
import { f as ProfilePointer } from "../nip19-DpPN17bY.mjs";
|
|
3
|
-
import { t as ManualFetch } from "../http-
|
|
3
|
+
import { t as ManualFetch } from "../http-kwWG-V1X.mjs";
|
|
4
4
|
//#region src/nips/nip05.d.ts
|
|
5
5
|
/** Root local-part (`_@domain` rendered as just the domain). */
|
|
6
6
|
export declare const NIP05_ROOT_LOCAL = "_";
|
package/dist/nips/nip10.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as EventBuilder } from "../builder-
|
|
1
|
+
import { h as Tag, t as Event } from "../event-j3BwI5dF.mjs";
|
|
2
|
+
import { t as EventBuilder } from "../builder-GBddxj8i.mjs";
|
|
3
3
|
import { f as ProfilePointer, i as EventPointer, t as AddressPointer } from "../nip19-DpPN17bY.mjs";
|
|
4
4
|
//#region src/nips/nip10.d.ts
|
|
5
5
|
/** Parsed NIP-10 thread references from an event's `e`/`q`/`p` tags. */
|
package/dist/nips/nip10.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { h as EventValidationError, o as isHex32 } from "../util-DMF9AIO0.mjs";
|
|
2
|
-
import { t as Kind } from "../kind-
|
|
3
|
-
import {
|
|
4
|
-
import { t as EventBuilder } from "../builder-
|
|
2
|
+
import { t as Kind } from "../kind-D8fENiiL.mjs";
|
|
3
|
+
import { S as parseEventAddress, g as Tag, y as formatEventAddress } from "../event-C2eLiPpV.mjs";
|
|
4
|
+
import { t as EventBuilder } from "../builder-CVRmUeNm.mjs";
|
|
5
5
|
//#region src/nips/nip10.ts
|
|
6
6
|
/**
|
|
7
7
|
* NIP-10: Text Notes and Threads
|
package/dist/nips/nip11.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as NostrError } from "../error-BquXDmIN.mjs";
|
|
2
|
-
import { t as ManualFetch } from "../http-
|
|
2
|
+
import { t as ManualFetch } from "../http-kwWG-V1X.mjs";
|
|
3
3
|
//#region src/nips/nip11.d.ts
|
|
4
4
|
export type Nip11Fetch = ManualFetch;
|
|
5
5
|
export type RelayInformation = {
|
package/dist/nips/nip13.d.mts
CHANGED
package/dist/nips/nip17.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as buildChatMessageRumor, c as normalizeRecipients, d as wrapDirectMessage, i as ReplyTo, l as parseDmRelayList, n as Nip17Error, o as dmRelayListEventBuilder, r as Recipient, s as dmRelayListToTags, t as ChatMessageOptions, u as requireDmRelays } from "../nip17-
|
|
1
|
+
import { a as buildChatMessageRumor, c as normalizeRecipients, d as wrapDirectMessage, i as ReplyTo, l as parseDmRelayList, n as Nip17Error, o as dmRelayListEventBuilder, r as Recipient, s as dmRelayListToTags, t as ChatMessageOptions, u as requireDmRelays } from "../nip17-B7MI82Iq.mjs";
|
|
2
2
|
export { ChatMessageOptions, Nip17Error, Recipient, ReplyTo, buildChatMessageRumor, dmRelayListEventBuilder, dmRelayListToTags, normalizeRecipients, parseDmRelayList, requireDmRelays, wrapDirectMessage };
|
package/dist/nips/nip17.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { h as EventValidationError, l as normalizeRelayUrls, n as assertHex32, v as NostrError } from "../util-DMF9AIO0.mjs";
|
|
2
|
-
import { t as Kind } from "../kind-
|
|
3
|
-
import {
|
|
4
|
-
import { t as EventBuilder } from "../builder-
|
|
2
|
+
import { t as Kind } from "../kind-D8fENiiL.mjs";
|
|
3
|
+
import { g as Tag } from "../event-C2eLiPpV.mjs";
|
|
4
|
+
import { t as EventBuilder } from "../builder-CVRmUeNm.mjs";
|
|
5
5
|
import { createGiftWrap, createRumor, createSeal } from "./nip59.mjs";
|
|
6
6
|
//#region src/nips/nip17.ts
|
|
7
7
|
/**
|
package/dist/nips/nip27.d.mts
CHANGED
package/dist/nips/nip42.d.mts
CHANGED
package/dist/nips/nip42.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { d as nowSeconds } from "../util-DMF9AIO0.mjs";
|
|
2
|
-
import { t as Kind } from "../kind-
|
|
2
|
+
import { t as Kind } from "../kind-D8fENiiL.mjs";
|
|
3
3
|
//#region src/nips/nip42.ts
|
|
4
4
|
/**
|
|
5
5
|
* Build an unsigned NIP-42 AUTH event template for the given relay challenge. Caller must sign with
|
package/dist/nips/nip51.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as encryptPrivateTags, c as parseEmojiSet, d as parseMuteList, f as parseMuteListPrivate, g as pinListEventBuilder, h as parseUserEmojiList, i as decryptPrivateTags, l as parseFavoriteRelays, m as parseRelaySet, n as Nip51Crypto, o as muteListEventBuilder, p as parsePinList, r as bookmarkListEventBuilder, s as parseBookmarkList, t as MuteItem, u as parseFollowPack } from "../nip51-
|
|
1
|
+
import { a as encryptPrivateTags, c as parseEmojiSet, d as parseMuteList, f as parseMuteListPrivate, g as pinListEventBuilder, h as parseUserEmojiList, i as decryptPrivateTags, l as parseFavoriteRelays, m as parseRelaySet, n as Nip51Crypto, o as muteListEventBuilder, p as parsePinList, r as bookmarkListEventBuilder, s as parseBookmarkList, t as MuteItem, u as parseFollowPack } from "../nip51-O_vhOiK2.mjs";
|
|
2
2
|
export { MuteItem, Nip51Crypto, bookmarkListEventBuilder, decryptPrivateTags, encryptPrivateTags, muteListEventBuilder, parseBookmarkList, parseEmojiSet, parseFavoriteRelays, parseFollowPack, parseMuteList, parseMuteListPrivate, parsePinList, parseRelaySet, parseUserEmojiList, pinListEventBuilder };
|
package/dist/nips/nip51.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { h as EventValidationError, l as normalizeRelayUrls, n as assertHex32, o as isHex32 } from "../util-DMF9AIO0.mjs";
|
|
2
|
-
import { t as Kind } from "../kind-
|
|
3
|
-
import {
|
|
4
|
-
import { t as EventBuilder } from "../builder-
|
|
2
|
+
import { t as Kind } from "../kind-D8fENiiL.mjs";
|
|
3
|
+
import { b as getDTag, g as Tag, v as firstTagValue, x as isTag } from "../event-C2eLiPpV.mjs";
|
|
4
|
+
import { t as EventBuilder } from "../builder-CVRmUeNm.mjs";
|
|
5
5
|
//#region src/nips/nip51.ts
|
|
6
6
|
/**
|
|
7
7
|
* NIP-51: Lists Public tags plus NIP-44 private `.content` (author encrypts to self). Crypto is
|
package/dist/nips/nip57.d.mts
CHANGED
package/dist/nips/nip57.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { a as hexToBytes, d as nowSeconds, h as EventValidationError, p as utf8Encoder } from "../util-DMF9AIO0.mjs";
|
|
2
|
-
import { r as isAddressableKind, t as Kind } from "../kind-
|
|
3
|
-
import {
|
|
4
|
-
import { n as verifyEvent } from "../verifier-
|
|
2
|
+
import { r as isAddressableKind, t as Kind } from "../kind-D8fENiiL.mjs";
|
|
3
|
+
import { S as parseEventAddress, _ as eventAddress, b as getDTag, g as Tag, h as validateSignedEvent, v as firstTagValue } from "../event-C2eLiPpV.mjs";
|
|
4
|
+
import { n as verifyEvent } from "../verifier-uC_jd-Nw.mjs";
|
|
5
5
|
import { sha256 } from "@noble/hashes/sha2.js";
|
|
6
6
|
import { bech32 } from "@scure/base";
|
|
7
7
|
import { equalBytes } from "@noble/ciphers/utils.js";
|
package/dist/nips/nip59.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { _ as requireNip59Crypto, a as Rumor, b as wrap, c as TimestampRandomize, d as createRumor, f as createSeal, g as requireNip44Decryptor, h as randomPastTimestamp, i as Nip59Error, l as WrapOptions, m as isGiftWrapKind, n as Nip44Decryptor, o as SealOptions, p as eventToJson, r as Nip59Crypto, s as TWO_DAYS_SECS, t as GiftWrapTimestamps, u as createGiftWrap, v as rumorToJson, y as unwrap } from "../nip59-
|
|
1
|
+
import { _ as requireNip59Crypto, a as Rumor, b as wrap, c as TimestampRandomize, d as createRumor, f as createSeal, g as requireNip44Decryptor, h as randomPastTimestamp, i as Nip59Error, l as WrapOptions, m as isGiftWrapKind, n as Nip44Decryptor, o as SealOptions, p as eventToJson, r as Nip59Crypto, s as TWO_DAYS_SECS, t as GiftWrapTimestamps, u as createGiftWrap, v as rumorToJson, y as unwrap } from "../nip59-CdDoJptA.mjs";
|
|
2
2
|
export { GiftWrapTimestamps, Nip44Decryptor, Nip59Crypto, Nip59Error, Rumor, SealOptions, TWO_DAYS_SECS, TimestampRandomize, WrapOptions, createGiftWrap, createRumor, createSeal, eventToJson, isGiftWrapKind, randomPastTimestamp, requireNip44Decryptor, requireNip59Crypto, rumorToJson, unwrap, wrap };
|
package/dist/nips/nip59.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { c as isRecord, d as nowSeconds, n as assertHex32, v as NostrError } from "../util-DMF9AIO0.mjs";
|
|
2
|
-
import { t as Kind } from "../kind-
|
|
3
|
-
import {
|
|
4
|
-
import { r as finalizeEvent, t as Keys } from "../key-
|
|
5
|
-
import { n as verifyEvent } from "../verifier-
|
|
2
|
+
import { t as Kind } from "../kind-D8fENiiL.mjs";
|
|
3
|
+
import { g as Tag, h as validateSignedEvent, m as validateEvent, n as getEventHash } from "../event-C2eLiPpV.mjs";
|
|
4
|
+
import { r as finalizeEvent, t as Keys } from "../key-DY_HEIpY.mjs";
|
|
5
|
+
import { n as verifyEvent } from "../verifier-uC_jd-Nw.mjs";
|
|
6
6
|
import { encryptToPubkey } from "./nip44.mjs";
|
|
7
7
|
import { randomBytes } from "@noble/hashes/utils.js";
|
|
8
8
|
//#region src/nips/nip59.ts
|
package/dist/nips/nip65.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as relayListEventBuilder, i as readRelays, n as RelayMarker, o as relayListToTags, r as parseRelayList, s as writeRelays, t as RelayListItem } from "../nip65-
|
|
1
|
+
import { a as relayListEventBuilder, i as readRelays, n as RelayMarker, o as relayListToTags, r as parseRelayList, s as writeRelays, t as RelayListItem } from "../nip65-BL79HI8N.mjs";
|
|
2
2
|
export { RelayListItem, RelayMarker, parseRelayList, readRelays, relayListEventBuilder, relayListToTags, writeRelays };
|
package/dist/nips/nip65.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { h as EventValidationError, u as normalizeURL } from "../util-DMF9AIO0.mjs";
|
|
2
|
-
import { t as Kind } from "../kind-
|
|
3
|
-
import { t as EventBuilder } from "../builder-
|
|
2
|
+
import { t as Kind } from "../kind-D8fENiiL.mjs";
|
|
3
|
+
import { t as EventBuilder } from "../builder-CVRmUeNm.mjs";
|
|
4
4
|
//#region src/nips/nip65.ts
|
|
5
5
|
/** Parse a kind:10002 NIP-65 event into relay list entries. */
|
|
6
6
|
function parseRelayList(event) {
|
package/dist/nips/nip77.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as NegentropyStorageVector, c as ReconcileOutcome, d as storageFromItems, i as Negentropy, l as runNegSession, n as MAX_NEG_ROUNDS, o as Nip77Error, r as NegItem, s as PROTOCOL_VERSION, t as DEFAULT_FRAME_SIZE_LIMIT, u as storageFromEvents } from "../nip77-
|
|
1
|
+
import { a as NegentropyStorageVector, c as ReconcileOutcome, d as storageFromItems, i as Negentropy, l as runNegSession, n as MAX_NEG_ROUNDS, o as Nip77Error, r as NegItem, s as PROTOCOL_VERSION, t as DEFAULT_FRAME_SIZE_LIMIT, u as storageFromEvents } from "../nip77-wHA_nEV5.mjs";
|
|
2
2
|
export { DEFAULT_FRAME_SIZE_LIMIT, MAX_NEG_ROUNDS, NegItem, Negentropy, NegentropyStorageVector, Nip77Error, PROTOCOL_VERSION, ReconcileOutcome, runNegSession, storageFromEvents, storageFromItems };
|
package/dist/nips/nip77.mjs
CHANGED
|
@@ -248,11 +248,14 @@ var Negentropy = class {
|
|
|
248
248
|
fullOutput.extend(new Uint8Array([97]));
|
|
249
249
|
const protocolVersion = query.read();
|
|
250
250
|
if (protocolVersion < 96 || protocolVersion > 111) throw new Nip77Error("invalid negentropy protocol version byte");
|
|
251
|
-
if (protocolVersion !== 97)
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
251
|
+
if (protocolVersion !== 97) {
|
|
252
|
+
if (this.#initiator) throw new Nip77Error(`unsupported negentropy protocol version ${protocolVersion - 96} (peer), we speak 1`);
|
|
253
|
+
return {
|
|
254
|
+
have,
|
|
255
|
+
need,
|
|
256
|
+
nextMessage: bytesToHex(fullOutput.unwrap())
|
|
257
|
+
};
|
|
258
|
+
}
|
|
256
259
|
const storageSize = this.#storage.size();
|
|
257
260
|
let prevBound = this.#bound(0);
|
|
258
261
|
let prevIndex = 0;
|