torotask
Version:
Task queue processing in NodeJS based on BullMQ and Redis
159 lines • 6.61 kB
JavaScript
// Suggested location: a new utility file like 'schema-utils.ts' or within 'task.ts'
import * as z from 'zod';
const dateCoercionPreprocess = (arg) => {
// If it's already a Date object, pass it through.
if (arg instanceof Date) {
return arg;
}
// Attempt to convert strings or numbers to Date objects.
if (typeof arg === 'string' || typeof arg === 'number') {
// Handle empty strings: new Date('') results in an Invalid Date.
// Let z.date() handle this after coercion for consistent error reporting.
if (typeof arg === 'string' && arg.trim() === '') {
return arg; // Pass empty string for z.date() to validate
}
return new Date(arg);
}
// Pass through other types.
return arg;
};
export function autoCoerceDatesInSchema(schema) {
if (schema instanceof z.ZodDate) {
return z.preprocess(dateCoercionPreprocess, schema);
}
if (schema instanceof z.ZodObject) {
const shape = schema.shape;
const newShape = {};
let hasChanged = false;
for (const key in shape) {
const fieldSchema = shape[key];
const newFieldSchema = autoCoerceDatesInSchema(fieldSchema);
if (newFieldSchema !== fieldSchema) {
hasChanged = true;
}
newShape[key] = newFieldSchema;
}
if (hasChanged) {
let newObject = z.object(newShape);
if (schema._def.catchall && schema._def.catchall !== z.NEVER) {
newObject = newObject.catchall(autoCoerceDatesInSchema(schema._def.catchall));
}
if (schema._def.unknownKeys === "passthrough")
newObject = newObject.passthrough();
else if (schema._def.unknownKeys === "strict")
newObject = newObject.strict();
return newObject;
}
return schema;
}
if (schema instanceof z.ZodArray) {
const element = schema.element;
const newElement = autoCoerceDatesInSchema(element);
if (newElement !== element) {
let newArray = z.array(newElement);
if (schema._def.minLength)
newArray = newArray.min(schema._def.minLength.value);
if (schema._def.maxLength)
newArray = newArray.max(schema._def.maxLength.value);
if (schema._def.exactLength)
newArray = newArray.length(schema._def.exactLength.value);
return newArray;
}
return schema;
}
if (schema instanceof z.ZodOptional || schema instanceof z.ZodNullable) {
const unwrapped = schema.unwrap();
const newUnwrapped = autoCoerceDatesInSchema(unwrapped);
if (newUnwrapped !== unwrapped) {
return (schema instanceof z.ZodOptional ? newUnwrapped.optional() : newUnwrapped.nullable());
}
return schema;
}
if (schema instanceof z.ZodDefault) {
const innerType = schema._def.innerType;
const newInnerType = autoCoerceDatesInSchema(innerType);
if (newInnerType !== innerType) {
return newInnerType.default(schema._def.defaultValue());
}
return schema;
}
if (schema instanceof z.ZodEffects) {
const innerSchema = schema.innerType();
const newInnerSchema = autoCoerceDatesInSchema(innerSchema);
if (newInnerSchema !== innerSchema) {
const effect = schema._def.effect;
switch (effect.type) {
case 'preprocess':
return newInnerSchema.preprocess(effect.transform);
case 'refinement':
return newInnerSchema.refine(effect.refinement, effect.params);
case 'transform':
return newInnerSchema.transform(effect.transform);
default:
// Fallback for unknown effect types if any future Zod versions add them
console.warn("Encountered an unknown ZodEffect type during auto-coercion. The effect may not be preserved correctly.");
return schema; // Or attempt a generic reconstruction if possible and safe
}
}
return schema;
}
if (schema instanceof z.ZodUnion) {
const options = schema.options;
const newOptions = options.map(opt => autoCoerceDatesInSchema(opt));
if (options.some((opt, i) => newOptions[i] !== opt)) {
if (newOptions.length >= 2) {
return z.union(newOptions);
}
else if (newOptions.length === 1) { // A union of one type is just the type itself
return newOptions[0];
}
}
return schema;
}
if (schema instanceof z.ZodIntersection) {
const left = schema._def.left;
const right = schema._def.right;
const newLeft = autoCoerceDatesInSchema(left);
const newRight = autoCoerceDatesInSchema(right);
if (newLeft !== left || newRight !== right) {
return z.intersection(newLeft, newRight);
}
return schema;
}
if (schema instanceof z.ZodTuple) {
const items = schema.items;
const newItems = items.map(item => autoCoerceDatesInSchema(item));
const rest = schema._def.rest ? autoCoerceDatesInSchema(schema._def.rest) : null;
if (items.some((item, i) => newItems[i] !== item) || (schema._def.rest && rest !== schema._def.rest)) {
let newTupleSchema = z.tuple(newItems);
if (rest) {
newTupleSchema = newTupleSchema.rest(rest);
}
return newTupleSchema;
}
return schema;
}
if (schema instanceof z.ZodRecord) {
const valueType = schema.valueType;
const newValueType = autoCoerceDatesInSchema(valueType);
if (newValueType !== valueType) {
return z.record(schema.keyType, newValueType);
}
return schema;
}
if (schema instanceof z.ZodLazy) {
const originalGetter = schema._def.getter;
return z.lazy(() => autoCoerceDatesInSchema(originalGetter()));
}
if (schema instanceof z.ZodReadonly) {
const innerType = schema._def.innerType;
const newInnerType = autoCoerceDatesInSchema(innerType);
if (newInnerType !== innerType) {
return newInnerType.readonly();
}
return schema;
}
// Other types (string, number, boolean, enums, etc.) are returned as is.
return schema;
}
//# sourceMappingURL=auto-coerce-dates.js.map