This commit is contained in:
@@ -3,23 +3,83 @@ import { identity } from "lodash-es"
|
||||
import { z } from "zod"
|
||||
|
||||
|
||||
type JsonifiedEffectOptionSomeBrand = "@thilawyn/zod-schema-class/JsonifiedEffectOptionSome"
|
||||
|
||||
|
||||
export const option = <S extends z.ZodTypeAny>(schema: S) =>
|
||||
z.union([option.some(schema), option.none(schema)])
|
||||
|
||||
option.some = <S extends z.ZodTypeAny>(schema: S) => z
|
||||
.custom<Option.Some<z.output<S>>>(v => Option.isOption(v) && Option.isSome(v), "Not an Option")
|
||||
.pipe(z.object({ value: schema }).passthrough())
|
||||
.transform<Option.Some<z.output<S>>>(identity)
|
||||
|
||||
option.none = <S extends z.ZodTypeAny | unknown = unknown>(_schema?: S) =>
|
||||
z.custom<Option.None<
|
||||
S extends z.ZodTypeAny
|
||||
? z.output<S>
|
||||
const some = <
|
||||
InnerS extends z.ZodTypeAny
|
||||
>(schema: InnerS) => z
|
||||
.custom<Option.Some<z.output<InnerS>>>(v => Option.isOption(v) && Option.isSome(v), "Not an Option.Some")
|
||||
.pipe(z.object({ value: schema }).passthrough())
|
||||
.transform<Option.Some<z.output<InnerS>>>(identity)
|
||||
|
||||
some.jsonify = <
|
||||
InnerS extends z.ZodTypeAny,
|
||||
JsonifiedInnerS extends z.ZodTypeAny = InnerS,
|
||||
>(
|
||||
schema: ZodEffectOptionSome<InnerS>,
|
||||
jsonifySchema: (schema: InnerS) => JsonifiedInnerS = identity,
|
||||
) => schema
|
||||
.transform(v => Option.getOrThrow(v))
|
||||
.pipe(jsonifySchema(effectOptionSomeInnerSchema(schema)))
|
||||
.brand<JsonifiedEffectOptionSomeBrand>()
|
||||
|
||||
some.dejsonify = <
|
||||
InnerS extends z.ZodTypeAny,
|
||||
DejsonifiedInnerS extends z.ZodTypeAny = InnerS,
|
||||
>(
|
||||
schema: ZodEffectOptionSome<InnerS>,
|
||||
dejsonifySchema: (schema: InnerS) => DejsonifiedInnerS = identity,
|
||||
) => z
|
||||
.custom<z.input<DejsonifiedInnerS> & z.BRAND<JsonifiedEffectOptionSomeBrand>>()
|
||||
.pipe(dejsonifySchema(effectOptionSomeInnerSchema(schema)))
|
||||
.transform(v => Option.some<z.output<DejsonifiedInnerS>>(v))
|
||||
.pipe(schema)
|
||||
|
||||
option.some = some
|
||||
|
||||
|
||||
const none = <
|
||||
InnerS extends z.ZodTypeAny | unknown = unknown
|
||||
>(_schema?: InnerS) =>
|
||||
z.custom<
|
||||
Option.None<
|
||||
InnerS extends z.ZodTypeAny
|
||||
? z.output<InnerS>
|
||||
: unknown
|
||||
>>(v => Option.isOption(v) && Option.isNone(v), "Not an Option")
|
||||
>
|
||||
>(v => Option.isOption(v) && Option.isNone(v), "Not an Option.None")
|
||||
|
||||
none.jsonify = <
|
||||
InnerS extends z.ZodTypeAny,
|
||||
JsonifiedInnerS extends z.ZodTypeAny = InnerS,
|
||||
>(
|
||||
schema: ZodEffectOptionNone<InnerS>,
|
||||
_jsonifySchema?: (schema: InnerS) => JsonifiedInnerS,
|
||||
) =>
|
||||
schema.transform(() => null),
|
||||
|
||||
none.dejsonify = <
|
||||
InnerS extends z.ZodTypeAny,
|
||||
DejsonifiedInnerS extends z.ZodTypeAny = InnerS,
|
||||
>(
|
||||
schema: ZodEffectOptionNone<InnerS>,
|
||||
_dejsonifySchema?: (schema: InnerS) => DejsonifiedInnerS,
|
||||
) => z
|
||||
.null()
|
||||
.transform(() => Option.none<z.output<DejsonifiedInnerS>>())
|
||||
.pipe(schema),
|
||||
|
||||
option.none = none
|
||||
|
||||
|
||||
export type ZodEffectOption<S extends z.ZodTypeAny> = ReturnType<typeof option<S>>
|
||||
export type ZodEffectOptionSome<S extends z.ZodTypeAny> = ReturnType<typeof option.some<S>>
|
||||
export type ZodEffectOptionNone<S extends z.ZodTypeAny> = ReturnType<typeof option.none<S>>
|
||||
|
||||
export const effectOptionSomeSchema = <S extends z.ZodTypeAny>(schema: ZodEffectOption<S>): ZodEffectOptionSome<S> =>
|
||||
schema.options[0]
|
||||
@@ -27,11 +87,5 @@ export const effectOptionSomeSchema = <S extends z.ZodTypeAny>(schema: ZodEffect
|
||||
export const effectOptionNoneSchema = <S extends z.ZodTypeAny>(schema: ZodEffectOption<S>): ZodEffectOptionNone<S> =>
|
||||
schema.options[1]
|
||||
|
||||
|
||||
export type ZodEffectOptionSome<S extends z.ZodTypeAny> = ReturnType<typeof option.some<S>>
|
||||
|
||||
export const effectOptionSomeInnerSchema = <S extends z.ZodTypeAny>(schema: ZodEffectOptionSome<S>): S =>
|
||||
schema._def.schema._def.out.shape.value
|
||||
|
||||
|
||||
export type ZodEffectOptionNone<S extends z.ZodTypeAny> = ReturnType<typeof option.none<S>>
|
||||
|
||||
Reference in New Issue
Block a user