Ir al contenido

Estructura del proyecto

Un proyecto inicial de Rebase consta de tres paquetes interconectados:

my-app/
├── .env # Generated for you: JWT_SECRET, a database password, a free port
├── rebase.json # Which apps this repository contains, and how each is built
├── package.json # Root workspace config
├── tsconfig.json # Typechecks scripts/; each workspace typechecks on its own
├── docker-compose.yml # Self-hosting: Postgres + the published runtime image
├── scripts/
│ └── example.ts # The SDK end to end against the running backend: `pnpm example`
│
├── config/ # Shared by the backend and the admin panel
│ ├── index.ts # Re-exports `collections`; the runtime reads `storageAuthorize` from here
│ ├── collections/ # Your data model
│ │ ├── index.ts # Sort order (`collections`) and `defaultSecurityRules` — not a registry
│ │ ├── posts.ts # Example collections
│ │ └── users.ts # The auth collection
│ ├── resources.ts # What this project needs from wherever it runs
│ ├── storage.ts # Who may read, write and list files
│ └── cms.d.ts # One line that makes the `admin` block legal here
│
├── backend/
│ ├── functions/ # Custom API routes, auto-mounted at /api/functions/<name>
│ │ └── hello.ts
│ └── src/
│ └── schema.generated.ts # Drizzle schema, regenerated from your collections
│
└── frontend/ # The admin panel (React + Vite)
├── src/App.tsx
├── src/main.tsx
└── vite.config.ts

tsc --noEmit en la raíz comprueba scripts/; en config/, backend/ o frontend/ comprueba ese workspace. Desde 0.25 En la 0.24 la raíz no tiene tsconfig.json, y tsc allí imprime su ayuda y no comprueba nada.

El frontend es una aplicación estándar de Vite + React + TypeScript. El archivo clave es App.tsx, que conecta todos los controladores de Rebase:

import React from "react";
import "@fontsource/jetbrains-mono";
import "@fontsource-variable/inter";
import "@fontsource-variable/instrument-sans";
import { Rebase, RebaseAuth, useRebaseAuthController } from "@rebasepro/app";
import { RebaseCMS, RebaseShell } from "@rebasepro/cms";
import { ErrorBoundary } from "@rebasepro/ui";
import { RebaseStudio } from "@rebasepro/studio";
import { createRebaseClient } from "@rebasepro/client";
import { collections } from "virtual:rebase-collections";
// `rebase dev` injects VITE_API_URL with the port it actually bound, and that
// port is derived from this project's path rather than fixed — so a
// `http://localhost:3001` fallback here names a port nothing is listening on.
// A deployed build serves the admin from the same origin as the API, where an
// empty value is exactly what you want.
const API_URL = import.meta.env.VITE_API_URL;
const GOOGLE_CLIENT_ID = import.meta.env.VITE_GOOGLE_CLIENT_ID;
export function App() {
const rebaseClient = React.useMemo(() => createRebaseClient({
baseUrl: API_URL,
// Store the refresh token in an httpOnly cookie (XSS-safe) rather than
// localStorage. The backend issues it via `auth.cookieAuth`.
auth: { authFlowMode: "cookie" }
}), []);
const authController = useRebaseAuthController({
client: rebaseClient,
googleClientId: GOOGLE_CLIENT_ID
});
return (
<ErrorBoundary fullPage>
<Rebase
client={rebaseClient}
authController={authController}
>
{/* The sign-in screen. On its own this changes nothing —
it is where you pass `loginView` to replace it. */}
<RebaseAuth />
<RebaseCMS
collections={collections}
/>
<RebaseStudio/>
<RebaseShell title="Rebase"/>
</Rebase>
</ErrorBoundary>
);
}

main.tsx lo monta bajo un basename de react-router obtenido de import.meta.env.BASE_URL, el cual rebase build establece a partir del path que esta aplicación declara en rebase.json; de este modo, los assets, el enrutador y el servidor coinciden en un único valor sin tener que definirlo tres veces.

  • createRebaseClient — Crea el cliente SDK que gestiona las peticiones HTTP, las conexiones WebSocket y la administración de tokens de autenticación
  • virtual:rebase-collections — Un plugin de Vite que importa automáticamente sus colecciones compartidas en tiempo de compilación
  • useRebaseAuthController — Mantiene el usuario autenticado y el ciclo de vida del token, y es lo que <Rebase> distribuye a todos los elementos por debajo de él

No hay ningún archivo de servidor que revisar, y ese es el diseño previsto: un proyecto generado declara runtime: "managed", por lo que la imagen publicada rebasepro/server arranca su proyecto. Lo que contiene backend/ es el código que el runtime recoge:

Ruta Qué es
backend/functions/ Rutas personalizadas, montadas automáticamente en /api/functions/<filename>
backend/crons/ Tareas programadas, detectadas de la misma manera (créelo cuando necesite una)
backend/src/schema.generated.ts El esquema de Drizzle de sus colecciones: lo escribe rebase init, y se regenera en cada ejecución de rebase dev y rebase build

El runtime configura:

  • API REST en /api/data/* — operaciones CRUD generadas para cada colección
  • Autenticación en /api/auth/* — registro, inicio de sesión, refresco, OAuth
  • Almacenamiento en /api/storage/* — subida y descarga de archivos
  • WebSocket — sincronización en tiempo real mediante LISTEN/NOTIFY de Postgres
  • Sus funciones y crons, a partir de los directorios indicados arriba

La configuración proviene de rebase.json, el directorio config/ y las variables de entorno. Consulte Environment & Configuration.

rebase build convierte todo esto en un bundle — las colecciones, funciones y crons compilados junto con un manifiesto — que el runtime administrado arranca. Nada en el bundle se escribe a mano; si desea ver uno, Runtime & Bundles detalla su contenido.

El panel que sirve el frontend tiene dos partes. Studio es la destinada a los desarrolladores — el editor de esquemas, la consola SQL, el explorador de políticas RLS — y se encuentra detrás del conmutador en el cajón lateral (drawer), no como un despliegue independiente. Consulte Studio.

Para tomar el control completo del proceso — sus propios middlewares, rutas y configuración de autenticación — ejecute rebase eject. Todo lo que sigue a continuación de este párrafo aplica únicamente a proyectos con eject: un proyecto generado no incluye ninguno de esos archivos y nada en él invoca a initializeRebaseBackend. rebase eject genera un punto de entrada que llama directamente a initializeRebaseBackend, además de un Dockerfile y un archivo compose que lo compila; a partir de ese momento, usted mantiene el servidor y las actualizaciones del runtime de la plataforma ya no se aplican al proyecto. Dicha interfaz está documentada en Custom Server Integration.

Las colecciones son la única fuente de verdad para su modelo de datos. Se definen en TypeScript y son consumidas tanto por el frontend (para la generación de la interfaz de usuario) como por el backend (para la generación de esquemas y el enrutamiento de la API).

import { defineCollection } from "@rebasepro/cms-types";
const productsCollection = defineCollection({
slug: "products",
name: "Products",
properties: {
name: { type: "string", name: "Name" },
price: { type: "number", name: "Price" }
}
});
// The default export is what the loader picks up — every file in this directory
// is loaded, listed in index.ts or not, and every collection in the scaffold is
// written this way.
export default productsCollection;

El slug se convierte en la ruta URL en la interfaz de administración y en el endpoint de la API REST (/api/data/products), y el nombre de la tabla en PostgreSQL adopta este valor por defecto. Agregue table únicamente cuando sean diferentes.

  1. Usted define las colecciones en config/collections/
  2. El backend las lee para generar esquemas de Drizzle y montar rutas REST
  3. El frontend las lee (mediante el plugin de Vite) para renderizar tablas, formularios y navegación
  4. La CLI las lee para generar el esquema de Drizzle (rebase schema generate), los tipos del SDK (rebase generate-sdk) y, a partir de ese esquema, archivos de migración (rebase db generate)

Mientras rebase dev está en ejecución, guardar un archivo en config/collections/ regenera backend/src/schema.generated.ts y los tipos del SDK en generated/sdk/, reinicia el backend, y el arranque crea las tablas y columnas que falten. Fuera de rebase dev, los pasos equivalentes son rebase schema generate y rebase generate-sdk.

En 0.23, rebase dev solo regenera el esquema, y rebase generate-sdk es un paso aparte.