diff --git a/src/schema/effect/option.ts b/src/schema/effect/option.ts index a3f91aa..56163f9 100644 --- a/src/schema/effect/option.ts +++ b/src/schema/effect/option.ts @@ -6,75 +6,91 @@ import { z } from "zod" type JsonifiedEffectOptionSomeBrand = "@thilawyn/zod-schema-class/JsonifiedEffectOptionSome" -export const option = (schema: S) => - z.union([option.some(schema), option.none(schema)]) +export function option(schema: S) { + return z.union([option.some(schema), option.none(schema)]) +} + +export module option { + export function some< + InnerS extends z.ZodTypeAny + >( + schema: InnerS + ) { + return z + .custom>>(v => Option.isOption(v) && Option.isSome(v), "Not an Option.Some") + .pipe(z.object({ value: schema }).passthrough()) + .transform>>(identity) + } + + export module some { + export function jsonify< + InnerS extends z.ZodTypeAny, + JsonifiedInnerS extends z.ZodTypeAny = InnerS, + >( + schema: ZodEffectOptionSome, + jsonifySchema: (schema: InnerS) => JsonifiedInnerS = identity, + ) { + return schema + .transform(v => Option.getOrThrow(v)) + .pipe(jsonifySchema(effectOptionSomeInnerSchema(schema))) + .brand() + } + + export function dejsonify< + InnerS extends z.ZodTypeAny, + DejsonifiedInnerS extends z.ZodTypeAny = InnerS, + >( + schema: ZodEffectOptionSome, + dejsonifySchema: (schema: InnerS) => DejsonifiedInnerS = identity, + ) { + return z + .custom & z.BRAND>() + .pipe(dejsonifySchema(effectOptionSomeInnerSchema(schema))) + .transform(v => Option.some>(v)) + .pipe(schema) + } + } -const some = < - InnerS extends z.ZodTypeAny ->(schema: InnerS) => z - .custom>>(v => Option.isOption(v) && Option.isSome(v), "Not an Option.Some") - .pipe(z.object({ value: schema }).passthrough()) - .transform>>(identity) + export function none< + InnerS extends z.ZodTypeAny | unknown = unknown + >( + _schema?: InnerS + ) { + return z.custom< + Option.None< + InnerS extends z.ZodTypeAny + ? z.output + : unknown + > + >(v => Option.isOption(v) && Option.isNone(v), "Not an Option.None") + } -some.jsonify = < - InnerS extends z.ZodTypeAny, - JsonifiedInnerS extends z.ZodTypeAny = InnerS, ->( - schema: ZodEffectOptionSome, - jsonifySchema: (schema: InnerS) => JsonifiedInnerS = identity, -) => schema - .transform(v => Option.getOrThrow(v)) - .pipe(jsonifySchema(effectOptionSomeInnerSchema(schema))) - .brand() + export module none { + export function jsonify< + InnerS extends z.ZodTypeAny, + JsonifiedInnerS extends z.ZodTypeAny = InnerS, + >( + schema: ZodEffectOptionNone, + _jsonifySchema?: (schema: InnerS) => JsonifiedInnerS, + ) { + return schema.transform(() => null) + } -some.dejsonify = < - InnerS extends z.ZodTypeAny, - DejsonifiedInnerS extends z.ZodTypeAny = InnerS, ->( - schema: ZodEffectOptionSome, - dejsonifySchema: (schema: InnerS) => DejsonifiedInnerS = identity, -) => z - .custom & z.BRAND>() - .pipe(dejsonifySchema(effectOptionSomeInnerSchema(schema))) - .transform(v => Option.some>(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 - : unknown - > - >(v => Option.isOption(v) && Option.isNone(v), "Not an Option.None") - -none.jsonify = < - InnerS extends z.ZodTypeAny, - JsonifiedInnerS extends z.ZodTypeAny = InnerS, ->( - schema: ZodEffectOptionNone, - _jsonifySchema?: (schema: InnerS) => JsonifiedInnerS, -) => - schema.transform(() => null), - -none.dejsonify = < - InnerS extends z.ZodTypeAny, - DejsonifiedInnerS extends z.ZodTypeAny = InnerS, ->( - schema: ZodEffectOptionNone, - _dejsonifySchema?: (schema: InnerS) => DejsonifiedInnerS, -) => z - .null() - .transform(() => Option.none>()) - .pipe(schema), - -option.none = none + export function dejsonify< + InnerS extends z.ZodTypeAny, + DejsonifiedInnerS extends z.ZodTypeAny = InnerS, + >( + schema: ZodEffectOptionNone, + _dejsonifySchema?: (schema: InnerS) => DejsonifiedInnerS, + ) { + return z + .null() + .transform(() => Option.none>()) + .pipe(schema) + } + } +} export type ZodEffectOption = ReturnType>