Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 | 2x 2x 2x 2x 2x 2x 2x 2x 52x 49x 632x 2x 2x 358x 2x 2x 2x 2x 2x 2x 2x 2x 2x 49x 2x 2x 2x 663x 2x 52x 52x 52x 52x 52x 52x 52x 52x 52x 52x 52x 91x 52x 52x 2x 2x 2x 2x 2x 50x 50x 50x 49x 2x 2x 6x 6x 6x 6x 6x 6x 6x 637x 2x 637x 637x 158x 16x 637x 637x 22x 50x 50x 637x 3x 50x 2x 637x 4x 637x 63x 4x 4x 4x 49x 2x 2x 2x 49x 61x 25x 20x 18x 14x 2x 2x 61x 52x 2x 2x 9x 2x 2x 2x 2x 2x 2x 2x 49x 7x 2x 2x 2x 2x 2x 2x 2x 49x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 49x 2x 2x 2x 2x 2x 2x 2x 2x | // src/utils/zodUtils.ts
import { z } from 'zod';
/**
* A Zod schema for a required, non-empty string.
* @param message The error message to display if the string is empty or missing.
* @param maxLength Optional maximum length (defaults to 255).
* @returns A Zod string schema.
*/
export const requiredString = (message: string, maxLength = 255) =>
z.preprocess(
// If the value is null or undefined, preprocess it to an empty string.
// This ensures that the subsequent `.min(1)` check will catch missing required fields.
(val) => val ?? '',
// Now, validate that the (potentially preprocessed) value is a string that, after trimming, has at least 1 character.
z.string().trim().min(1, message).max(maxLength, `Must be ${maxLength} characters or less.`),
);
/**
* Creates a Zod schema for a numeric ID in request parameters.
* @param paramName The name of the parameter (e.g., 'id').
* @param message The error message for invalid input.
* @returns A Zod object schema for the params.
*/
export const numericIdParam = (
paramName: string,
message = `Invalid ID for parameter '${paramName}'. Must be a number.`,
) =>
z.object({
params: z.object({
[paramName]: z.coerce.number().int(message).positive(message),
}),
});
/**
* Creates a Zod schema for a UUID in request parameters.
* @param paramName The name of the parameter (e.g., 'id').
* @param message The error message for invalid input.
* @returns A Zod object schema for the params.
*/
export const uuidParamSchema = (paramName: string, message: string) =>
z.object({
params: z.object({
[paramName]: z.string().uuid(message),
}),
});
/**
* Creates a Zod schema for an optional, numeric query parameter that is coerced from a string.
* @param options Configuration for the validation like default value, min/max, and integer constraints.
* @returns A Zod schema for the number.
*/
export const optionalNumeric = (
options: {
default?: number;
min?: number;
max?: number;
integer?: boolean;
positive?: boolean;
nonnegative?: boolean;
} = {},
) => {
let numberSchema = z.coerce.number();
if (options.integer) numberSchema = numberSchema.int();
if (options.positive) numberSchema = numberSchema.positive();
else if (options.nonnegative) numberSchema = numberSchema.nonnegative();
if (options.min !== undefined) numberSchema = numberSchema.min(options.min);
if (options.max !== undefined) numberSchema = numberSchema.max(options.max);
// Make the number schema optional *before* preprocessing. This allows it to correctly handle
// the `undefined` value that our preprocessor generates from `null`.
const optionalNumberSchema = numberSchema.optional();
// This is crucial because z.coerce.number(null) results in 0, which bypasses
// the .optional() and .default() logic for null inputs. We want null to be
// treated as "not provided", just like undefined.
const schema = z.preprocess((val) => (val === null ? undefined : val), optionalNumberSchema);
if (options.default !== undefined) return schema.default(options.default);
return schema;
};
/**
* Creates a Zod schema for an optional date string in YYYY-MM-DD format.
* @param message Optional custom error message.
* @returns A Zod schema for the date string.
*/
export const optionalDate = (message?: string) => z.string().date(message).optional();
/**
* Creates a Zod schema for an optional boolean query parameter that is coerced from a string.
* Handles 'true', '1' as true and 'false', '0' as false.
* @param options Configuration for the validation like default value.
* @returns A Zod schema for the boolean.
*/
export const optionalBoolean = (
options: {
default?: boolean;
} = {},
) => {
const schema = z.preprocess((val) => {
if (val === 'true' || val === '1') return true;
if (val === 'false' || val === '0') return false;
if (val === '' || val === null) return undefined; // Treat empty string and null as not present
return val;
}, z.boolean().optional());
if (options.default !== undefined) {
return schema.default(options.default);
}
return schema;
};
/**
* Creates a Zod schema for an optional string.
* Treats null as undefined so it can be properly handled as optional.
* @returns A Zod schema for an optional string.
*/
export const optionalString = () =>
z.preprocess((val) => (val === null ? undefined : val), z.string().optional());
/**
* Creates a Zod schema for a required HTTP/HTTPS URL.
* Validates that the URL starts with http:// or https:// to match database constraints.
* @param message Optional custom error message.
* @returns A Zod schema for the URL string.
*/
export const httpUrl = (message = 'Must be a valid HTTP or HTTPS URL') =>
z
.string()
.url(message)
.regex(/^https?:\/\/.+/, message);
/**
* Creates a Zod schema for an optional HTTP/HTTPS URL.
* Validates that if provided, the URL starts with http:// or https://.
* @param message Optional custom error message.
* @returns A Zod schema for the optional URL string.
*/
export const optionalHttpUrl = (message = 'Must be a valid HTTP or HTTPS URL') =>
z.preprocess(
(val) => (val === null ? undefined : val),
z
.string()
.url(message)
.regex(/^https?:\/\/.+/, message)
.optional(),
);
|