import { Err, Ok, Result } from ".";

/**
 * Convert an exception throwing function into a {@type Result} returning one.
 */
export function trySync<T, E>(f: () => T, e: (e: unknown) => E): Result<T, E> {
  try {
    return Ok(f());
  } catch (cause) {
    return Err(e(cause));
  }
}

/**
 * Convert an exception throwing async function into a {@type Result} returning
 * one.
 */
export async function tryAsync<T, E>(
  f: () => Promise<T>,
  e: (e: unknown) => E,
): Promise<Result<T, E>> {
  try {
    return Ok(await f());
  } catch (cause) {
    return Err(e(cause));
  }
}

export function passOrYield<E>(
  // eslint-disable-next-line @typescript-eslint/ban-types
  errorClass: Function,
  f: (error: unknown) => E,
): (error: unknown) => E {
  return (error: unknown) => {
    if (
      error instanceof errorClass ||
      (error instanceof Error && error.name === errorClass.name)
    ) {
      return error as E;
    }
    return f(error);
  };
}
