Funzioni Personalizzate
Panoramica
Sezione intitolata “Panoramica”Le funzioni personalizzate ti permettono di aggiungere route API Hono arbitrarie accanto agli endpoint CRUD auto-generati di Rebase. Seguono lo stesso modello di scoperta basata su file delle collezioni e dei cron job: inserisci un file TypeScript nella tua directory functions/, e Rebase lo monterà automaticamente.
Usa le funzioni personalizzate per:
- Endpoint di logica aziendale — approvazioni, promozioni, workflow personalizzati
- Integrazioni di terze parti — webhook di Stripe, comandi Slack, proxy API esterni
- Endpoint pubblici — moduli di contatto, acquisizione lead, controlli di stato
- Query aggregate — statistiche dashboard, report, analisi
Definire una Funzione Personalizzata
Sezione intitolata “Definire una Funzione Personalizzata”Crea un file nella tua directory backend/functions/ che esporta di default un’applicazione Hono:
// backend/functions/hello.tsimport { Hono } from "hono";
const app = new Hono();
app.get("/", (c) => { return c.json({ message: "Hello from custom function!" });});
export default app;Questo viene montato su /api/functions/hello. Il nome del file (senza estensione) diventa il prefisso della route.
Configurazione
Sezione intitolata “Configurazione”Abilita le funzioni personalizzate aggiungendo functionsDir alla tua configurazione backend:
import path from "path";
const instance = await initializeRebaseBackend({ // ... other config functionsDir: path.resolve(__dirname, "../functions"),});Rebase farà:
- Scannerizzare la directory per file
.ts/.js - Convalidare che ogni esportazione di default sia un’app Hono (duck-typed tramite
.fetch()+.routes) - Montare ogni app su
/api/functions/<filename> - Applicare il middleware di autenticazione (vedi Autenticazione sotto)
Nomenclatura dei File e Mappatura delle Route
Sezione intitolata “Nomenclatura dei File e Mappatura delle Route”| File | Percorso di Montaggio |
|---|---|
functions/hello.ts | /api/functions/hello/* |
functions/send-invoice.ts | /api/functions/send-invoice/* |
functions/webhooks.ts | /api/functions/webhooks/* |
File che vengono saltati:
index.ts/index.js— riservati*.test.ts/*.test.js— file di test*.d.ts— dichiarazioni di tipo
Formati di Esportazione
Sezione intitolata “Formati di Esportazione”Il loader accetta due formati di esportazione:
App Hono (raccomandato)
Sezione intitolata “App Hono (raccomandato)”import { Hono } from "hono";const app = new Hono();app.get("/status", (c) => c.json({ ok: true }));export default app;Funzione Factory
Sezione intitolata “Funzione Factory”import { Hono } from "hono";export default function () { const app = new Hono(); app.get("/status", (c) => c.json({ ok: true })); return app;}Entrambi vengono rilevati tramite duck-typing — il loader controlla le proprietà .fetch() e .routes, quindi qualsiasi istanza compatibile con Hono funzionerà indipendentemente dalla versione di Hono installata.
Autenticazione
Sezione intitolata “Autenticazione”Le funzioni personalizzate vengono montate con lo stesso middleware di autenticazione delle route dati, ma con requireAuth: false. Questo significa:
- Il JWT dell’utente viene parsiato e iniettato nel contesto se presente
- Ma le richieste non vengono rifiutate se non viene fornito alcun JWT
- Devi proteggere esplicitamente le route che richiedono autenticazione
Protezione delle Route
Sezione intitolata “Protezione delle Route”Usa gli helper di autenticazione integrati di Rebase:
import { Hono } from "hono";
const app = new Hono();
// Public endpoint — no auth requiredapp.get("/public", (c) => { return c.json({ message: "Anyone can access this" });});
// Protected endpoint — requires a valid JWTapp.post("/protected", async (c) => { const user = c.get("user"); // Injected by Rebase middleware if (!user) { return c.json({ error: "Unauthorized" }, 401); } return c.json({ message: `Hello, ${user.uid}` });});
// Admin-only endpointapp.post("/admin-only", async (c) => { const user = c.get("user"); const roles: string[] = user?.roles ?? []; if (!roles.includes("admin")) { return c.json({ error: "Admin access required" }, 403); } return c.json({ message: "Admin operation succeeded" });});
export default app;Il middleware JWT di Rebase è limitato alle route API integrate (/api/data, /api/auth, ecc.). Le route delle funzioni personalizzate ottengono il contesto utente parsato, ma devi imporre il controllo degli accessi da solo.
Accedere al Database
Sezione intitolata “Accedere al Database”Le funzioni personalizzate vengono eseguite insieme a Rebase, quindi puoi accedere al database tramite due approcci:
1. Tramite il Singleton di Rebase (Raccomandato)
Sezione intitolata “1. Tramite il Singleton di Rebase (Raccomandato)”Il pacchetto @rebasepro/server-core fornisce un singleton rebase che ti dà accesso a livello amministrativo a tutti i servizi con ambito applicazione (dati, autenticazione, storage, email) da qualsiasi punto del tuo backend.
// backend/functions/approve-job.tsimport { Hono } from "hono";import { rebase } from "@rebasepro/server-core";
const app = new Hono();
app.post("/:id/approve", async (c) => { const id = c.req.param("id");
// Use the admin-level data API (bypasses RLS) await rebase.data.saveEntity("jobs", { id, status: "published", approved_at: new Date().toISOString(), });
return c.json({ success: true });});
export default app;2. Tramite Accesso Diretto a Drizzle
Sezione intitolata “2. Tramite Accesso Diretto a Drizzle”// backend/functions/reports.tsimport { Hono } from "hono";import { db } from "../src/db"; // Your Drizzle instanceimport { sql } from "drizzle-orm";
const app = new Hono();
app.get("/stats", async (c) => { const result = await db.execute(sql` SELECT COUNT(*) as total FROM jobs WHERE status = 'published' `); return c.json({ totalJobs: result.rows[0]?.total });});
export default app;Ordine di Registrazione delle Route
Sezione intitolata “Ordine di Registrazione delle Route”Le funzioni personalizzate vengono caricate e montate dopo che initializeRebaseBackend() completa la configurazione principale. L’ordine di inizializzazione è:
- Bootstrappers — Connessioni al database, tabelle di autenticazione, servizi realtime
- Route di autenticazione —
/api/auth/*,/api/admin/* - Route di storage —
/api/storage/* - Route dati —
/api/data/*(CRUD per le collezioni) - Funzioni personalizzate ←
/api/functions/* - Cron job —
/api/cron/* - WebSocket — Sottoscrizioni realtime
Ciò significa che le tue funzioni personalizzate hanno accesso a tutti i servizi inizializzati. Registra qualsiasi route che deve essere eseguita prima di Rebase direttamente sull’app Hono, prima di chiamare initializeRebaseBackend():
const app = new Hono();
// Questo viene eseguito PRIMA delle route di Rebaseapp.get("/health", (c) => c.json({ status: "ok" }));
// Inizializzazione di Rebase — registra tutte le route /api/*const instance = await initializeRebaseBackend({ app, /* ... */ });Esempio: Gestore Webhook
Sezione intitolata “Esempio: Gestore Webhook”// backend/functions/stripe-webhook.tsimport { Hono } from "hono";import Stripe from "stripe";import { instance } from "../src/index";
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);const app = new Hono();
app.post("/", async (c) => { const sig = c.req.header("stripe-signature")!; const body = await c.req.text();
const event = stripe.webhooks.constructEvent( body, sig, process.env.STRIPE_WEBHOOK_SECRET! );
if (event.type === "checkout.session.completed") { const session = event.data.object; await instance.driver.data.subscriptions.create({ user_id: session.client_reference_id, stripe_id: session.subscription, status: "active", }); }
return c.json({ received: true });});
export default app;Debugging
Sezione intitolata “Debugging”Quando una funzione viene caricata con successo, vedrai:
⚡ Loaded function route: helloSe il caricamento fallisce, il loader fornisce un output diagnostico:
[functions] broken-function.ts: default export is not a Hono app or factory. Skipping. tipo di esportazione: object (SomeClass) metodi prototipo: constructor, someMethod Suggerimento: assicurati che la funzione esporti un'app Hono creata con la stessa versione di Hono del server.Prossimi Passi
Sezione intitolata “Prossimi Passi”- Panoramica del Backend — Riferimento completo alla configurazione del backend
- Callback delle Entità — Esegui la logica sulle modifiche ai dati
- Cron Job — Task in background programmati