UNPKG

@prismicio/types-internal

Version:
116 lines (104 loc) 2.88 kB
import { either } from "fp-ts" import { pipe } from "fp-ts/function" import * as t from "io-ts" import { withValidate } from "io-ts-types" import { mapOutput } from "io-ts-types/mapOutput" export function nullable<A, O>(c: t.Type<A, O>) { return t.union([c, t.null, t.undefined]) } export function refineType<A, O, I>( type: t.Type<A, O, I>, newName: string, pred: (a: A) => boolean, ): t.Type<A, O, I> { return new t.Type<A, O, I>( newName, type.is, (u, c) => pipe( type.validate(u, c), either.chain((v) => (pred(v) ? t.success(v) : t.failure(u, c))), ), type.encode, ) } export function filterDouble(value: string): number | null { if (value === "") { return null } const result = Number(value) return Number.isNaN(result) ? null : result } export function formatDateTime(date: Date): string { return date.toISOString().replace(/\.\d{3}Z$/, "+0000") } export function formatDate(date: Date): string { return date.toISOString().replace(/T.*/, "") } export function grouped<A>(array: A[], n: number): A[][] { return array.reduce((acc, curr, idx) => { if (idx % n === 0) { acc.push([curr]) } else { /* eslint-disable @typescript-eslint/no-non-null-assertion */ acc[Math.floor(idx / n)]!.push(curr) } return acc }, new Array<A[]>()) } export function objectToMap<T>(object: { [key: string]: T }): Map<string, T> { return new Map(Object.entries(object)) } export function isEmpty(obj: object) { for (const _x in obj) { return false } return true } export function addType<A, O extends object, I, T extends string>( codec: t.Type<A, O, I>, t: T, ): t.Type<A, O & { __TYPE__: T }, I> { return mapOutput(codec, (o) => ({ ...o, __TYPE__: t } as const)) } /** * Returns a clone of the given codec that tries to find sub-error with message already set. * If there is such error it just returns sub-errors array. * If there is no such error it generates new error with given message. * * @example * expect( * withCustomError( * t.type({age: withCustomError(t.number, () => 'Invalid child')}), * () => "Invalid parent" * ) * ).toSubsetEqualLeft([{message: "Invalid child"}]) * expect( * withCustomError( * t.type({age: t.number}), * () => "Invalid parent" * ) * ).toSubsetEqualLeft([{message: "Invalid parent"}]) */ export function withCustomError<C extends t.Any>( codec: C, message: (i: t.InputOf<C>, c: t.Context) => string, ): C { return withValidate(codec, (i, c) => { return either.mapLeft((errors: t.Errors) => { if (errors.find((error) => error.message)) { return errors } return [ { value: i, context: c, // eslint-disable-next-line @typescript-eslint/no-unsafe-argument message: message(i, c), // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment actual: i, }, ] })(codec.validate(i, c)) }) }