import type { Context } from "hono"; import { z, ZodError } from "zod"; import { getConnInfo } from "@hono/node-server/conninfo"; import { tryCatch } from "./tryCatch.js"; import { db } from "../../database/dbclient.js"; import { apiHits } from "../../database/schema/apiHits.js"; import { sql } from "drizzle-orm"; // Define the request body schema const requestSchema = z.object({ ip: z.string().optional(), endpoint: z.string(), action: z.string().optional(), lastBody: z.array(z.object({})).or(z.object({})).optional(), stats: z.string().optional(), }); type ApiHitData = z.infer; export const apiHit = async ( c: Context, data: ApiHitData ): Promise<{ success: boolean; data?: ApiHitData; errors?: any[] }> => { const info = getConnInfo(c); // console.log(`Your remote address is ${info.remote.address}`); try { // Extract IP from request headers or connection info const forwarded = c.req.header("host"); //console.log(forwarded); // Validate the data const checkData = { ip: info.remote.address!, endpoint: data?.endpoint, lastBody: data?.lastBody, action: data?.action, //stats: data?.stats, }; const validatedData = requestSchema.parse(checkData); const { data: apitHitData, error } = await tryCatch( db .insert(apiHits) .values(checkData) .onConflictDoUpdate({ target: [apiHits.endpoint, apiHits.ip], set: { stats: sql`${apiHits.stats} + 1`, lastBody: data?.lastBody, action: data?.action, upd_date: sql`NOW()`, }, }) ); if (error) { console.log(error); } // Proceed with the validated data return { success: true, data: validatedData }; } catch (error) { // Explicitly check if the error is an instance of ZodError if (error instanceof ZodError) { console.log({ success: false, errors: error.errors }); return { success: false, errors: error.errors }; } // Catch other unexpected errors return { success: false, errors: [{ message: "An unknown error occurred" }], }; } };