Simple API gateway for webhooks
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120import { crypto } from "@std/crypto"import { encodeHex } from "@std/encoding/hex"
export const kv = await Deno.openKv()
/** * Wraps a promise in a try/catch block and returns a Result object representing * either a successful value or an error. * * This utility function provides a more structured way to handle asynchronous operations * without using try/catch blocks throughout your codebase. It follows a pattern similar * to Rust's Result type, allowing for more predictable error handling. * * @template T - The type of the value returned by the promise on success * @template E - The type of the error object (defaults to Error) * * @param promise - The promise to wrap and execute * * @returns A Promise resolving to a discriminated union object with: * - On success: `{ success: true, value: T, error: null }` * - On failure: `{ success: false, value: null, error: E }` * * @example * // Success case * const successResult = await tryCatch(Promise.resolve('data')); * if (successResult.success) { * console.log(successResult.value); // 'data' * } * * @example * // Error case * const errorResult = await tryCatch(Promise.reject(new Error('Failed'))); * if (!errorResult.success) { * console.error(errorResult.error.message); // 'Failed' * } * * @example * // Using with custom error type * interface ApiError { code: number; message: string } * const apiCall = tryCatch<UserData, ApiError>(fetchUserData()); */export async function tryCatch<T, E = Error>( promise: Promise<T>,): Promise< | { success: true value: T error: null } | { success: false value: null error: E }> { try { const value = await promise return { success: true, value, error: null } } catch (error) { return { success: false, value: null, error: error as E } }}
/** * Fetches data from a URL with caching. * Cache is stored in the KV * @param url - The URL to fetch data from. * @returns A promise that resolves to an object with success status, value, and error. */export async function fetchWithCache<T>(url: string): Promise< | { success: true value: T error: null } | { success: false value: null error: string }> { // Calculate the hash of the request URL const keybuffer = new TextEncoder().encode(url) const hashBuffer = await crypto.subtle.digest("SHA-256", keybuffer) const hash = encodeHex(hashBuffer)
// Check if the data is already in cache const cached = await kv.get<T>(["fetch-cache", hash]) if (cached.value) { console.info("Serving cached request data") return { success: true, value: cached.value, error: null, } }
// Fetch the data from the URL const data = await tryCatch( fetch(url).then((res) => res.json()), )
if (!data.success) { return { success: false, value: null, error: data.error.message, } }
// Store the fetched data in cache, with a 1-day expiration await kv.set(["fetch-cache", hash], data.value, { expireIn: 60 * 60 * 24 })
return { success: true, value: data.value, error: null, }}