import { NostrEvent, NostrRelayOK, NPolicy } from '@nostrify/nostrify'; import { Stickynotes } from '@soapbox/stickynotes'; import * as Comlink from 'comlink'; import { Conf } from '@/config.ts'; import type { CustomPolicy } from '@/workers/policy.worker.ts'; import '@/workers/handlers/abortsignal.ts'; const console = new Stickynotes('ditto:policy'); class PolicyWorker implements NPolicy { private worker: Comlink.Remote; private ready: Promise; private enabled = true; constructor() { this.worker = Comlink.wrap( new Worker( new URL('./policy.worker.ts', import.meta.url), { type: 'module', deno: { permissions: { read: [Conf.denoDir, Conf.policy, Conf.dataDir], write: [Conf.dataDir], net: 'inherit', env: false, }, }, }, ), ); this.ready = this.init(); } async call(event: NostrEvent, signal?: AbortSignal): Promise { await this.ready; if (!this.enabled) { return ['OK', event.id, true, '']; } return this.worker.call(event, signal); } private async init(): Promise { try { await this.worker.init({ path: Conf.policy, databaseUrl: Conf.databaseUrl, adminPubkey: Conf.pubkey, }); console.warn(`Using custom policy: ${Conf.policy}`); } catch (e) { if (e instanceof Error && e.message.includes('Module not found')) { console.warn('Custom policy not found '); this.enabled = false; return; } if (e instanceof Error && e.message.includes('PGlite is not supported in worker threads')) { console.warn('Custom policies are not supported with PGlite. The policy is disabled.'); this.enabled = false; return; } throw new Error(`DITTO_POLICY (error importing policy): ${Conf.policy}`, e); } } } export const policyWorker = new PolicyWorker();