import type * as MSAWorker from './multi-sequence-alignment.worker'; const cache = new Map(); function runInWorker( worker: Worker, message: MSAWorker.RequestMessage, signal: AbortSignal, ): Promise { return new Promise((resolve, reject) => { worker.addEventListener('message', ({ data }: MessageEvent) => { resolve(data); worker.terminate(); }); worker.addEventListener('error', ({ error, message: msg }: ErrorEvent) => { reject(error ?? msg); worker.terminate(); }); signal.addEventListener('abort', () => { reject(signal.reason); worker.terminate(); }); worker.postMessage(message); }); } export async function alignSequences( sequences: string[], params = { gpo: 5.5, gpe: 2.0, tgpe: 1.0 }, signal?: AbortSignal, ): Promise { if (sequences.length < 2) return sequences; const key = JSON.stringify([sequences, params]); const cached = cache.get(key); if (cached) return cached; const result = await runInWorker( new Worker(new URL('./multi-sequence-alignment.worker.ts', import.meta.url), { type: 'module' }), { sequences, params }, signal ?? new AbortController().signal, ); if (!signal?.aborted) { cache.set(key, result); } return result; }