import { identity } from 'remeda' import { Cage, Caged, CageP, uncage, uncageP } from './cage' export function ensure(object: Obj | null | undefined, error?: Cage) { if (object === null || object === undefined) throw uncage(error ?? getNotFoundError()) return object } export async function ensureP(object: Obj | null | undefined, error?: CageP) { if (object === null || object === undefined) throw await uncageP(error ?? getNotFoundError()) return object } export function ensureFind(collection: Obj[], filter: (object: Obj) => boolean, error?: Cage) { const object = collection.find(filter) if (object === null || object === undefined) throw uncage(error ?? getNotFoundErrorForFilter(filter)) return object } export async function ensureFindP(collection: Obj[], filter: (object: Obj) => boolean, error?: CageP) { const object = collection.find(filter) if (object === null || object === undefined) throw await uncageP(error ?? getNotFoundErrorForFilter(filter)) return object } export function ensureMapGet(map: Map, key: Key, error?: Cage) { return ensure(map.get(key), () => uncage(error) ?? getNotFoundInMapByKeyError(map, key)) } export function ensureGet(record: Record, key: Key, error?: Cage) { return ensure(record[key], () => uncage(error) ?? getNotFoundInRecordByKeyError(record, key)) } export function ensureByIndex(array: Value[], index: number, error?: Cage) { return ensure(array[index], () => uncage(error) ?? getNotFoundInArrayByIndexError(array, index)) } export function ensureEvery(objects: Array, error?: CageP) { if (!objects.every(identity)) throw uncage(error ?? new Error(`Some objects are falsy: \n\n${JSON.stringify(objects)}`)) return objects } export function ensureError(e: unknown) { if (e instanceof Error) { return e } else { throw e } } export const ensureMin = (min: number) => (value: number) => value > min ? value : min export const ensureMax = (max: number) => (value: number) => value < max ? value : max export const ensureMinMax = (min: number, max: number) => (value: number) => ensureMin(min)(ensureMax(max)(value)) export const getFinder = (filter: (object: T) => boolean) => (array: T[]) => ensureFind(array, filter) export const getNotFoundError = () => new Error('Can\'t find object in collection') export const getNotFoundErrorForFilter = (filter: (object: Obj) => boolean) => new Error('Can\'t find an object in a collection using filter: ' + filter.toString()) export const getNotFoundInMapByKeyError = (map: Map, key: Key) => new Error(`Can't find key "${key}" in map ${map}`) export const getNotFoundInRecordByKeyError = (record: Record, key: Key) => new Error(`Can't find key "${key.toString()}" in record ${record}`) export const getNotFoundInArrayByIndexError = (array: Value[], index: number) => new Error(`Can't find index "${index}" in array ${array.join(', ')}`)