type WaitOptions = {
  signal?: AbortSignal;
};

/**
 * Resolves after `ms` milliseconds, or immediately if the provided AbortSignal
 * is (or becomes) aborted.
 *
 * Note: resolves (does not reject) on abort, so callers that need to detect
 * early exit should check `signal.aborted` after awaiting.
 */
const wait = (ms: number, options?: WaitOptions): Promise<void> =>
  new Promise(resolve => {
    const { signal } = options ?? {};
    if (signal?.aborted) {
      resolve();
      return;
    }
    const onAbort = () => {
      clearTimeout(timer);
      resolve();
    };
    const timer = setTimeout(() => {
      signal?.removeEventListener('abort', onAbort);
      resolve();
    }, ms);
    signal?.addEventListener('abort', onAbort, { once: true });
  });

export default wait;
