zod-invertible
Version:
declare zod schemas that can be inverted to format from output to input
158 lines • 4.55 kB
JavaScript
import z from 'zod';
export class ZodInvertible extends z.ZodPipeline {
constructor(inputSchema, parse, outputSchema, format) {
super({
...inputSchema.transform(parse).pipe(outputSchema)._def,
inputSchema,
outputSchema,
parse,
format
});
}
}
export function invertible(schema, parse, outSchema, format) {
return new ZodInvertible(schema, parse, outSchema, format);
}
export const IgnoreEffect = Symbol('IgnoreEffect');
export function ignoreEffect(schema) {
;
schema[IgnoreEffect] = true;
return schema;
}
export function invert(schema) {
switch (schema._def.typeName) {
case z.ZodFirstPartyTypeKind.ZodArray:
return z.array(invert(schema.element));
case z.ZodFirstPartyTypeKind.ZodObject:
{
const {
shape,
_def
} = schema;
const invertedShape = Object.fromEntries(Object.entries(shape).map(([key, value]) => [key, invert(value)]));
return new z.ZodObject({
..._def,
catchall: invert(_def.catchall),
shape: () => invertedShape
});
}
case z.ZodFirstPartyTypeKind.ZodUnion:
return z.union(schema.options.map(invert));
case z.ZodFirstPartyTypeKind.ZodDiscriminatedUnion:
{
const {
discriminator,
options
} = schema;
return z.discriminatedUnion(discriminator, options.map(invert));
}
case z.ZodFirstPartyTypeKind.ZodIntersection:
{
const {
left,
right
} = schema._def;
return z.intersection(invert(left), invert(right));
}
case z.ZodFirstPartyTypeKind.ZodTuple:
{
const {
items,
_def: {
rest
}
} = schema;
const result = z.tuple(items.map(invert));
return rest ? result.rest(invert(rest)) : result;
}
case z.ZodFirstPartyTypeKind.ZodRecord:
{
const {
keySchema,
valueSchema
} = schema;
return z.record(invert(keySchema), invert(valueSchema));
}
case z.ZodFirstPartyTypeKind.ZodMap:
{
const {
keySchema,
valueSchema
} = schema;
return z.map(invert(keySchema), invert(valueSchema));
}
case z.ZodFirstPartyTypeKind.ZodSet:
return z.set(invert(schema._def.valueType));
case z.ZodFirstPartyTypeKind.ZodFunction:
{
const {
_def: {
args,
returns
}
} = schema;
return z.function(args.map(invert), invert(returns));
}
case z.ZodFirstPartyTypeKind.ZodLazy:
return z.lazy(() => invert(schema.schema));
case z.ZodFirstPartyTypeKind.ZodEffects:
{
const {
_def: {
effect,
schema: innerType
}
} = schema;
switch (effect.type) {
case 'refinement':
{
const {
refinement
} = effect;
return z.any().superRefine(refinement).pipe(invert(innerType));
}
case 'preprocess':
case 'transform':
if (schema[IgnoreEffect]) {
return invert(innerType);
}
throw new Error(`effect not supported: ${effect.type}`);
}
break;
}
case z.ZodFirstPartyTypeKind.ZodOptional:
return invert(schema.unwrap()).optional();
case z.ZodFirstPartyTypeKind.ZodNullable:
return invert(schema.unwrap()).nullable();
case z.ZodFirstPartyTypeKind.ZodDefault:
return invert(schema.removeDefault());
case z.ZodFirstPartyTypeKind.ZodCatch:
return invert(schema.removeCatch());
case z.ZodFirstPartyTypeKind.ZodPromise:
return z.promise(invert(schema._def.type));
case z.ZodFirstPartyTypeKind.ZodBranded:
return invert(schema._def.type);
case z.ZodFirstPartyTypeKind.ZodPipeline:
{
if (schema instanceof ZodInvertible) {
const {
_def: {
inputSchema,
outputSchema,
parse,
format
}
} = schema;
return invertible(invert(outputSchema), format, invert(inputSchema), parse);
}
const {
_def
} = schema;
return invert(_def.out).pipe(invert(_def.in));
}
case z.ZodFirstPartyTypeKind.ZodReadonly:
return invert(schema._def.innerType).readonly();
}
return schema;
}
//# sourceMappingURL=index.mjs.map