diff --git a/src/lib/utils/nostrUtils.ts b/src/lib/utils/nostrUtils.ts
index 5faa1bb..3d67c57 100644
--- a/src/lib/utils/nostrUtils.ts
+++ b/src/lib/utils/nostrUtils.ts
@@ -12,8 +12,6 @@ import { schnorr } from "@noble/curves/secp256k1";
import { bytesToHex } from "@noble/hashes/utils";
import { wellKnownUrl } from "./search_utility.ts";
import { VALIDATION } from "./search_constants.ts";
-import { error } from "@sveltejs/kit";
-import { naddrDecode, neventDecode } from "../utils.ts";
const badgeCheckSvg =
'';
@@ -673,84 +671,3 @@ export function prefixNostrAddresses(content: string): string {
return `nostr:${match}`;
});
}
-
-// Added functions for fetching events by various identifiers
-
-/**
- * Fetches an event by hex ID, throwing a SvelteKit 404 error if not found.
- */
-export async function fetchEventById(ndk: NDK, id: string): Promise {
- try {
- const event = await fetchEventWithFallback(ndk, id);
- if (!event) {
- throw error(404, `Event not found for ID: ${id}`);
- }
- return event;
- } catch (err) {
- if (err && typeof err === "object" && "status" in err) {
- throw err;
- }
- throw error(404, `Failed to fetch event by ID: ${err}`);
- }
-}
-
-/**
- * Fetches an event by d tag, throwing a 404 if not found.
- */
-export async function fetchEventByDTag(ndk: NDK, dTag: string): Promise {
- try {
- const event = await fetchEventWithFallback(ndk, { "#d": [dTag], limit: 1 });
- if (!event) {
- throw error(404, `Event not found for d-tag: ${dTag}`);
- }
- return event;
- } catch (err) {
- if (err && typeof err === "object" && "status" in err) {
- throw err;
- }
- throw error(404, `Failed to fetch event by d-tag: ${err}`);
- }
-}
-
-/**
- * Fetches an event by naddr identifier.
- */
-export async function fetchEventByNaddr(ndk: NDK, naddr: string): Promise {
- try {
- const decoded = naddrDecode(naddr);
- const filter = {
- kinds: [decoded.kind],
- authors: [decoded.pubkey],
- "#d": [decoded.identifier],
- };
- const event = await fetchEventWithFallback(ndk, filter);
- if (!event) {
- throw error(404, `Event not found for naddr: ${naddr}`);
- }
- return event;
- } catch (err) {
- if (err && typeof err === "object" && "status" in err) {
- throw err;
- }
- throw error(404, `Failed to fetch event by naddr: ${err}`);
- }
-}
-
-/**
- * Fetches an event by nevent identifier.
- */
-export async function fetchEventByNevent(ndk: NDK, nevent: string): Promise {
- try {
- const decoded = neventDecode(nevent);
- const event = await fetchEventWithFallback(ndk, decoded.id);
- if (!event) {
- throw error(404, `Event not found for nevent: ${nevent}`);
- }
- return event;
- } catch (err) {
- if (err && typeof err === "object" && "status" in err) {
- throw err;
- }
- throw error(404, `Failed to fetch event by nevent: ${err}`);
- }
-}
diff --git a/src/lib/utils/websocket_utils.ts b/src/lib/utils/websocket_utils.ts
new file mode 100644
index 0000000..9d0d382
--- /dev/null
+++ b/src/lib/utils/websocket_utils.ts
@@ -0,0 +1,143 @@
+import { WebSocketPool } from "../data_structures/websocket_pool.ts";
+import { error } from "@sveltejs/kit";
+import { naddrDecode, neventDecode } from "../utils.ts";
+
+export interface NostrEvent {
+ id: string;
+ pubkey: string;
+ created_at: number;
+ kind: number;
+ tags: string[][];
+ content: string;
+ sig: string;
+}
+
+export interface NostrFilter {
+ ids?: string[];
+ authors?: string[];
+ kinds?: number[];
+ [tag: `#${string}`]: string[] | undefined;
+ since?: number;
+ until?: number;
+ limit?: number;
+}
+
+export async function fetchNostrEvent(filter: NostrFilter): Promise {
+ // TODO: Improve relay selection when relay management is implemented.
+ const ws = await WebSocketPool.instance.acquire("wss://thecitadel.nostr1.com");
+ const subId = crypto.randomUUID();
+
+ const res = new Promise((resolve, reject) => {
+ ws.addEventListener("message", (ev) => {
+ const data = JSON.parse(ev.data);
+
+ if (data[1] !== subId) {
+ return;
+ }
+
+ switch (data[0]) {
+ case "EVENT":
+ break;
+ case "CLOSED":
+ reject(new Error(`[WebSocket Utils]: Subscription ${subId} closed`));
+ break;
+ case "EOSE":
+ resolve(null);
+ break;
+ }
+
+ const event = data[2] as NostrEvent;
+ if (!event) {
+ return;
+ }
+
+ resolve(event);
+ });
+
+ ws.addEventListener("error", (ev) => {
+ reject(ev);
+ });
+ }).withTimeout(2000);
+
+ ws.send(JSON.stringify(["REQ", subId, filter]));
+ return res;
+}
+
+/**
+ * Fetches an event by hex ID, throwing a SvelteKit 404 error if not found.
+ */
+export async function fetchEventById(id: string): Promise {
+ try {
+ const event = await fetchNostrEvent({ ids: [id], limit: 1 });
+ if (!event) {
+ throw error(404, `Event not found for ID: ${id}`);
+ }
+ return event;
+ } catch (err) {
+ if (err && typeof err === "object" && "status" in err) {
+ throw err;
+ }
+ throw error(404, `Failed to fetch event by ID: ${err}`);
+ }
+}
+
+/**
+ * Fetches an event by d tag, throwing a 404 if not found.
+ */
+export async function fetchEventByDTag(dTag: string): Promise {
+ try {
+ const event = await fetchNostrEvent({ "#d": [dTag], limit: 1 });
+ if (!event) {
+ throw error(404, `Event not found for d-tag: ${dTag}`);
+ }
+ return event;
+ } catch (err) {
+ if (err && typeof err === "object" && "status" in err) {
+ throw err;
+ }
+ throw error(404, `Failed to fetch event by d-tag: ${err}`);
+ }
+}
+
+/**
+ * Fetches an event by naddr identifier.
+ */
+export async function fetchEventByNaddr(naddr: string): Promise {
+ try {
+ const decoded = naddrDecode(naddr);
+ const filter = {
+ kinds: [decoded.kind],
+ authors: [decoded.pubkey],
+ "#d": [decoded.identifier],
+ };
+ const event = await fetchNostrEvent(filter);
+ if (!event) {
+ throw error(404, `Event not found for naddr: ${naddr}`);
+ }
+ return event;
+ } catch (err) {
+ if (err && typeof err === "object" && "status" in err) {
+ throw err;
+ }
+ throw error(404, `Failed to fetch event by naddr: ${err}`);
+ }
+}
+
+/**
+ * Fetches an event by nevent identifier.
+ */
+export async function fetchEventByNevent(nevent: string): Promise {
+ try {
+ const decoded = neventDecode(nevent);
+ const event = await fetchNostrEvent({ ids: [decoded.id], limit: 1 });
+ if (!event) {
+ throw error(404, `Event not found for nevent: ${nevent}`);
+ }
+ return event;
+ } catch (err) {
+ if (err && typeof err === "object" && "status" in err) {
+ throw err;
+ }
+ throw error(404, `Failed to fetch event by nevent: ${err}`);
+ }
+}
diff --git a/src/routes/publication/[type]/[identifier]/+layout.server.ts b/src/routes/publication/[type]/[identifier]/+layout.server.ts
index 2c6bebe..b89da64 100644
--- a/src/routes/publication/[type]/[identifier]/+layout.server.ts
+++ b/src/routes/publication/[type]/[identifier]/+layout.server.ts
@@ -1,44 +1,35 @@
import { error } from "@sveltejs/kit";
import type { LayoutServerLoad } from "./$types";
-import type { NDKEvent } from "@nostr-dev-kit/ndk";
-import { getMatchingTags, fetchEventById, fetchEventByDTag, fetchEventByNaddr, fetchEventByNevent } from "../../../../lib/utils/nostrUtils.ts";
+import { fetchEventByDTag, fetchEventById, fetchEventByNaddr, fetchEventByNevent, NostrEvent } from "../../../../lib/utils/websocket_utils.ts";
-export const load: LayoutServerLoad = async ({ params, parent, url }) => {
+export const load: LayoutServerLoad = async ({ params, url }) => {
const { type, identifier } = params;
- // TODO: Remove the need for NDK in nostrUtils dependencies, since NDK is not available on the server.
- // deno-lint-ignore no-explicit-any
- const { ndk } = (await parent()) as any;
-
- if (!ndk) {
- throw error(500, "NDK not available");
- }
-
- let indexEvent: NDKEvent;
+ let indexEvent: NostrEvent;
// Handle different identifier types
switch (type) {
case 'id':
- indexEvent = await fetchEventById(ndk, identifier);
+ indexEvent = await fetchEventById(identifier);
break;
case 'd':
- indexEvent = await fetchEventByDTag(ndk, identifier);
+ indexEvent = await fetchEventByDTag(identifier);
break;
case 'naddr':
- indexEvent = await fetchEventByNaddr(ndk, identifier);
+ indexEvent = await fetchEventByNaddr(identifier);
break;
case 'nevent':
- indexEvent = await fetchEventByNevent(ndk, identifier);
+ indexEvent = await fetchEventByNevent(identifier);
break;
default:
throw error(400, `Unsupported identifier type: ${type}`);
}
// Extract metadata for meta tags
- const title = getMatchingTags(indexEvent, "title")[0]?.[1] || "Alexandria Publication";
- const summary = getMatchingTags(indexEvent, "summary")[0]?.[1] ||
+ const title = indexEvent.tags.find((tag) => tag[0] === "title")?.[1] || "Alexandria Publication";
+ const summary = indexEvent.tags.find((tag) => tag[0] === "summary")?.[1] ||
"Alexandria is a digital library, utilizing Nostr events for curated publications and wiki pages.";
- const image = getMatchingTags(indexEvent, "image")[0]?.[1] || "/screenshots/old_books.jpg";
+ const image = indexEvent.tags.find((tag) => tag[0] === "image")?.[1] || "/screenshots/old_books.jpg";
const currentUrl = `${url.origin}${url.pathname}`;
return {
diff --git a/src/routes/publication/[type]/[identifier]/+page.server.ts b/src/routes/publication/[type]/[identifier]/+page.server.ts
index 95b58fe..18a5e41 100644
--- a/src/routes/publication/[type]/[identifier]/+page.server.ts
+++ b/src/routes/publication/[type]/[identifier]/+page.server.ts
@@ -1,42 +1,38 @@
import { error } from "@sveltejs/kit";
import type { PageServerLoad } from "./$types";
-import type { NDKEvent } from "@nostr-dev-kit/ndk";
-import { getMatchingTags, fetchEventById, fetchEventByDTag, fetchEventByNaddr, fetchEventByNevent } from "../../../../lib/utils/nostrUtils.ts";
+import { fetchEventByDTag, fetchEventById, fetchEventByNaddr, fetchEventByNevent, NostrEvent } from "../../../../lib/utils/websocket_utils.ts";
-export const load: PageServerLoad = async ({ params, parent }) => {
+export const load: PageServerLoad = async ({ params }) => {
const { type, identifier } = params;
- // deno-lint-ignore no-explicit-any
- const { ndk } = (await parent()) as any;
- if (!ndk) {
- throw error(500, "NDK not available");
- }
-
- let indexEvent: NDKEvent;
+ let indexEvent: NostrEvent | null;
// Handle different identifier types
switch (type) {
case 'id':
- indexEvent = await fetchEventById(ndk, identifier);
+ indexEvent = await fetchEventById(identifier);
break;
case 'd':
- indexEvent = await fetchEventByDTag(ndk, identifier);
+ indexEvent = await fetchEventByDTag(identifier);
break;
case 'naddr':
- indexEvent = await fetchEventByNaddr(ndk, identifier);
+ indexEvent = await fetchEventByNaddr(identifier);
break;
case 'nevent':
- indexEvent = await fetchEventByNevent(ndk, identifier);
+ indexEvent = await fetchEventByNevent(identifier);
break;
default:
throw error(400, `Unsupported identifier type: ${type}`);
}
- const publicationType = getMatchingTags(indexEvent, "type")[0]?.[1];
+ if (!indexEvent) {
+ throw error(404, `Event not found for ${type}: ${identifier}`);
+ }
+
+ const publicationType = indexEvent.tags.find((tag) => tag[0] === "type")?.[1] ?? "";
return {
publicationType,
indexEvent,
- ndk, // Pass ndk to the page for the publication tree
};
};
\ No newline at end of file
diff --git a/src/routes/publication/[type]/[identifier]/+page.svelte b/src/routes/publication/[type]/[identifier]/+page.svelte
index 07cf547..9b786a8 100644
--- a/src/routes/publication/[type]/[identifier]/+page.svelte
+++ b/src/routes/publication/[type]/[identifier]/+page.svelte
@@ -1,6 +1,5 @@