UNPKG

@nostr-dev-kit/ndk-svelte

Version:

This package provides convenience functionalities to make usage of NDK with Svelte nicer.

196 lines (195 loc) 5.84 kB
// src/index.ts import NDK, { NDKEvent, NDKKind, NDKRepost } from "@nostr-dev-kit/ndk"; import { writable } from "svelte/store"; var NDKSvelte = class extends NDK { createEventStore(filters) { const store = writable([]); return { id: Math.random().toString(36).substring(7), refCount: 0, filters, skipDeleted: true, subscription: void 0, eosed: false, set: store.set, update: store.update, subscribe: store.subscribe, unsubscribe: () => { }, onEose: (_cb) => { }, onEvent: (_cb) => { }, startSubscription: () => { throw new Error("not implemented"); }, ref: () => { throw new Error("not implemented"); }, unref: () => { throw new Error("not implemented"); }, empty: () => { throw new Error("not implemented"); }, changeFilters: (_filters) => { throw new Error("not implemented"); } }; } eventIsRepost(event) { return [NDKKind.Repost, NDKKind.GenericRepost].includes(event.kind); } storeSubscribe(filters, opts, klass) { let events = /* @__PURE__ */ new Map(); const store = this.createEventStore(Array.isArray(filters) ? filters : [filters]); const autoStart = opts?.autoStart ?? true; const relaySet = opts?.relaySet; const skipDeleted = opts?.skipDeleted ?? true; const deletedPRETimestamps = /* @__PURE__ */ new Map(); const getEventArrayFromMap = () => { return Array.from(events.values()); }; const handleEventReposts = (event) => { const _repostEvent = NDKRepost.from(event); _repostEvent.ndk = this; const addRepostToExistingEvent = (repostedEvent) => { if (repostedEvent.repostedByEvents) { repostedEvent.repostedByEvents.push(event); } else { repostedEvent.repostedByEvents = [event]; } store.set(getEventArrayFromMap()); }; for (const repostedEventId of _repostEvent.repostedEventIds()) { const repostedEvent = events.get(repostedEventId); if (repostedEvent) { addRepostToExistingEvent(repostedEvent); } else { _repostEvent.repostedEvents(klass, { subId: "reposted-event-fetch", groupable: true, groupableDelay: 1500, groupableDelayType: "at-least" }).then((fetchedEvents) => { for (const e of fetchedEvents) { if (e instanceof NDKEvent) { handleEvent(e); } } }); } } }; const handleEvent = (event) => { if (opts?.repostsFilters && this.eventIsRepost(event)) { handleEventReposts(event); return; } let e = event; if (klass) { const ev = klass.from(event); if (!ev) return; e = ev; e.relay = event.relay; } e.ndk = this; const dedupKey = event.deduplicationKey(); if (events.has(dedupKey)) { const prevEvent = events.get(dedupKey); if (prevEvent.created_at > event.created_at) return; if (prevEvent.created_at === event.created_at) { if (prevEvent.id === event.id) return; console.warn("Received event with same created_at but different id", { prevId: prevEvent.id, newId: event.id, prev: prevEvent.rawEvent(), new: event.rawEvent() }); } } if (skipDeleted && event.isParamReplaceable()) { const currentDeletedTimestamp = deletedPRETimestamps.get(dedupKey); if (currentDeletedTimestamp && currentDeletedTimestamp > event.created_at) return; const isDeleted = event.hasTag("deleted"); if (isDeleted) { deletedPRETimestamps.set(dedupKey, event.created_at); return; } deletedPRETimestamps.delete(dedupKey); } events.set(dedupKey, e); store.set(getEventArrayFromMap()); }; store.ref = () => { store.refCount++; if (store.refCount === 1) { store.startSubscription(); } return store.refCount; }; store.unref = () => { if (--store.refCount > 0) return store.refCount; if (opts?.unrefUnsubscribeTimeout) { setTimeout(() => { if (store.refCount === 0) { store.unsubscribe(); } }, opts.unrefUnsubscribeTimeout); } else { store.unsubscribe(); } return store.refCount; }; store.empty = () => { store.set([]); events = /* @__PURE__ */ new Map(); store.unsubscribe(); }; store.changeFilters = (filters2) => { store.filters = filters2; store.empty(); if (store.refCount > 0) store.startSubscription(); }; store.startSubscription = () => { if (!store.filters) { throw new Error("no filters"); } const filters2 = store.filters; if (opts?.repostsFilters) { filters2.push(...opts.repostsFilters); } store.subscription = this.subscribe(filters2, { ...opts, relaySet }, false); store.subscription.on("event", (event, relay) => { handleEvent(event); if (opts?.onEvent) opts.onEvent(event, relay); }); store.subscription.start(); store.unsubscribe = () => { store.subscription?.stop(); store.subscription = void 0; }; store.onEose = (cb) => { store.subscription?.on("eose", () => { store.eosed = true; cb(); }); }; if (opts?.onEose) { store.onEose(opts.onEose); } }; if (autoStart) { store.startSubscription(); } return store; } }; var index_default = NDKSvelte; export { index_default as default };