import { ZodError } from 'zod' // ── Action Result Type ─────────────────────────────────────────────── export type ActionResult> = | { ok: true; data?: T } | { ok: false; error: string; fieldErrors?: Record } // ── Helper to build results ────────────────────────────────────────── export function actionOk>(data?: T): ActionResult { return { ok: true, data: data ?? ({} as T) } } export function actionError(message: string): ActionResult { return { ok: false, error: message } } // ── Throwable error ────────────────────────────────────────────────── export class ActionError extends Error { constructor(message: string) { super(message) this.name = 'ActionError' } } // ── Error handler ──────────────────────────────────────────────────── export function handleActionError(error: unknown): ActionResult { if (error instanceof ZodError) { return { ok: false, error: 'Validation failed', fieldErrors: error.flatten().fieldErrors as Record, } } if (error instanceof Error && error.name === 'ActionError') { return { ok: false, error: error.message } } // Prisma P2025 if ( error instanceof Error && error.constructor.name === 'PrismaClientKnownRequestError' && (error as Error & { code?: string }).code === 'P2025' ) { return { ok: false, error: 'Not found' } } console.error('[Action error]', error) return { ok: false, error: 'Internal server error' } }