80 lines
2.8 KiB
TypeScript
80 lines
2.8 KiB
TypeScript
import { fetchRelayInformation } from '@nostr-dev-kit/ndk';
|
|
import type NDK from '@nostr-dev-kit/ndk';
|
|
import type { NDKRelay } from '@nostr-dev-kit/ndk';
|
|
import type { RelayConnection, RelayConnectionEvent } from './relay-manager';
|
|
import type { RelayInformation } from '$lib/types/relay';
|
|
|
|
/**
|
|
* adapts an NDKRelay (from the shared pool) to the driver-agnostic
|
|
* RelayConnection interface the RelayManager leans on. keeping this thin adapter
|
|
* separate means the manager's logic never imports ndk directly.
|
|
*/
|
|
class NdkRelayConnection implements RelayConnection {
|
|
private readonly relay: NDKRelay;
|
|
/** ndk runs its own reconnection loop; the manager mustn't add a second. */
|
|
readonly selfReconnecting = true;
|
|
|
|
constructor(
|
|
public readonly url: string,
|
|
ndk: NDK
|
|
) {
|
|
// `getRelay(url, false)` returns (or creates) the pool relay without
|
|
// eagerly connecting — we call connect() ourselves.
|
|
this.relay = ndk.pool.getRelay(url, false, false);
|
|
}
|
|
|
|
async connect(): Promise<void> {
|
|
// reconnect=true lets ndk retry, but our manager owns the higher-level
|
|
// backoff and loop prevention across the app.
|
|
await this.relay.connect(undefined, true);
|
|
}
|
|
|
|
disconnect(): void {
|
|
this.relay.disconnect();
|
|
}
|
|
|
|
on(event: RelayConnectionEvent, handler: (payload?: string) => void): () => void {
|
|
// map our vocabulary onto NDKRelay events.
|
|
const wrapped = (payload?: unknown) =>
|
|
handler(typeof payload === 'string' ? payload : undefined);
|
|
this.relay.on(event, wrapped as never);
|
|
return () => this.relay.off(event, wrapped as never);
|
|
}
|
|
}
|
|
|
|
/** factory used by the app-level RelayManager wiring. */
|
|
export function createNdkConnection(url: string, ndk: NDK): RelayConnection {
|
|
return new NdkRelayConnection(url, ndk);
|
|
}
|
|
|
|
/** nip-11 fetch mapped into the app-level RelayInformation model. */
|
|
export async function fetchNip11(url: string): Promise<RelayInformation> {
|
|
const info = await fetchRelayInformation(url);
|
|
// `features` and `motd` are nosterm extensions ndk's typed document doesn't
|
|
// know about, so read them defensively off the raw object.
|
|
const raw = info as unknown as { features?: unknown; motd?: unknown };
|
|
const features = Array.isArray(raw.features)
|
|
? raw.features.filter((f): f is string => typeof f === 'string')
|
|
: undefined;
|
|
const motd = typeof raw.motd === 'string' ? raw.motd : undefined;
|
|
return {
|
|
name: info.name,
|
|
description: info.description,
|
|
pubkey: info.pubkey,
|
|
contact: info.contact,
|
|
software: info.software,
|
|
version: info.version,
|
|
supportedNips: info.supported_nips,
|
|
features,
|
|
motd,
|
|
limitation: info.limitation
|
|
? {
|
|
maxMessageLength: info.limitation.max_message_length,
|
|
maxSubscriptions: info.limitation.max_subscriptions,
|
|
authRequired: info.limitation.auth_required,
|
|
paymentRequired: info.limitation.payment_required
|
|
}
|
|
: undefined
|
|
};
|
|
}
|