Appearance
Shared Kit (_shared)
Every Edge Function is built from the same reusable utilities in supabase/functions/_shared/. Unit tests are co-located in _shared/tests/ (auth.test.ts, cors.test.ts, errors.test.ts, response.test.ts). @supabase/supabase-js is pinned to 2.30.0.
Modules
| File | Key exports | Use |
|---|---|---|
cors.ts | corsHeaders, handleCors(req) | First line of every EF: returns a preflight Response or null. |
auth.ts | requireAuth(req), requireAdmin(req), optionalAuth(req), AuthResult, OptionalAuthResult | Resolve { user, serviceClient }; enforce JWT / admin role. |
errors.ts | AppError + ValidationError, AuthError, ForbiddenError, NotFoundError, ConflictError, RateLimitError, UnprocessableError, PartialSuccessError, DatabaseError, TimeoutError | Typed, status-mapped errors. Throw these; err() maps them. |
response.ts | ok(data, init?), err(functionName, error) | Uniform JSON responses; err() produces safe messages + structured logs. |
logging.ts | Logger, LoggerConfig | Structured JSON logs with an event field on INFO/WARN. |
error-handler.ts | isRetryableError, formatErrorResponse, logError | Correlation-id error formatting + retry classification (Type B). |
database.ts | getSupabaseClient, insertLogEntry, insertCronExecution, insertCacheOperation, getActiveCronJobs, batchInsert, batchUpdate, getJobByName | Ops-table helpers used by public_page_ops_* Type B functions. |
cloudflare.ts | cloudflare (purge API), PurgeResult | Cloudflare cache purge/invalidation from EFs. |
config-cache.ts | configCache, FeatureConfig | In-memory feature-config cache for hot paths. |
retry.ts | retryWithBackoff<T>(...) | Exponential-backoff retry for external calls (Type B / webhooks). |
Typed errors → HTTP status
Canonical usage
ts
import { handleCors } from '../_shared/cors.ts'
import { requireAuth } from '../_shared/auth.ts'
import { ValidationError } from '../_shared/errors.ts'
import { ok, err } from '../_shared/response.ts'
Deno.serve(async (req) => {
const preflight = handleCors(req); if (preflight) return preflight
try {
const { user, serviceClient } = await requireAuth(req)
const body = await req.json()
if (!body.action) throw new ValidationError('action is required.')
// ...business logic (complex parts in helpers.ts)
return ok({ result })
} catch (e) {
return err('manage-profile', e)
}
})
manage-profile/index.tsis the closest current reference for the auth block. See Backend architecture for the Type A / B / Webhook model and Adding an Edge Function for the full recipe.