Sifa professional network API (Fastify, AT Protocol, Jetstream)
sifa.id/
1import { logger as rootLogger } from '../logger.js';
2import { getIdentityResolver, resolvePdsEndpointCached, resolvePdsHostCached } from './identity.js';
3
4const logger = rootLogger.child({ module: 'pds-provider' });
5
6export interface PdsProviderInfo {
7 name: string;
8 host: string;
9}
10
11const KNOWN_PDS_HOSTS: { pattern: RegExp; name: string }[] = [
12 { pattern: /\.bsky\.network$/i, name: 'bluesky' },
13 { pattern: /^bsky\.social$/i, name: 'bluesky' },
14 { pattern: /\.blacksky\.app$/i, name: 'blacksky' },
15 { pattern: /^blacksky\.app$/i, name: 'blacksky' },
16 { pattern: /\.eurosky\.social$/i, name: 'eurosky' },
17 { pattern: /^eurosky\.social$/i, name: 'eurosky' },
18 { pattern: /\.northsky\.social$/i, name: 'northsky' },
19 { pattern: /^northsky\.social$/i, name: 'northsky' },
20 { pattern: /\.selfhosted\.social$/i, name: 'selfhosted-social' },
21 { pattern: /^selfhosted\.social$/i, name: 'selfhosted-social' },
22];
23
24export function mapPdsHostToProvider(host: string): PdsProviderInfo {
25 for (const entry of KNOWN_PDS_HOSTS) {
26 if (entry.pattern.test(host)) {
27 return { name: entry.name, host };
28 }
29 }
30 return { name: 'selfhosted', host };
31}
32
33export function extractPdsHostFromEndpoint(endpoint: string): string | null {
34 try {
35 return new URL(endpoint).hostname;
36 } catch {
37 return null;
38 }
39}
40
41/**
42 * Resolves the full PDS endpoint URL (e.g. "https://maitake.us-west.host.bsky.network")
43 * from a DID. Uses the cached IdentityResolver if available, falls back to
44 * direct plc.directory fetch for standalone/test usage.
45 */
46export async function resolvePdsEndpoint(did: string): Promise<string | null> {
47 const resolver = getIdentityResolver();
48 if (resolver) {
49 return resolvePdsEndpointCached(resolver, did);
50 }
51 logger.warn({ did }, 'IdentityResolver not initialized, skipping PDS resolution');
52 return null;
53}
54
55/**
56 * Resolves the PDS hostname from a DID.
57 * Uses the cached IdentityResolver if available.
58 */
59export async function resolvePdsHost(did: string): Promise<string | null> {
60 const resolver = getIdentityResolver();
61 if (resolver) {
62 return resolvePdsHostCached(resolver, did);
63 }
64 logger.warn({ did }, 'IdentityResolver not initialized, skipping PDS host resolution');
65 return null;
66}