Vue d'ensemble du backend
Vue d’ensemble
Section intitulée « Vue d’ensemble »Le backend Rebase est un serveur Node.js basé sur Hono qui fournit :
- API REST — Points de terminaison CRUD générés automatiquement pour chaque collection
- Authentification — Jetons JWT, connexion OAuth et OIDC, liens magiques, codes à usage unique, MFA, clés d’API, gestion des utilisateurs et des rôles
- Stockage — Téléversement/téléchargement de fichiers avec le système de fichiers local ou S3
- WebSocket — Synchronisation des données en temps réel via PostgreSQL LISTEN/NOTIFY
- Historique des entités — Piste d’audit pour chaque modification de données
- Branching de base de données — Copies instantanées et isolées de bases de données pour le dev, le staging et les tests
- Tâches Cron — Tâches d’arrière-plan planifiées avec tableau de bord de surveillance
Tout est initialisé avec une seule fonction :
import { initializeRebaseBackend } from "@rebasepro/server";import { createPostgresAdapter } from "@rebasepro/server-postgres";import { env } from "./env";
const instance = await initializeRebaseBackend({ app, server, collectionsDir: "./config/collections", database: createPostgresAdapter({ connection: db, schema: { tables, enums, relations } }), auth: { jwtSecret: env.JWT_SECRET, }, storage: { type: "local", basePath: "./uploads" }, history: true, enableSwagger: env.NODE_ENV !== "production"});Depuis 0.25 Cet unique appel est un
raccourci au-dessus d’étapes publiques : installUnhandledRejectionHandler évite qu’un rejet
isolé ne mette fin au processus, createRebaseBackend construit le backend,
setDefaultBackend en fait celui dont répond l’API de niveau module, et
mount, attachRealtime et start le servent. Pour ne monter que certains groupes de
routes, les placer à d’autres chemins, laisser les minuteurs à un autre processus, ou faire
tourner deux backends dans un même processus, appelez vous-même les étapes. Voir
Intégration de serveur personnalisé.
Où réside chaque option
Section intitulée « Où réside chaque option »Cet appel représente la forme éjectée — celle que vous écrivez vous-même après un rebase eject, ou dans un serveur personnalisé. Un projet généré à partir d’un template ne l’a pas : le runtime publié démarre le projet, et chaque option provient d’une variable d’environnement dans .env, d’un export depuis config/index.ts, ou d’un répertoire que le bundle déclare dans rebase.json.
Les deux voies aboutissent au même RebaseBackendConfig. En voici la correspondance complète.
| Option | Runtime managé |
|---|---|
basePath |
REBASE_BASE_PATH (par défaut /api) |
collections, collectionsDir |
le répertoire config/collections/, déclaré par rebase.json |
functions, functionsDir |
backend/functions/ |
crons, cronsDir |
backend/crons/ |
bootstrappers, database |
DATABASE_URL, plus une déclaration database("<key>") dans config/resources.ts pour chaque base de données au-delà de celle par défaut |
auth |
JWT_SECRET, les variables OAUTH_* et config/collections/users |
storage |
les variables STORAGE_*, plus une déclaration bucket("<key>") dans config/resources.ts pour chaque bucket au-delà de celui par défaut |
storageAuthorize |
export const storageAuthorize depuis config/index.ts |
storagePublicRead |
STORAGE_PUBLIC_READ |
storageRenditionCache |
STORAGE_RENDITION_CACHE |
storageInsecureAllowAnyAuthenticated |
STORAGE_ALLOW_ANY_AUTHENTICATED |
callbacks |
export const callbacks depuis config/index.ts |
history |
REBASE_HISTORY (activé par défaut) — sous forme booléenne uniquement |
enableSwagger |
REBASE_ENABLE_SWAGGER ; non défini signifie activé hors production |
compression |
REBASE_COMPRESSION |
maxBodySize |
REBASE_MAX_BODY_SIZE |
logging |
LOG_LEVEL |
provisionSchema, surfaces, ownership, functionsSelection, functionsUpstream |
REBASE_ROLE — voir Processus séparés |
corsHandled |
Le CORS est installé par le runtime à partir de CORS_ORIGINS |
schemaVersion, runtimeVersion |
le build inscrit les deux dans le bundle |
app, server, provisioningDriverResult |
le runtime les crée |
Options sans équivalent managé
Section intitulée « Options sans équivalent managé »Celles-ci ne disposent d’aucune variable d’environnement ni d’aucun export de configuration. Elles ne sont accessibles que depuis un appel manuel à initializeRebaseBackend — lors d’un rebase eject, ou dans un serveur personnalisé :
rateLimit · jobs · csrf · cronPersistence · functionsTimeoutMs ·
storagePolicies · storageTriggers · baas · liveSchema · rlsAudit ·
history sous sa forme d’objet ({ retention })
schemaEditor est obligatoirement désactivé dans un bundle compilé : l’éditeur réécrit les fichiers sources des collections, or un bundle ne contient que des sorties compilées.
Ce qui est créé
Section intitulée « Ce qui est créé »Après l’initialisation, ces routes sont montées :
| Chemin | Rôle |
|---|---|
/api/auth/* |
Authentification (inscription, connexion, rafraîchissement, OAuth, liens magiques, codes à usage unique, MFA) |
/api/admin/* |
Utilisateurs, rôles, clés de service, cron, sauvegardes, journaux et schéma, chacun derrière sa propre portée |
/api/storage/* |
Téléversement, téléchargement et suppression de fichiers |
/api/data/:slug |
Opérations CRUD par collection (GET, POST, PATCH, DELETE) |
/api/data/:slug/:id/history |
Historique des modifications de l’entité (si activé) |
/api/docs |
Spécification OpenAPI (lorsque enableSwagger: true) |
/api/swagger |
Interface Swagger UI (mode développement, lorsque enableSwagger: true) |
/api/meta/contract |
Schéma des collections du projet (exige schema:read) |
/api/meta/schema-version |
Chaîne de version pour ce schéma (non authentifié) |
/api/functions/* |
Routes de fonctions personnalisées (lorsque functions ou functionsDir est défini) |
/api/admin/cron/* |
Gestion des tâches cron (cron:read / cron:write, lorsque crons ou cronsDir est défini) |
| WebSocket sur mise à niveau (upgrade) | Abonnements en temps réel, sur / pour une API à /api |
Le cycle de vie de l’initialisation
Section intitulée « Le cycle de vie de l’initialisation »Lorsque vous invoquez initializeRebaseBackend(), le framework déclenche une séquence de démarrage séquentielle en 5 étapes :
[Start Boot] │ ▼1. ENV validation (Zod parsing of jwt, databases, cors) │ ▼2. Dynamic Collection Loading (Chokidar watches .ts files, AST parsing) │ ▼3. Database Bootstrapping (Acquires advisory lock, creates schemas/auth/helper SQL functions) │ ▼4. Service Initialization (Auth, Storage S3/Local client instances, Cron store seeding) │ ▼5. Route Mounting & Edge Loading (Hono controllers, custom functions, WebSocket binding) │ ▼[Boot Complete]Que se passe-t-il en cas d’échec du démarrage
Section intitulée « Que se passe-t-il en cas d’échec du démarrage »Le démarrage échoue de manière stricte et immédiate. Si la base de données est inaccessible, que les identifiants sont incorrects ou que le schéma de collection ne peut pas être appliqué, initializeRebaseBackend lève une exception, rien n’est servi et le processus se termine avec le code de sortie 1. Il n’y a aucun mode dégradé ni serveur partiel : un conteneur incapable de joindre sa base de données redémarre, et l’erreur ayant provoqué son arrêt est la dernière chose présente dans ses logs.
C’est délibéré. Un serveur qui démarre en répondant aux requêtes d’authentification alors que chaque route /api/data/* échoue est bien plus difficile à diagnostiquer qu’un serveur qui ne démarre jamais — et un orchestrateur peut réagir face à une boucle de plantage (crash loop).
Avant la première requête, le démarrage teste la connexion et affiche le diagnostic : l’hôte et le port qu’il n’a pas pu joindre, la raison fournie par le pilote lui-même (ECONNREFUSED, password authentication failed for user "app"), et la solution. Consultez la page de Dépannage pour obtenir la liste détaillée de chaque défaillance.
Une fois en service : /livez et /health
Section intitulée « Une fois en service : /livez et /health »Deux sondes, répondant à deux questions différentes.
| Chemin | Interroge la base de données | Réponse |
|---|---|---|
/livez |
Non | 200 {"status":"ok"} tant que le processus est en cours d’exécution. À utiliser comme sonde de vivacité (liveness probe). |
/health |
Oui, chaque source de données | 200 {"status":"ok"} lorsque chaque source de données configurée répond ; 503 {"status":"degraded"} dès que l’une d’entre elles échoue. À utiliser comme sonde d’aptitude (readiness probe). |
Placer une sonde de vivacité sur /health est une erreur importante à souligner : une saute d’humeur passagère de la base de données pousserait l’orchestrateur à tuer un processus par ailleurs sain, transformant une courte panne en boucle de redémarrage.
/health n’est pas authentifié, il ne publie donc que le verdict et non la cause — en dehors du développement, il indique quelle source de données est dégradée, rien de plus. Le message d’erreur du pilote mentionne l’hôte, le port, le nom de la base de données et le rôle, et cette information est dirigée vers les logs. Les deux chemins sont également exposés sous basePath (/api/health).
Référence de configuration
Section intitulée « Référence de configuration »interface RebaseBackendConfig { // HTTP framework app: Hono; // Hono application instance server: Server; // Node.js HTTP server (for WebSocket attachment) basePath?: string; // Route prefix (default: "/api")
// Collections collections?: CollectionConfig[]; // Your collection definitions collectionsDir?: string; // Auto-load collections from a directory
// Database adapter (PostgreSQL, SQLite, etc.) database?: DatabaseAdapter;
// Authentication configuration or custom adapter auth?: RebaseAuthConfig | AuthAdapter;
// File storage storage?: BackendStorageConfig | Record<string, BackendStorageConfig>;
// Entity history history?: boolean | HistoryConfig;
// OpenAPI/Swagger enableSwagger?: boolean;
// Custom API endpoints: values, or a directory of files (not both) functions?: Record<string, FunctionApp>; // { "send-invoice": app } → /api/functions/send-invoice functionsDir?: string; // Auto-load Hono routes from a directory
// Scheduled tasks: values, or a directory of files (not both) crons?: Record<string, CronJobDefinition>; // { "nightly-report": defineCron(…) } cronsDir?: string; // Auto-load cron jobs from a directory cronPersistence?: boolean; // Write run logs to rebase.cron_logs (default: true)
// HTTP behaviour compression?: boolean; // gzip/deflate for API responses (default: true) maxBodySize?: number; // Request-body ceiling in bytes (default: 10MB; 0 disables) csrf?: { origin: string | string[] | ((origin: string) => boolean) };
// Schema editing schemaEditor?: boolean; // Force the schema-editor routes on or off
// Logging logging?: { level?: "error" | "warn" | "info" | "debug" };}Cinq de ces options sont faciles à négliger et modifient des comportements que vous ne pourriez observer qu’autrement :
| Clé | Valeur par défaut | Description |
|---|---|---|
compression |
true |
gzip/deflate sur les réponses de l’API, négocié d’après Accept-Encoding. Les corps déjà compressés, streamés et avec l’en-tête no-transform ne sont pas modifiés, pas plus que les corps de moins de 1 Ko (gzip y coûte plus qu’il ne rapporte), il est donc sans danger de la laisser active — une liste JSON volumineuse voit généralement sa taille réduite d’environ un facteur 20. Définissez à false lorsqu’un proxy comme nginx, Cloudflare ou un autre en amont effectue déjà la compression, afin d’éviter un double coût de traitement. Variable d’environnement : REBASE_COMPRESSION. |
maxBodySize |
10485760 (10 Mo) |
Plafond pour les corps de requêtes sur les routes API ; 0 le désactive. Les téléversements de stockage utilisent le maxFileSize propre à la configuration de stockage (50 Mo), qui prévaut pour ces routes. Variable d’environnement : REBASE_MAX_BODY_SIZE. |
csrf |
désactivé | Activation explicite (Opt-in). Une API BaaS est appelée par des applications mobiles, des SPAs sur d’autres domaines et des outils CLI, dont aucun n’envoie d’en-tête Origin qu’une liste fixe accepterait — ce n’est donc pas activé par défaut. Activez-le en spécifiant les origines utilisées par vos clients navigateurs. Aucune variable d’environnement : éjectez pour le configurer. |
cronPersistence |
true |
Détermine si les journaux d’exécution sont enregistrés dans rebase.cron_logs. false permet de faire tourner les tâches tout en conservant l’historique uniquement en mémoire, ce qui est alors perdu par le panneau Studio lors d’un redémarrage. |
schemaEditor |
activé hors production, quand collectionsDir est défini |
Force l’activation ou la désactivation des routes de l’éditeur de schéma. L’éditeur réécrit les fichiers sources des collections, il a donc besoin d’un répertoire dans lequel écrire — or un bundle compilé n’en a pas, c’est pourquoi un déploiement n’en dispose jamais. |
Le reste de RebaseBackendConfig est soit documenté sur sa propre page (auth, storage, jobs, callbacks, liveSchema, rlsAudit), soit marqué @internal : bootstrappers, provisioningDriverResult, provisionSchema, corsHandled, functionsSelection, functionsUpstream et runtimeVersion sont renseignés par bootFromBundle à partir de l’environnement, et les passer manuellement risque d’entrer en conflit avec ce que le runtime attend pour ce processus.
L’instance du backend
Section intitulée « L’instance du backend »initializeRebaseBackend renvoie le backend qu’il a construit, déjà monté et
démarré. Son type est RebaseBackendInstance, qui est RebaseBackend, le
type que renvoie createRebaseBackend :
const instance = await initializeRebaseBackend(config);
// Internal service accessinstance.driver // Default data driverinstance.driverRegistry // All drivers (for multi-database)instance.realtimeService // Default realtime serviceinstance.auth?.userService // User managementinstance.storageController // Default storageinstance.storageRegistry // All storage backendsinstance.collectionRegistry // Collection metadatainstance.history?.historyService // Entity historyinstance.cronScheduler // Cron job scheduler (when crons or cronsDir is set)instance.jobQueue // Durable job queue (when jobs are enabled)instance.setCollectionCallbacks(slug, callbacks) // Replace a collection's callbacksinstance.shutdown() // Drain and stop; also closes the server it was givenDepuis 0.25 Elle porte aussi
rebase, le client en processus, fetch(request), routes, les groupes de routes
sous forme de sous-applications Hono, services, ses propres clés JWT, son modèle d’accès, son
magasin de clés API et ses limiteurs de débit, ainsi que verifyCredential(token) ; voir
Intégration de serveur personnalisé.
Remarque : Bien que l’
instanceexpose ces services internes, le code applicatif (comme les fonctions personnalisées et les tâches cron) doit utiliser le singletonrebasede@rebasepro/serverpour interagir avec l’API backend. Depuis 0.25 Dans une requête, une exécution cron ou un job,rebaseest le backend qui la sert ; ailleurs, c’est le backend par défaut du processus, queinitializeRebaseBackendrègle sur son propre backend.
API REST
Section intitulée « API REST »L’API REST est générée automatiquement à partir de vos collections. Chaque collection dispose de ces points de terminaison :
| Méthode | Chemin | Description |
|---|---|---|
GET |
/api/data/:slug |
Lister les entités — le filtrage, le tri, la pagination et la recherche se font par paramètres de requête |
GET |
/api/data/:slug/count |
Nombre de lignes correspondant à cette même requête |
GET |
/api/data/:slug/aggregate |
count/sum/avg/min/max, éventuellement groupés |
GET |
/api/data/:slug/:id |
Récupérer une entité unique |
POST |
/api/data/:slug |
Créer une nouvelle entité |
PATCH |
/api/data/:slug/:id |
Mettre à jour les champs envoyés |
DELETE |
/api/data/:slug/:id |
Supprimer un enregistrement |
POST |
/api/data/:slug/bulk |
Créer plusieurs lignes dans une seule transaction |
PATCH |
/api/data/:slug/bulk |
Mettre à jour plusieurs lignes dans une seule transaction |
POST |
/api/data/:slug/bulk/delete |
Supprimer plusieurs lignes dans une seule transaction |
Paramètres de requête
Section intitulée « Paramètres de requête »Il existe une référence unique pour ces paramètres, et ce n’est pas cette page. La documentation de l’API REST détaille les deux syntaxes de requête acceptées par le serveur — le format de type PostgREST ?column=op.value et le format JSON ?where= — ainsi que orderBy, limit/offset, include, fields, searchString et la recherche vectorielle. La page des Endpoints constitue l’index de chaque route montée par le serveur, y compris celles générées automatiquement.
Tout paramètre qui n’est pas réservé par le serveur est interprété comme un filtre sur la colonne portant ce nom ; par conséquent, un paramètre inventé ne provoque pas d’erreur : il ne correspondra simplement à aucun résultat.
WebSocket
Section intitulée « WebSocket »Le serveur WebSocket se greffe sur le même serveur HTTP et fournit des abonnements en temps réel. Depuis 0.25 Il répond aux mises à niveau sur un seul chemin, / pour une API à /api, là où le SDK se connecte, et laisse tous les autres chemins à vos propres écouteurs upgrade ; sur la 0.24, il prend toutes les mises à niveau du serveur :
- Abonnement aux changements de collection — soyez notifié dès qu’une entité d’une collection est créée, mise à jour ou supprimée
- Abonnement aux changements d’entités — soyez notifié lorsqu’une entité spécifique est modifiée
- Gestion automatique de la reconnexion dans le SDK typé
Le backend s’appuie en interne sur le mécanisme LISTEN/NOTIFY de PostgreSQL. Pour les déploiements multi-instances, fournissez une chaîne connectionString dans votre PostgresBootstrapper pour activer la diffusion inter-instances.
Gestion des erreurs
Section intitulée « Gestion des erreurs »Chaque défaillance — quelle que soit la route ou le sous-système concerné — est renvoyée dans une enveloppe unique :
{ "error": { "message": "Entity not found", "code": "NOT_FOUND", "requestId": "9f1c0b8e-4d2a-4e1b-9d0f-2c7a5b3e6a11" }}| Champ | Toujours présent | Ce que c’est |
|---|---|---|
message |
oui | Rédigé pour un être humain lisant une console. Désigne l’obstacle rencontré, pas la règle. |
code |
oui | En SCREAMING_SNAKE_CASE et stable. C’est le champ à utiliser pour vos embranchements conditionnels. |
details |
non | Charge utile structurée lorsque le refus porte sur un élément précis — une liste de chemins en échec, un ensemble de champs inconnus. |
requestId |
non | Présent lorsque la requête en comportait un ou qu’un identifiant lui a été attribué ; reprend X-Request-ID. À inclure dans un rapport de bug. |
Le statut HTTP figure sur la réponse elle-même, pas dans le corps. Basez vos conditions sur code et non sur message — les messages sont rédigés pour des humains et sont susceptibles d’évoluer.
Le SDK typé convertit chacune de ces réponses en une RebaseApiError contenant status, code et details — y compris les échecs qui n’ont jamais pu atteindre le serveur. Une connexion refusée, une défaillance DNS, une erreur CORS ou une annulation arrive sous la forme status: 0, code: "NETWORK_ERROR", avec l’erreur originelle du runtime dans cause, plutôt que sous la forme aléatoire avec laquelle fetch aurait pu rejeter. Une réponse sans enveloppe — un 413 de proxy, un 502 de répartiteur de charge — reçoit tout de même un code déduit de son statut (PAYLOAD_TOO_LARGE, SERVICE_UNAVAILABLE, INTERNAL_ERROR, …), et un client construit hors d’un navigateur sans baseUrl échoue avec BASE_URL_REQUIRED plutôt qu’avec une erreur réseau.
Depuis 0.25 Une lecture qui reçoit un succès sans la forme attendue — un 204, un corps vide, une page sans liste data — échoue avec UNEXPECTED_RESPONSE au lieu de se résoudre en « aucune ligne », et createMany, updateMany, deleteMany ou batch appelés avec autre chose qu’un tableau échouent avec INVALID_BULK_BODY, le code que le serveur utilise pour la même erreur. Le code applicatif n’a ainsi qu’une seule classe à capturer :
async function setPrice(id: string, price: number) { try { return await client.data.products.update(id, { price }); } catch (e) { if (e instanceof RebaseApiError && e.code === "NOT_FOUND") return null; throw e; }}Étapes suivantes
Section intitulée « Étapes suivantes »- Authentification — Fournisseurs JWT, OAuth et OIDC, MFA, clés d’API, gestion des utilisateurs
- Stockage — Stockage de fichiers en local et sur S3
- Callbacks d’entités — Hooks de cycle de vie et API
context.data - Historique des entités — Piste d’audit
- Fonctions personnalisées — Ajouter des points de terminaison d’API personnalisés
- Tâches Cron — Tâches d’arrière-plan planifiées
- Branching de base de données — Copies instantanées de base de données pour dev/staging
- Déploiement — Mettre le backend en production