import type { NextApiRequest } from 'next'; import type { RequestInternal } from 'next-auth'; import { z } from 'zod'; const ZIpSchema = z.string().ip(); export const ZRequestMetadataSchema = z.object({ ipAddress: ZIpSchema.optional(), userAgent: z.string().optional(), }); export type RequestMetadata = z.infer; export const extractNextApiRequestMetadata = (req: NextApiRequest): RequestMetadata => { const parsedIp = ZIpSchema.safeParse(req.headers['x-forwarded-for'] || req.socket.remoteAddress); const ipAddress = parsedIp.success ? parsedIp.data : undefined; const userAgent = req.headers['user-agent']; return { ipAddress, userAgent, }; }; export const extractNextAuthRequestMetadata = ( req: Pick, ): RequestMetadata => { return extractNextHeaderRequestMetadata(req.headers ?? {}); }; export const extractNextHeaderRequestMetadata = ( headers: Record, ): RequestMetadata => { const parsedIp = ZIpSchema.safeParse(headers?.['x-forwarded-for']); const ipAddress = parsedIp.success ? parsedIp.data : undefined; const userAgent = headers?.['user-agent']; return { ipAddress, userAgent, }; };