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 | 1702x 192x 1409x 1104x 1104x 2x 1102x 844x 258x 1x 257x 16x 236x | // Standard API response helpers
import { whatsAppErrorCopy } from "@interioring/utils/whatsapp/errors";
import type { Context } from "hono";
import type { ContentfulStatusCode } from "hono/utils/http-status";
import { AppError, ConfigurationError } from "./errors";
import { WhatsAppApiError, WhatsAppConfigError } from "./whatsapp/client";
export interface ApiResponse<T = unknown> {
success: boolean;
data?: T;
error?: {
code: string;
message: string;
};
meta?: {
total?: number;
page?: number;
limit?: number;
offset?: number;
totalPages?: number;
hasNext?: boolean;
hasPrev?: boolean;
};
}
/**
* Send a success response
*/
export function success<T>(
c: Context,
data: T,
status: ContentfulStatusCode = 200,
meta?: ApiResponse["meta"],
) {
return c.json<ApiResponse<T>>(
{
success: true,
data,
...(meta && { meta }),
},
status,
);
}
/**
* Send a success response with pagination
*/
export function successWithPagination<T>(
c: Context,
data: T[],
meta: {
total: number;
page: number;
limit: number;
totalPages: number;
hasNext: boolean;
hasPrev: boolean;
},
) {
return c.json<ApiResponse<T[]>>({
success: true,
data,
meta,
});
}
/**
* Send an error response
*/
export function error(
c: Context,
code: string,
message: string,
statusCode: ContentfulStatusCode,
) {
return c.json<ApiResponse>(
{
success: false,
error: { code, message },
},
statusCode,
);
}
/**
* Handle errors consistently
* Note: Internal error messages are not exposed to clients for security
*/
export function handleError(c: Context, err: unknown) {
// Log the full error for debugging (server-side only)
console.error("API Error:", err);
// Configuration errors carry operator-only diagnostics (env var names,
// deployment commands). Scrub before sending to client; the full message
// is already logged above for debugging.
if (err instanceof ConfigurationError) {
return error(
c,
"CONFIGURATION_ERROR",
"Service temporarily unavailable. Please contact support.",
503,
);
}
// Handle known application errors - these have safe, user-facing messages
if (err instanceof AppError) {
return error(
c,
err.code,
err.message,
err.statusCode as ContentfulStatusCode,
);
}
// Handle WhatsApp config errors — service not configured
if (err instanceof WhatsAppConfigError) {
return error(c, "CONFIG_ERROR", "WhatsApp not configured", 500);
}
// Handle WhatsApp API errors — map to safe user-facing messages
if (err instanceof WhatsAppApiError) {
return error(c, "WHATSAPP_API_ERROR", whatsAppErrorCopy(err.code), 400);
}
// For unknown errors, don't expose internal details to clients
// The actual error is logged above for debugging
return error(c, "INTERNAL_ERROR", "An unexpected error occurred", 500);
}
|