@rebasepro/agent-skills 0.0.1-canary.4829d6e

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +96 -0
  3. package/package.json +21 -0
  4. package/skills/rebase-admin/SKILL.md +816 -0
  5. package/skills/rebase-api/SKILL.md +673 -0
  6. package/skills/rebase-api/references/.gitkeep +3 -0
  7. package/skills/rebase-auth/SKILL.md +1323 -0
  8. package/skills/rebase-auth/references/.gitkeep +3 -0
  9. package/skills/rebase-backend-postgres/SKILL.md +633 -0
  10. package/skills/rebase-backend-postgres/references/.gitkeep +3 -0
  11. package/skills/rebase-basics/SKILL.md +757 -0
  12. package/skills/rebase-basics/references/.gitkeep +3 -0
  13. package/skills/rebase-collections/SKILL.md +1421 -0
  14. package/skills/rebase-collections/references/.gitkeep +3 -0
  15. package/skills/rebase-cron-jobs/SKILL.md +704 -0
  16. package/skills/rebase-cron-jobs/references/.gitkeep +1 -0
  17. package/skills/rebase-custom-functions/SKILL.md +281 -0
  18. package/skills/rebase-deployment/SKILL.md +894 -0
  19. package/skills/rebase-deployment/references/.gitkeep +3 -0
  20. package/skills/rebase-design-language/SKILL.md +692 -0
  21. package/skills/rebase-email/SKILL.md +701 -0
  22. package/skills/rebase-email/references/.gitkeep +1 -0
  23. package/skills/rebase-entity-history/SKILL.md +485 -0
  24. package/skills/rebase-entity-history/references/.gitkeep +1 -0
  25. package/skills/rebase-local-env-setup/SKILL.md +189 -0
  26. package/skills/rebase-local-env-setup/references/.gitkeep +3 -0
  27. package/skills/rebase-realtime/SKILL.md +759 -0
  28. package/skills/rebase-realtime/references/.gitkeep +3 -0
  29. package/skills/rebase-sdk/SKILL.md +617 -0
  30. package/skills/rebase-sdk/references/.gitkeep +0 -0
  31. package/skills/rebase-security/SKILL.md +646 -0
  32. package/skills/rebase-storage/SKILL.md +989 -0
  33. package/skills/rebase-storage/references/.gitkeep +3 -0
  34. package/skills/rebase-studio/SKILL.md +772 -0
  35. package/skills/rebase-studio/references/.gitkeep +3 -0
  36. package/skills/rebase-ui-components/SKILL.md +1579 -0
  37. package/skills/rebase-ui-components/references/.gitkeep +3 -0
  38. package/skills/rebase-webhooks/SKILL.md +618 -0
  39. package/skills/rebase-webhooks/references/.gitkeep +1 -0
@@ -0,0 +1,757 @@
1
+ ---
2
+ name: rebase-basics
3
+ description: Core principles, workflow, and maintenance for using Rebase. Use this for all Rebase CLI tasks, project setup, MCP server usage, and general development. Make sure to ALWAYS use this skill whenever you are trying to use Rebase, even if not explicitly asked.
4
+ ---
5
+
6
+ # Prerequisites
7
+
8
+ Please complete these setup steps before proceeding, and remember your progress to avoid repeating them in future interactions.
9
+
10
+ 1. **Local Environment Setup:** Verify the environment is properly set up:
11
+ - Run `node --version` to check Node.js is installed (v20+ required).
12
+ - Run `pnpm --version` to check pnpm is installed. If not, install it: `npm install -g pnpm`.
13
+ - Verify PostgreSQL is available: `psql --version` or confirm Docker is running with a Postgres container.
14
+ - If any of these checks fail, use the `rebase-local-env-setup` skill to get the environment ready.
15
+
16
+ 2. **Authentication:**
17
+ Ensure you are logged in to Rebase Cloud for MCP server access. Run `rebase login`. This opens a browser for Google OAuth.
18
+ - Tokens are stored at `~/.rebase/tokens.json` and shared between CLI and MCP server.
19
+ - If the browser fails to open, check the CLI output for a manual URL.
20
+
21
+ 3. **Active Project:**
22
+ Most Rebase tasks require a project context.
23
+ - For Rebase Cloud: Run `rebase login` and select your project via the MCP `list_projects` tool.
24
+ - For self-hosted: Ensure your `.env` file in the project root contains a valid `DATABASE_URL`.
25
+
26
+ # Rebase Usage Principles
27
+
28
+ Please adhere to these principles when working with Rebase, as they ensure reliability and consistency:
29
+
30
+ 1. **Use pnpm exclusively:** Rebase uses pnpm as its package manager. Never use `npm` or `yarn`. All commands should use `pnpm run`, `pnpm install`, `pnpm add`, etc.
31
+
32
+ 2. **Never convert to `any`:** TypeScript strictness is critical. Never use `as any` type assertions. Use proper typing, `unknown`, or explicit type narrowing instead.
33
+
34
+ 3. **Follow the Schema-as-Code approach:** Schemas are defined as standalone TypeScript files. The visual Studio generates TypeScript via AST manipulation — it does NOT run raw SQL. Always define collections in code first.
35
+
36
+ 4. **Use the two-step migration workflow:**
37
+ - `rebase schema generate` — converts collection definitions to Drizzle ORM schema
38
+ - `rebase db push` (development) or `rebase db generate && rebase db migrate` (production)
39
+
40
+ 5. **Use Rebase MCP Server tools when available:** For data operations, user management, and collection browsing, prefer the MCP tools (`list_documents`, `get_document`, `create_document`, etc.) over writing manual API calls.
41
+
42
+ 6. **Respect the monorepo structure:** See the [Package Reference](#package-reference) section below for the full list of packages and when to use each.
43
+
44
+ 7. **Never deploy unless explicitly asked:** Agents should never run `rebase deploy`, `firebase deploy`, `gcloud deploy`, or any command that pushes code to live infrastructure unless the user explicitly asks you to deploy in the current conversation. Provide the exact command and let the user run it themselves if they prefer.
45
+
46
+ 8. **Scripting and Data Tasks:** Default to using the Rebase SDK (`@rebasepro/client` or `@rebasepro/server`) to write scripts or tasks for manipulating data. For standalone scripts running locally, you can dynamically read the active backend URL from the `.rebase-dev-url` temp file automatically created by the dev server. For internal server-side backend tasks, use the global `import { rebase } from "@rebasepro/server"` singleton. For calling custom backend functions from the frontend, use `client.functions.invoke('name', payload)` — NEVER manually construct `/api/functions/` URLs or extract auth tokens from `localStorage`. NEVER default to using raw `psql` queries or raw REST API calls (`fetch`/`curl`) unless explicitly instructed or the SDK lacks the functionality.
47
+
48
+ # Project Structure
49
+
50
+ ## Scaffolded Project Structure (CLI)
51
+
52
+ When you initialize a Rebase project via the CLI (`rebase init`), the generated project structure contains:
53
+
54
+ ```
55
+ <project-root>/
56
+ ├── frontend/ # React frontend (Vite)
57
+ ├── backend/ # Hono backend server
58
+ │ └── src/
59
+ │ ├── index.ts # Server entry point
60
+ │ └── schema.generated.ts # Auto-generated Drizzle schema
61
+ ├── config/ # Application configuration
62
+ │ └── collections/ # TypeScript collection files (one per collection)
63
+ │ └── index.ts # Barrel export of all collections
64
+ ├── .env # Environment variables (generated from .env.example)
65
+ ├── .env.example # Template with placeholder secrets
66
+ ├── docker-compose.yml # PostgreSQL container (when no custom DB provided)
67
+ ├── drizzle.config.ts # Drizzle ORM configuration
68
+ ├── pnpm-workspace.yaml # pnpm workspace definition
69
+ └── package.json # Root workspace package.json
70
+ ```
71
+
72
+ ### Key Files
73
+
74
+ | File | Purpose |
75
+ |------|---------|
76
+ | `.env` | Environment variables — secrets, DATABASE_URL, JWT_SECRET |
77
+ | `config/collections/*.ts` | Collection definitions (schema-as-code) |
78
+ | `backend/src/index.ts` | Server entry point — calls `initializeRebaseBackend()` |
79
+ | `backend/src/schema.generated.ts` | Auto-generated by `rebase schema generate` — DO NOT edit manually |
80
+ | `.rebase-dev-port` | Written by `rebase dev` — stores the resolved backend port |
81
+ | `.rebase-dev-url` | Written by `rebase dev` — stores `http://localhost:<port>` for scripts |
82
+
83
+ ## Framework Monorepo Structure
84
+
85
+ For development of the Rebase framework itself, the repository is organized as a modular monorepo:
86
+
87
+ ```
88
+ rebase/
89
+ ├── app/ # Example application (scaffolded structure above)
90
+ │ ├── frontend/ # React frontend (Vite)
91
+ │ ├── backend/ # Hono backend server
92
+ │ └── config/ # Application configuration
93
+ │ └── collections/ # TypeScript collection files (one per collection)
94
+ ├── packages/ # each directory is its package: `@rebasepro/<dir>`
95
+ │ ├── types/ # shared kernel — isomorphic, no UI, no node
96
+ │ ├── utils/
97
+ │ ├── common/
98
+ │ ├── client/ # the SDK
99
+ │ ├── server/ # BaaS — Hono coordinator. Never imports a UI package
100
+ │ ├── server-postgres/ # database driver
101
+ │ ├── server-mongo/ # database driver
102
+ │ ├── client-postgres/
103
+ │ ├── cli/
104
+ │ ├── codegen/
105
+ │ ├── inference/
106
+ │ ├── mcp/
107
+ │ ├── ui/ # CMS — React tier
108
+ │ ├── forms/
109
+ │ ├── app/ # the runtime admin/studio/plugins register into
110
+ │ ├── admin/
111
+ │ ├── firebase/
112
+ │ ├── studio/ # Full — BaaS console (admin is an optional peer)
113
+ │ ├── plugin-ai/
114
+ │ └── plugin-insights/
115
+ ├── pnpm-workspace.yaml
116
+ └── package.json
117
+ ```
118
+
119
+ The tiers are adoption modes, not separate products — see `MODULAR-ARCHITECTURE.md`.
120
+ A BaaS install is `server` + a driver + `client`, with no React in the tree.
121
+
122
+ ## Package Reference
123
+
124
+ | Package | Purpose | When to use |
125
+ |---------|---------|-------------|
126
+ | `@rebasepro/server` | Hono server coordinator, API generation, auth middleware, storage, email, cron, custom functions | Backend entry point — every Rebase backend imports this |
127
+ | `@rebasepro/server-postgres` | PostgreSQL bootstrapper and Drizzle ORM data driver | Backend setup when using PostgreSQL |
128
+ | `@rebasepro/server-mongo` | MongoDB bootstrapper and data driver | Backend setup when using MongoDB |
129
+ | `@rebasepro/app` | The frontend runtime: hooks, providers, context, the auth controller (`useRebaseAuthController`) and `LoginView` | Frontend — React integration, hooks, providers, auth flows |
130
+ | `@rebasepro/types` | Shared TypeScript type definitions (`PostgresCollectionConfig`, `CollectionConfig`, `RebaseClient`, etc.) | Type imports across all packages |
131
+ | `@rebasepro/ui` | Standalone component library (Tailwind CSS v4 + Radix) | Building custom views in Studio or standalone UI |
132
+ | `@rebasepro/admin` | The CMS: `RebaseAdmin`, collection views, entity forms, collection editor — built from your collection definitions | The admin panel. Needs collection files |
133
+ | `@rebasepro/studio` | The BaaS console: SQL editor, schema visualizer, RLS editor, storage browser, logs, API explorer, API keys, backups, cron | Database tooling. Ships on BaaS with no CMS — `admin` is an optional peer |
134
+ | `@rebasepro/client` | Client SDK for consuming the Rebase API | Any client-side or script-side data operations |
135
+ | `@rebasepro/firebase` | Firebase client adapter | When connecting to a Firebase backend |
136
+ | `@rebasepro/client-postgres` | PostgreSQL client adapter | When connecting directly to PostgreSQL from client |
137
+ | `@rebasepro/common` | Shared utilities, `defaultUsersCollection` | Shared constants and default collection exports |
138
+ | `@rebasepro/forms` | Form engine | Building dynamic forms from collection schemas |
139
+ | `@rebasepro/mcp` | AI agent MCP tools | The MCP server that agents use |
140
+ | `@rebasepro/codegen` | Typed SDK generation from collection definitions | Used by `rebase generate-sdk` command |
141
+ | `@rebasepro/inference` | Auto-infer schema from data / database introspection | Used by `rebase schema introspect` |
142
+ | `@rebasepro/plugin-ai` | AI-powered data autofill | Studio plugin for auto-completing fields |
143
+ | `@rebasepro/plugin-insights` | Usage and data insights views | Plugin for analytics over your collections |
144
+ | `@rebasepro/cli` | CLI tool | The `rebase` CLI binary |
145
+ | `@rebasepro/utils` | Utility functions | Low-level shared helpers |
146
+
147
+ # CLI Commands
148
+
149
+ ## Global Options
150
+
151
+ | Option | Description |
152
+ |--------|-------------|
153
+ | `--version`, `-v` | Show CLI version number |
154
+ | `--help`, `-h` | Show help message |
155
+
156
+ ## Full Command Reference
157
+
158
+ ### Project Lifecycle
159
+
160
+ | Command | Description |
161
+ |---------|-------------|
162
+ | `rebase init [name]` | Scaffold a new Rebase project interactively |
163
+ | `rebase dev` | Start development server (backend + frontend concurrently) |
164
+ | `rebase build` | Build all workspace packages for production |
165
+ | `rebase start` | Start the backend server in production mode |
166
+
167
+ ### `rebase init` Options
168
+
169
+ | Option | Alias | Description |
170
+ |--------|-------|-------------|
171
+ | `--git` | `-g` | Initialize a git repository |
172
+ | `--install` | `-i` | Install dependencies with the detected PM |
173
+ | `--database-url` | — | PostgreSQL connection string (skip prompt) |
174
+ | `--introspect` | — | Auto-introspect the database after init |
175
+ | `--yes` | `-y` | Non-interactive mode (use all defaults) |
176
+
177
+ ```bash
178
+ # Interactive mode
179
+ rebase init my-app
180
+
181
+ # Non-interactive — scaffold with a remote database and introspect it
182
+ rebase init my-app --yes --database-url "postgresql://user:pass@host:5432/db" --introspect --install
183
+ ```
184
+
185
+ ### `rebase dev` Options
186
+
187
+ | Option | Alias | Description |
188
+ |--------|-------|-------------|
189
+ | `--backend-only` | `-b` | Only start the backend server |
190
+ | `--frontend-only` | `-f` | Only start the frontend server |
191
+ | `--port` | `-p` | Set the backend port (default: deterministic per-project hash) |
192
+ | `--generate` | `-g` | Auto-regenerate schema + SDK on startup and file changes |
193
+
194
+ > **IMPORTANT FOR AGENTS:** Each project automatically receives a **unique default port** derived from its directory path (range 3001–3999), preventing collisions when running multiple Rebase instances. The resolved port is saved to `.rebase-dev-port` for affinity across restarts. The backend URL is saved to `.rebase-dev-url` so scripts can read it. The frontend receives `VITE_API_URL` automatically.
195
+
196
+ **Port resolution order:**
197
+ 1. Explicit `--port` flag (highest priority)
198
+ 2. `PORT` environment variable
199
+ 3. Previously saved port from `.rebase-dev-port` (port affinity)
200
+ 4. Deterministic hash from project path (unique per project)
201
+
202
+ **Auto-generation:** Disabled by default. Enable with `--generate` or by setting `REBASE_AUTO_GENERATE=true` / `REBASE_GENERATE=true` in your environment. When enabled, the CLI:
203
+ - Runs `schema generate` + `generate-sdk` once on startup
204
+ - Watches `config/collections/` for file changes and regenerates automatically
205
+
206
+ ```bash
207
+ # Start everything (default)
208
+ rebase dev
209
+
210
+ # Backend only on a specific port
211
+ rebase dev --backend-only --port 3005
212
+
213
+ # With auto-generation of schema/SDK on collection file changes
214
+ rebase dev --generate
215
+ ```
216
+
217
+ ### `rebase build`
218
+
219
+ Runs the build script across all workspace packages using the detected package manager (pnpm or npm). No options.
220
+
221
+ ```bash
222
+ rebase build
223
+ ```
224
+
225
+ ### `rebase start`
226
+
227
+ Starts the backend server in production mode. Automatically sets `DOTENV_CONFIG_PATH` if a `.env` file is found. No options.
228
+
229
+ ```bash
230
+ rebase start
231
+ ```
232
+
233
+ ### Schema Commands
234
+
235
+ | Command | Description |
236
+ |---------|-------------|
237
+ | `rebase schema generate` | Generate Drizzle schema from collection definitions |
238
+ | `rebase schema introspect` | Introspect a live database → generate Rebase collection files |
239
+ | `rebase schema --help` | Show schema command help |
240
+
241
+ > **IMPORTANT FOR AGENTS:** Schema commands are delegated to the active database driver plugin (e.g. `@rebasepro/server-postgres`). The plugin must be installed in `backend/package.json` or the command will fail with `Could not detect an active database plugin`.
242
+
243
+ #### `schema generate` Options
244
+
245
+ | Option | Alias | Description |
246
+ |--------|-------|-------------|
247
+ | `--collections` | `-c` | Path to collections directory |
248
+ | `--output` | `-o` | Output path for generated schema |
249
+ | `--watch` | `-w` | Watch for changes and regenerate automatically |
250
+
251
+ #### `schema introspect` Options
252
+
253
+ | Option | Alias | Description |
254
+ |--------|-------|-------------|
255
+ | `--output` | `-o` | Output directory for generated collection files |
256
+
257
+ ### Database Commands
258
+
259
+ | Command | Description |
260
+ |---------|-------------|
261
+ | `rebase db push` | Apply schema directly to database (development only) |
262
+ | `rebase db generate` | Generate SQL migration files |
263
+ | `rebase db migrate` | Run pending SQL migrations |
264
+ | `rebase db studio` | Open Drizzle Studio (visual database browser) |
265
+ | `rebase db branch` | Database branching (create, list, delete, info) |
266
+ | `rebase db --help` | Show database command help |
267
+
268
+ > **IMPORTANT FOR AGENTS:** Like schema commands, database commands are delegated to the active database driver plugin. The plugin provides the actual implementation.
269
+
270
+ ```bash
271
+ # Development workflow (fast, no migration files)
272
+ rebase schema generate && rebase db push
273
+
274
+ # Production workflow (versioned migrations)
275
+ rebase schema generate
276
+ rebase db generate
277
+ rebase db migrate
278
+
279
+ # Create a database branch
280
+ rebase db branch create feature_auth
281
+ ```
282
+
283
+ ### SDK Generation
284
+
285
+ | Command | Description |
286
+ |---------|-------------|
287
+ | `rebase generate-sdk` | Generate a typed JS/TS SDK from collection definitions |
288
+
289
+ | Option | Alias | Default | Description |
290
+ |--------|-------|---------|-------------|
291
+ | `--collections-dir` | `-c` | `./config/collections` | Path to collections directory |
292
+ | `--output` | `-o` | `./generated/sdk` | Output path for generated SDK |
293
+
294
+ The SDK generator uses `jiti` for dynamic TypeScript import of collection files. It will look for an `index.ts` barrel export in the collections directory. If no index file is found, it falls back to scanning individual `.ts`/`.js` files.
295
+
296
+ ```bash
297
+ rebase generate-sdk --collections-dir ./config/collections --output ./generated/sdk
298
+ ```
299
+
300
+ ### Auth Commands
301
+
302
+ | Command | Description |
303
+ |---------|-------------|
304
+ | `rebase auth reset-password` | Reset a user's password directly in the database |
305
+ | `rebase auth --help` | Show auth command help |
306
+
307
+ | Option | Alias | Default | Description |
308
+ |--------|-------|---------|-------------|
309
+ | `--email` | `-e` | (required — or pass as positional arg) | User's email address |
310
+ | `--password` | `-p` | `NewPassword123!` | New password |
311
+
312
+ ```bash
313
+ # With flags
314
+ rebase auth reset-password --email user@example.com --password MyNewPass!
315
+
316
+ # Positional args
317
+ rebase auth reset-password user@example.com MyNewPass!
318
+ ```
319
+
320
+ ### Diagnostics
321
+
322
+ | Command | Description |
323
+ |---------|-------------|
324
+ | `rebase doctor` | Detect three-way schema drift between collections, Drizzle schema, and live DB |
325
+
326
+ > **IMPORTANT FOR AGENTS:** `rebase doctor` compares collection definitions, the generated Drizzle schema (`schema.generated.ts`), and the actual PostgreSQL database. Run it after any manual DB changes or when suspecting schema drift.
327
+
328
+ # Environment Variables
329
+
330
+ ## `loadEnv()` Function
331
+
332
+ Rebase provides `loadEnv()` from `@rebasepro/server` to validate and load environment variables with Zod. Call it **after** your `.env` file has been loaded (e.g. via `dotenv.config()`). It does NOT load `.env` files itself.
333
+
334
+ ### Behavior
335
+
336
+ - **Auto-generates** ephemeral `JWT_SECRET` and `REBASE_SERVICE_KEY` in non-production mode so developers can start without manual setup
337
+ - **Blocks** auto-generated secrets in production (fails validation)
338
+ - Returns a fully typed, validated env object
339
+
340
+ ### Signature
341
+
342
+ ```typescript
343
+ import { loadEnv } from "@rebasepro/server";
344
+
345
+ // Basic — just Rebase env vars:
346
+ export const env = loadEnv();
347
+
348
+ // Extended — add your own typed vars:
349
+ import { z } from "zod";
350
+ export const env = loadEnv({
351
+ extend: z.object({
352
+ SMTP_HOST: z.string().optional(),
353
+ SMTP_PORT: z.string().default("587").transform(Number),
354
+ STRIPE_SECRET_KEY: z.string(),
355
+ })
356
+ });
357
+ // env.SMTP_HOST → string | undefined (fully typed)
358
+ // env.STRIPE_SECRET_KEY → string (validated, required)
359
+ ```
360
+
361
+ ### Function Overloads
362
+
363
+ ```typescript
364
+ function loadEnv(): RebaseEnv;
365
+ function loadEnv<E extends z.AnyZodObject>(options: { extend: E }): RebaseEnv & z.infer<E>;
366
+ ```
367
+
368
+ When `extend` is provided, the base `rebaseEnvSchema` is merged (`.merge()`) with your custom Zod object, so all fields are validated together in a single pass.
369
+
370
+ ### Complete Environment Variable Reference
371
+
372
+ | Variable | Type | Default | Required | Description |
373
+ |----------|------|---------|----------|-------------|
374
+ | `NODE_ENV` | `"development" \| "production" \| "test"` | `"development"` | No | Environment mode |
375
+ | `PORT` | `string` → `number` | `"3001"` | No | Server port |
376
+ | `DATABASE_URL` | `string` (URL) | — | **Yes** | PostgreSQL connection string |
377
+ | `DATABASE_DIRECT_URL` | `string` (URL) | — | No | Direct connection (bypasses pooler) |
378
+ | `DATABASE_READ_URL` | `string` (URL) | — | No | Read replica connection |
379
+ | `ADMIN_CONNECTION_STRING` | `string` (URL) | — | No | Admin-level DB connection |
380
+ | `JWT_SECRET` | `string` (≥32 chars) | Auto-generated in dev | **Yes** (prod) | JWT signing secret |
381
+ | `JWT_ACCESS_EXPIRES_IN` | `string` | `"1h"` | No | Access token TTL |
382
+ | `JWT_REFRESH_EXPIRES_IN` | `string` | `"30d"` | No | Refresh token TTL |
383
+ | `REBASE_SERVICE_KEY` | `string` | Auto-generated in dev | No | Static key for server-to-server auth |
384
+ | `GOOGLE_CLIENT_ID` | `string` | — | No | Google OAuth client ID |
385
+ | `GOOGLE_CLIENT_SECRET` | `string` | — | No | Google OAuth client secret |
386
+ | `ALLOW_REGISTRATION` | `"true" \| "false"` | `"false"` | No | Allow public user registration |
387
+ | `ALLOW_LOCALHOST_IN_PRODUCTION` | `"true" \| "false"` | — | No | Skip localhost URL checks in production |
388
+ | `CORS_ORIGINS` | `string` | — | **Yes** (prod) | Allowed CORS origins (comma-separated) |
389
+ | `FRONTEND_URL` | `string` | — | Prod alt | Alternative to CORS_ORIGINS for single frontend |
390
+ | `DB_POOL_MAX` | `string` → `number` | `"20"` | No | Max database pool connections |
391
+ | `DB_POOL_IDLE_TIMEOUT` | `string` → `number` | `"30000"` | No | Pool idle timeout (ms) |
392
+ | `DB_POOL_CONNECT_TIMEOUT` | `string` → `number` | `"10000"` | No | Pool connect timeout (ms) |
393
+ | `STORAGE_TYPE` | `"local" \| "s3" \| "gcs"` | `"local"` | No | File storage backend type |
394
+ | `STORAGE_PATH` | `string` | — | No | Local storage directory path |
395
+ | `FORCE_LOCAL_STORAGE` | `"true" \| "false"` | — | No | Force local storage even in production |
396
+ | `S3_BUCKET` | `string` | — | When S3 | S3 bucket name |
397
+ | `S3_REGION` | `string` | — | When S3 | S3 region |
398
+ | `S3_ACCESS_KEY_ID` | `string` | — | When S3 | S3 access key |
399
+ | `S3_SECRET_ACCESS_KEY` | `string` | — | When S3 | S3 secret key |
400
+ | `S3_ENDPOINT` | `string` (URL) | — | No | Custom S3 endpoint (MinIO, R2, etc.) |
401
+ | `S3_FORCE_PATH_STYLE` | `"true" \| "false"` | — | No | Use path-style S3 URLs |
402
+ | `GCS_BUCKET` | `string` | — | When GCS | GCS/Firebase Storage bucket name |
403
+ | `GCS_PROJECT_ID` | `string` | — | When GCS | GCP project ID |
404
+ | `GOOGLE_APPLICATION_CREDENTIALS` | `string` (path) | — | When GCS | Path to GCP service account JSON |
405
+
406
+ ### Production Validations
407
+
408
+ `loadEnv()` enforces these rules when `NODE_ENV=production`:
409
+
410
+ 1. `CORS_ORIGINS` or `FRONTEND_URL` **must** be set
411
+ 2. `JWT_SECRET` and `REBASE_SERVICE_KEY` **must** be explicitly set (auto-generation disabled)
412
+ 3. No environment variable may contain a localhost/loopback URL (unless `ALLOW_LOCALHOST_IN_PRODUCTION=true`)
413
+
414
+ ### Auto-Generated Dev Secrets
415
+
416
+ In non-production mode, `loadEnv()` automatically generates cryptographically secure random values for `JWT_SECRET` and `REBASE_SERVICE_KEY` using `crypto.randomBytes(48).toString("hex")` when they are not set. This means:
417
+
418
+ - **Developers can start immediately** without creating a `.env` file
419
+ - **Existing JWT tokens are invalidated on every server restart** because the secret changes
420
+ - A console warning is emitted: `⚠️ Auto-generated secrets for: JWT_SECRET, REBASE_SERVICE_KEY...`
421
+ - To persist sessions across restarts, set these values explicitly in `.env`
422
+
423
+ # Backend Configuration
424
+
425
+ ## `initializeRebaseBackend()`
426
+
427
+ The main entry point for initializing a Rebase backend server. Returns a `RebaseBackendInstance` with access to drivers, auth, storage, and lifecycle methods.
428
+
429
+ ### `RebaseBackendConfig` — Full Interface
430
+
431
+ ```typescript
432
+ import { initializeRebaseBackend, RebaseBackendConfig } from "@rebasepro/server";
433
+ ```
434
+
435
+ | Property | Type | Default | Description |
436
+ |----------|------|---------|-------------|
437
+ | `server` | `Server` (Node `http.Server`) | — | **Required.** The HTTP server instance |
438
+ | `app` | `Hono<HonoEnv>` | — | **Required.** The Hono application instance |
439
+ | `collections` | `CollectionConfig[]` | `[]` | Inline collection definitions |
440
+ | `collectionsDir` | `string` | — | Directory to auto-discover collection files (used if `collections` is empty) |
441
+ | `basePath` | `string` | `"/api"` | Base path for all API routes |
442
+ | `database` | `DatabaseAdapter` | — | Database adapter (takes precedence over `bootstrappers`) |
443
+ | `bootstrappers` | `BackendBootstrapper[]` | `[]` | Database bootstrappers. Use one per engine for multiple engines in a single instance (e.g. Postgres + MongoDB); mark one `isDefault` |
444
+ | `dataSources` | `DataSourceDefinition[]` | `[]` | Declared data sources (`key`, `engine`, `transport`). Drives capabilities and the server-vs-direct distinction. Collections on a `direct`/`custom` transport are client-only — the backend skips data routes for them. Server engines need no entry |
445
+ | `auth` | `RebaseAuthConfig \| AuthAdapter` | — | Authentication config or pluggable adapter |
446
+ | `storage` | `BackendStorageConfig \| StorageController \| Record<string, ...>` | — | File storage configuration. Supports `"local"`, `"s3"`, and `"gcs"` (GCS/Firebase Storage) backends. Use `Record<string, StorageController>` for multi-backend setups with named sources |
447
+ | `history` | `unknown` | — | Entity history/audit-log configuration |
448
+ | `defaultSecurityRules` | `SecurityRule[]` | — | Default RLS rules for collections without their own |
449
+ | `enableSwagger` | `boolean` | `true` | Enable OpenAPI spec at `/api/docs` and Swagger UI at `/api/swagger` (dev only) |
450
+ | `functionsDir` | `string` | — | Directory for auto-discovered custom function handlers |
451
+ | `cronsDir` | `string` | — | Directory for auto-discovered cron job handlers |
452
+ | `cronPersistence` | `boolean` | `true` | Persist cron job execution logs to the database |
453
+ | `maxBodySize` | `number` | `10485760` (10 MB) | Max request body size in bytes. Set `0` to disable |
454
+ | `csrf` | `{ origin: string \| string[] \| ((origin: string) => boolean) }` | — | CSRF protection (opt-in, disabled by default) |
455
+ | `hooks` | `BackendHooks` | — | Backend-level hooks for intercepting admin data at the API boundary |
456
+ | `logging` | `{ level?: "error" \| "warn" \| "info" \| "debug" }` | `"info"` | Log level configuration |
457
+
458
+ > **IMPORTANT FOR AGENTS:** `maxBodySize` applies to all API routes under `basePath`. Storage upload routes have their **own** limit derived from the storage config's `maxFileSize` property (default: 50 MB), which overrides the global limit.
459
+
460
+ ### `RebaseAuthConfig` — Authentication Options
461
+
462
+ | Property | Type | Default | Description |
463
+ |----------|------|---------|-------------|
464
+ | `collection` | `CollectionConfig` | `defaultUsersCollection` | The collection used for auth users |
465
+ | `jwtSecret` | `string` | — | JWT signing secret (≥32 chars) |
466
+ | `accessExpiresIn` | `string` | `"1h"` | Access token TTL |
467
+ | `refreshExpiresIn` | `string` | `"30d"` | Refresh token TTL |
468
+ | `requireAuth` | `boolean` | `true` | Require authentication for data routes |
469
+ | `allowRegistration` | `boolean` | `false` | Allow public user registration |
470
+ | `serviceKey` | `string` | — | Static secret for server-to-server auth (≥32 chars) |
471
+ | `defaultRole` | `string` | — | Role assigned to new users on registration |
472
+ | `email` | `EmailConfig` | — | SMTP email configuration |
473
+ | `hooks` | `AuthHooks` | — | Override auth behavior (password hashing, validation, etc.) |
474
+ | `providers` | `OAuthProvider[]` | — | Custom OAuth providers |
475
+
476
+ #### Built-in OAuth Providers
477
+
478
+ | Property | Required Fields | Description |
479
+ |----------|----------------|-------------|
480
+ | `google` | `clientId`, `clientSecret?` | Google OAuth (supports ID token without secret) |
481
+ | `github` | `clientId`, `clientSecret` | GitHub OAuth |
482
+ | `linkedin` | `clientId`, `clientSecret` | LinkedIn OAuth |
483
+ | `microsoft` | `clientId`, `clientSecret`, `tenantId?` | Microsoft/Azure AD OAuth |
484
+ | `apple` | `clientId`, `teamId`, `keyId`, `privateKey` | Apple Sign In |
485
+ | `facebook` | `clientId`, `clientSecret` | Facebook OAuth |
486
+ | `twitter` | `clientId`, `clientSecret` | Twitter/X OAuth |
487
+ | `discord` | `clientId`, `clientSecret` | Discord OAuth |
488
+ | `gitlab` | `clientId`, `clientSecret`, `baseUrl?` | GitLab OAuth (supports self-hosted) |
489
+ | `bitbucket` | `clientId`, `clientSecret` | Bitbucket OAuth |
490
+ | `slack` | `clientId`, `clientSecret` | Slack OAuth |
491
+ | `spotify` | `clientId`, `clientSecret` | Spotify OAuth |
492
+
493
+ ### `RebaseBackendInstance` — Return Value
494
+
495
+ | Property / Method | Type | Description |
496
+ |-------------------|------|-------------|
497
+ | `driver` | `DataDriver` | The default data driver |
498
+ | `driverRegistry` | `DriverRegistry` | Registry of all initialized drivers |
499
+ | `realtimeService` | `RealtimeProvider` | Default realtime provider |
500
+ | `realtimeServices` | `Record<string, RealtimeProvider>` | All realtime providers |
501
+ | `auth` | `BootstrappedAuth \| undefined` | Bootstrapped auth result |
502
+ | `storageRegistry` | `StorageRegistry \| undefined` | All storage backends |
503
+ | `storageController` | `StorageController \| undefined` | Default storage controller |
504
+ | `collectionRegistry` | `BackendCollectionRegistry` | Registry of all active collections |
505
+ | `cronScheduler` | `CronScheduler \| undefined` | The cron job scheduler (if configured) |
506
+ | `healthCheck()` | `() => Promise<HealthCheckResult>` | Deep health check (verifies DB connectivity, returns latency) |
507
+ | `shutdown(timeoutMs?)` | `(timeoutMs?: number) => Promise<void>` | Graceful shutdown (stops cron, destroys realtime, drains HTTP, default 15s timeout) |
508
+
509
+ ### Shutdown Behavior
510
+
511
+ When `shutdown()` is called, it performs these steps in order:
512
+
513
+ 1. **Stops the cron scheduler** (if configured)
514
+ 2. **Destroys realtime services** (LISTEN clients, debounce timers, subscriptions) — this happens **before** pool close to prevent timer callbacks firing against a closed pool
515
+ 3. **Closes the HTTP server** (stops accepting, drains in-flight requests)
516
+ 4. **Force-resolves** after `timeoutMs` (default 15000ms). Pass `0` to disable the force timer (useful in tests)
517
+
518
+ ### Minimal Backend Example
519
+
520
+ ```typescript
521
+ import { Hono } from "hono";
522
+ import { serve } from "@hono/node-server";
523
+ import { initializeRebaseBackend, loadEnv } from "@rebasepro/server";
524
+ import { createPostgresAdapter } from "@rebasepro/server-postgres";
525
+ import { defaultUsersCollection } from "@rebasepro/common";
526
+ import collections from "../config/collections";
527
+ import dotenv from "dotenv";
528
+
529
+ dotenv.config({ path: "../../.env" });
530
+ const env = loadEnv();
531
+
532
+ const app = new Hono();
533
+ const server = serve({ fetch: app.fetch, port: env.PORT });
534
+
535
+ await initializeRebaseBackend({
536
+ app,
537
+ server,
538
+ database: createPostgresAdapter({
539
+ connectionString: env.DATABASE_URL,
540
+ }),
541
+ collections: [...collections, defaultUsersCollection],
542
+ collectionsDir: "../config/collections",
543
+ functionsDir: "./src/functions",
544
+ cronsDir: "./src/crons",
545
+ auth: {
546
+ collection: defaultUsersCollection,
547
+ jwtSecret: env.JWT_SECRET,
548
+ serviceKey: env.REBASE_SERVICE_KEY,
549
+ allowRegistration: env.ALLOW_REGISTRATION,
550
+ google: env.GOOGLE_CLIENT_ID
551
+ ? { clientId: env.GOOGLE_CLIENT_ID }
552
+ : undefined,
553
+ },
554
+ // Single backend: { type: "local" | "s3" | "gcs" }
555
+ // Multi-backend: Record<string, StorageController> with named sources
556
+ storage: { type: env.STORAGE_TYPE },
557
+ defaultSecurityRules: [
558
+ { operation: "select", access: "public" },
559
+ { operations: ["insert", "update", "delete"], roles: ["admin"] },
560
+ ],
561
+ });
562
+
563
+ console.log(`Server running at http://localhost:${env.PORT}`);
564
+ ```
565
+
566
+ # The `rebase` Singleton
567
+
568
+ After `initializeRebaseBackend()` completes, a server-side singleton is available:
569
+
570
+ ```typescript
571
+ import { rebase } from "@rebasepro/server";
572
+ ```
573
+
574
+ > **WARNING FOR AGENTS:** The singleton is a **lazy proxy** — accessing it at module import time (top-level) will throw. Only use it inside request handlers, cron jobs, hooks, or functions that run after the server has started.
575
+
576
+ ### How It Works
577
+
578
+ The singleton is a JavaScript `Proxy` object. Any property access on `rebase.*` is intercepted:
579
+ - If the server **has** been initialized (`_initRebase()` called by `initializeRebaseBackend()`), the access is forwarded to the internal `RebaseClient` instance.
580
+ - If the server **has not** been initialized yet, a descriptive error is thrown: `"rebase.<prop>: server not initialized yet"`.
581
+ - The proxy is **read-only** — attempting to assign `rebase.anything = value` throws.
582
+
583
+ The underlying client uses an internal `app.request()` fetch (no network hop) and authenticates with the `serviceKey`, giving it **admin-level access** (bypasses RLS).
584
+
585
+ ### What It Exposes
586
+
587
+ The `rebase` singleton implements the `RebaseClient` interface:
588
+
589
+ | Property | Type | Description |
590
+ |----------|------|-------------|
591
+ | `rebase.data` | `RebaseData` | Admin-level data access (bypasses RLS). Use `rebase.data.<slug>.find()`, `.findOne()`, `.create()`, `.update()`, `.delete()` |
592
+ | `rebase.auth` | `AuthClient` | Authentication operations |
593
+ | `rebase.storage` | `StorageSource \| undefined` | File storage operations |
594
+ | `rebase.email` | `EmailService \| undefined` | Send emails via SMTP (only when email is configured) |
595
+ | `rebase.admin` | `AdminAPI \| undefined` | User management API |
596
+ | `rebase.sql` | `(query: string) => Promise<Record[]> \| undefined` | Raw SQL execution (only for SQL databases) |
597
+ | `rebase.baseUrl` | `string \| undefined` | The base HTTP URL of the backend |
598
+
599
+ ### Usage Examples
600
+
601
+ ```typescript
602
+ import { rebase } from "@rebasepro/server";
603
+
604
+ // In a cron job, custom function, or hook:
605
+
606
+ // Data operations (admin-level, no RLS)
607
+ const posts = await rebase.data.posts.find({ limit: 10 });
608
+ await rebase.data.orders.create({ status: "pending", total: 99.99 });
609
+
610
+ // Send an email
611
+ await rebase.email?.send({
612
+ to: "admin@company.com",
613
+ subject: "Daily Report",
614
+ html: "<p>Today's summary...</p>",
615
+ });
616
+
617
+ // Execute raw SQL
618
+ if (rebase.sql) {
619
+ const rows = await rebase.sql("SELECT count(*) FROM orders WHERE status = 'pending'");
620
+ }
621
+ ```
622
+
623
+ ### Testing
624
+
625
+ ```typescript
626
+ import { _setRebaseMock, _resetRebaseMock } from "@rebasepro/server";
627
+
628
+ // Only works when NODE_ENV=test
629
+ beforeEach(() => {
630
+ _setRebaseMock({
631
+ data: mockDataLayer,
632
+ email: mockEmailService,
633
+ });
634
+ });
635
+ afterEach(() => _resetRebaseMock());
636
+ ```
637
+
638
+ > **IMPORTANT FOR AGENTS:** `_setRebaseMock()` and `_resetRebaseMock()` throw if `NODE_ENV !== "test"`. This prevents accidental use in production.
639
+
640
+ # MCP Server Tools
641
+
642
+ The Rebase MCP server provides these tools for AI agents. Use the MCP tool calling convention (`call_mcp_tool` with server name `rebase`):
643
+
644
+ ### Dev Server Management
645
+
646
+ | Tool | Description | Parameters |
647
+ |------|-------------|------------|
648
+ | `rebase_dev_start` | Start the Rebase dev server (frontend + backend). Returns immediately — use `rebase_dev_logs` to check output | — |
649
+ | `rebase_dev_stop` | Stop the running Rebase dev server | — |
650
+ | `rebase_dev_logs` | Read recent output from the running dev server | `lines?: number` (default 50) |
651
+
652
+ ### Schema & Database
653
+
654
+ | Tool | Description | Parameters |
655
+ |------|-------------|------------|
656
+ | `rebase_schema_generate` | Generate Drizzle schema from collection definitions. Run after adding or modifying collection files | — |
657
+ | `rebase_schema_introspect` | Introspect the live database and generate Rebase collection definitions from existing tables | — |
658
+ | `rebase_db_push` | Apply the current Drizzle schema directly to the database (development shortcut, skips migration files) | — |
659
+ | `rebase_db_generate` | Generate SQL migration files from schema changes (compares current Drizzle schema against the last entity) | — |
660
+ | `rebase_db_migrate` | Run all pending SQL migrations against the database | — |
661
+
662
+ ### SDK
663
+
664
+ | Tool | Description | Parameters |
665
+ |------|-------------|------------|
666
+ | `rebase_generate_sdk` | Generate a fully-typed JS/TS SDK from collection definitions | — |
667
+
668
+ ### Document Operations
669
+
670
+ | Tool | Description | Parameters |
671
+ |------|-------------|------------|
672
+ | `list_documents` | List documents from a collection with optional filtering, sorting, pagination | `collection` (required), `where?: object`, `orderBy?: string`, `limit?: number` (default 25), `offset?: number` |
673
+ | `get_document` | Get a single document by ID | `collection` (required), `id` (required) |
674
+ | `create_document` | Create a new document in a collection | `collection` (required), `data` (required) |
675
+ | `update_document` | Update an existing document | `collection` (required), `id` (required), `data` (required) |
676
+ | `delete_document` | Delete a document from a collection | `collection` (required), `id` (required) |
677
+
678
+ ### User Management
679
+
680
+ | Tool | Description | Parameters |
681
+ |------|-------------|------------|
682
+ | `list_users` | List all users registered in the backend, including their roles | — |
683
+ | `create_user` | Create a new user | `email` (required), `displayName?: string`, `password?: string`, `roles?: string[]` |
684
+ | `update_user` | Update an existing user (email, display name, roles) | `userId` (required), `email?: string`, `displayName?: string`, `roles?: string[]` |
685
+ | `delete_user` | Delete a user from the backend | `userId` (required) |
686
+ | `list_roles` | List all roles defined in the backend | — |
687
+
688
+ ### Filtering with `list_documents`
689
+
690
+ The `where` parameter accepts a filter object with PostgREST-style operators:
691
+
692
+ ```json
693
+ {
694
+ "collection": "products",
695
+ "where": {
696
+ "status": "eq.active",
697
+ "price": "gte.100",
698
+ "category": "eq.electronics"
699
+ },
700
+ "orderBy": "price:desc",
701
+ "limit": 10
702
+ }
703
+ ```
704
+
705
+ # Common Issues
706
+
707
+ ### Database & Connection
708
+
709
+ - **`DATABASE_URL is not set`:** Ensure `.env` exists in the project root with `DATABASE_URL=postgresql://user:password@localhost:5432/rebase`
710
+ - **`DATABASE_URL must be a valid URL`:** The value must be a proper PostgreSQL URL including protocol (`postgresql://`). Check for missing or malformed values.
711
+ - **Connection refused on port 5432:** PostgreSQL is not running. Start it with `docker compose up -d db` or verify your local Postgres service.
712
+ - **`CORS_ORIGINS or FRONTEND_URL must be set in production`:** In `NODE_ENV=production`, set `CORS_ORIGINS=https://yourapp.com` or `FRONTEND_URL=https://yourapp.com` in `.env`.
713
+ - **Localhost URL blocked in production:** `loadEnv()` rejects localhost/loopback URLs in production. Set `ALLOW_LOCALHOST_IN_PRODUCTION=true` to override (not recommended).
714
+
715
+ ### JWT & Authentication
716
+
717
+ - **`JWT_SECRET must be at least 32 characters long`:** Generate one with `node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"` and set it in `.env`.
718
+ - **`JWT_SECRET must be explicitly set in production`:** Auto-generated dev secrets are blocked in production. Set the value explicitly in `.env`.
719
+ - **Tokens invalidated on restart:** In development, `JWT_SECRET` is auto-generated ephemerally. Set it explicitly in `.env` for persistent sessions across restarts.
720
+ - **`REBASE_SERVICE_KEY is too short`:** Must be ≥32 characters. Generate with `node -e "console.log(require('crypto').randomBytes(48).toString('base64'))"`.
721
+
722
+ ### Port Conflicts
723
+
724
+ - **Port already in use:** `rebase dev` auto-selects a unique port per project (3001–3999). If a conflict occurs, use `--port <number>` to specify an explicit port: `rebase dev --port 3010`.
725
+ - **Frontend connecting to wrong backend:** Delete `.rebase-dev-port` to reset port affinity, then restart with `rebase dev`.
726
+
727
+ ### Schema Drift
728
+
729
+ - **Schema out of sync:** Run `rebase doctor` to detect three-way drift between collections, generated Drizzle schema, and the live database.
730
+ - **`schema.generated.ts` is stale:** Run `rebase schema generate` to regenerate it from your collection definitions.
731
+ - **Migrations pending:** Run `rebase db migrate` to apply outstanding migration files.
732
+ - **Column type mismatch after manual DB edit:** Never edit the database manually. Always modify collection files → `rebase schema generate` → `rebase db push` (dev) or `rebase db generate && rebase db migrate` (prod).
733
+
734
+ ### CLI & Tooling
735
+
736
+ - **pnpm not found:** Install with `npm install -g pnpm`.
737
+ - **Node.js version mismatch:** Rebase requires Node.js v20+. Use `nvm install 20 && nvm use 20`.
738
+ - **`Could not find tsx binary`:** Install tsx in your project: `pnpm add -D tsx`.
739
+ - **`Could not detect an active database plugin`:** Ensure `@rebasepro/server-postgres` (or another driver) is listed in `backend/package.json` dependencies.
740
+ - **`No bootstrappers or database adapter provided`:** The `initializeRebaseBackend()` call is missing the `database` (or `bootstrappers`) property. See the backend configuration section above.
741
+ - **`Could not find CLI entry point for <plugin>`:** The database driver plugin's CLI script is missing or not found. Reinstall the plugin: `pnpm add @rebasepro/server-postgres`.
742
+
743
+ ### Singleton Errors
744
+
745
+ - **`rebase.<prop>: server not initialized yet`:** You are accessing the `rebase` singleton at module import time or before `initializeRebaseBackend()` has completed. Move the access inside a handler, hook, or function body.
746
+ - **`Cannot set rebase.<prop> directly`:** The singleton is read-only. You cannot assign properties to it.
747
+ - **`_setRebaseMock can only be called in a test environment`:** Set `NODE_ENV=test` before calling `_setRebaseMock()`.
748
+
749
+ ### Storage
750
+
751
+ - **`Storage backend "default" uses local filesystem in production`:** A warning is emitted when using `type: "local"` with `NODE_ENV=production`. Files will be lost on container restart. Configure S3-compatible storage or a custom `StorageController`.
752
+ - **`File too large`:** The storage upload endpoint has its own body limit (default 50 MB), separate from the global `maxBodySize` (default 10 MB). Configure `maxFileSize` in your storage config to increase it.
753
+
754
+ # References
755
+
756
+ - **Documentation:** [rebase.pro/docs](https://rebase.pro/docs)
757
+ - **GitHub:** [github.com/rebasepro/rebase](https://github.com/rebasepro/rebase)