Files
galvanic-corrosion-rewrite/src/util/validators.ts

81 lines
2.6 KiB
TypeScript

import { zValidator } from "@hono/zod-validator";
import type { MiddlewareHandler } from "@hono/hono";
import { z } from "zod";
import type { HonoEnv } from "./types.ts";
import { ZodSchema } from "zod/v4";
import { HTTPStatus } from "@oneday/http-status";
import Logging from "@proxnet/undead-logging";
const log = new Logging("Validation");
// thanks claude, this hurt my brain!
export const typedZValidator = <
T extends 'query' | 'json' | 'form' | 'header' | 'param' | 'cookie',
S extends ZodSchema
>(
target: T,
schema: S,
httpOk?: boolean,
recNetError?: string
) => {
return zValidator(target, schema, (result, c) => {
if (!result.success) {
log.w(`Validation failed: ${JSON.stringify(result.error)}`);
if (recNetError) return c.json({ success: false, error: recNetError }, httpOk == true ? HTTPStatus.OK : HTTPStatus.BadRequest);
else return c.json({ success: false, error: "Request validation failed" }, httpOk == true ? HTTPStatus.OK : HTTPStatus.BadRequest);
}
}) as MiddlewareHandler<
HonoEnv,
string,
{
in: { [K in T]: z.input<S> };
out: { [K in T]: z.output<S> };
}
>;
};
/**
* @deprecated Use transformCheckEnum after #.coerce.number() (optionally)
*/
export const transformStringToEnum = <T>(anEnum: { [s: string]: string | number }, str?: boolean) => {
return (arg: string, ctx: z.RefinementCtx<string | number>) => {
if (!str) {
const int = parseInt(arg);
if (isNaN(int) || !Number.isSafeInteger(int)) ctx.addIssue("number was not valid");
else if (anEnum[int]) return int as T;
else ctx.addIssue("number was not a valid enum member");
} else {
const vals = Object.values(anEnum);
if (vals.includes(arg)) return arg as T;
else ctx.addIssue("string was not a valid enum member");
}
}
}
export const transformCheckEnum = <T>(anEnum: { [s: string]: string | number }) => {
return (arg: number | string, ctx: z.RefinementCtx<number | string>) => {
function invalid() {
ctx.addIssue("Invalid enum member");
}
if (typeof arg == 'string') {
if (typeof anEnum[arg] == 'number') return anEnum[arg] as T;
else {
invalid();
return null;
}
} else if (typeof arg == 'number') {
if (typeof anEnum[arg] == 'string') return arg as T;
else {
invalid();
return null;
}
} else {
invalid();
return null;
}
}
}