An AT Protocol PDS
at main 61 lines 2.0 kB view raw
1import type { MoonstoneEnv } from '@ewanc26/moonstone-config' 2import { logger } from './logger.js' 3import { createRequire } from 'node:module' 4 5const require = createRequire(import.meta.url) 6 7type NativeAddon = { 8 ensureValidHandle(handle: string): void 9 ensureValidDid(did: string): void 10 resolveDid(did: string, plcUrl: string, timeoutMs: number): Promise<Record<string, unknown> | null> 11} 12 13function loadNative(): NativeAddon | null { 14 try { 15 return require('@ewanc26/moonstone-native') as NativeAddon 16 } catch { 17 logger.warn( 18 'moonstone-native addon not built — skipping Rust-backed startup validation. ' + 19 'Run `pnpm --filter @ewanc26/moonstone-native build` to enable.', 20 ) 21 return null 22 } 23} 24 25export async function validateStartup(env: MoonstoneEnv): Promise<void> { 26 const native = loadNative() 27 if (!native) return 28 29 const hostname = env.PDS_HOSTNAME 30 const did = env.PDS_SERVICE_DID ?? `did:web:${hostname}` 31 const plcUrl = env.PDS_PLC_URL 32 const devMode = env.PDS_DEV_MODE 33 34 try { 35 native.ensureValidHandle(hostname) 36 } catch (e) { 37 throw new Error(`PDS_HOSTNAME "${hostname}" is not a valid ATProto handle: ${(e as Error).message}`) 38 } 39 40 try { 41 native.ensureValidDid(did) 42 } catch (e) { 43 throw new Error(`Service DID "${did}" is invalid: ${(e as Error).message}`) 44 } 45 46 if (!devMode) { 47 logger.info({ did, plcUrl }, 'moonstone: resolving PDS DID document for pre-flight check') 48 try { 49 const doc = await native.resolveDid(did, plcUrl, 5000) 50 if (doc) { 51 logger.info({ did }, 'moonstone: DID document found') 52 } else { 53 logger.warn({ did, plcUrl }, 'moonstone: DID document not yet registered — expected for first-time setup') 54 } 55 } catch (e) { 56 logger.warn({ did, err: (e as Error).message }, 'moonstone: DID resolution failed during startup — continuing anyway') 57 } 58 } 59 60 logger.info({ hostname, did }, 'moonstone: startup validation passed') 61}