import type { Atom, AtomRegistry } from "effect/unstable/reactivity"; export async function waitForAtomValue(input: { readonly registry: AtomRegistry.AtomRegistry; readonly atom: Atom.Atom; readonly predicate: (value: A) => boolean; readonly timeoutMs: number; }): Promise { const read = () => input.registry.get(input.atom); if (input.predicate(read())) { return true; } return await new Promise((resolve) => { let settled = false; let timeoutId: ReturnType | null = null; let unsubscribe: (() => void) | null = null; let unsubscribeWhenReady = false; const finish = (result: boolean) => { if (settled) { return; } settled = true; if (timeoutId !== null) { globalThis.clearTimeout(timeoutId); } if (unsubscribe === null) { unsubscribeWhenReady = true; } else { unsubscribe(); } resolve(result); }; unsubscribe = input.registry.subscribe(input.atom, (value) => { if (input.predicate(value)) { finish(true); } }); if (unsubscribeWhenReady) { unsubscribe(); return; } // Close the gap between the initial read and subscription registration. if (input.predicate(read())) { finish(true); return; } timeoutId = globalThis.setTimeout(() => { finish(false); }, input.timeoutMs); }); }