@rebasepro/cli 0.21.0 → 0.21.1-canary.g8c5a265
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.
- package/README.md +13 -3
- package/bin/rebase.js +4 -1
- package/dist/commands/cloud/errors.d.ts +5 -0
- package/dist/index.es.js +53 -14
- package/dist/index.es.js.map +1 -1
- package/dist/manifest.d.ts +1 -1
- package/package.json +7 -7
- package/templates/overlays/baas/README.md +5 -3
- package/templates/overlays/baas/ai-instructions.md +40 -0
- package/templates/template/README.md +2 -2
- package/templates/template/ai-instructions.md +2 -2
package/dist/manifest.d.ts
CHANGED
|
@@ -41,7 +41,7 @@ export declare function validateManifest(raw: unknown): {
|
|
|
41
41
|
* else. It used to be inferred from the presence of `backend/src/index.ts`,
|
|
42
42
|
* which every scaffolded project had whether or not it wanted its own server, so
|
|
43
43
|
* projects predating the manifest silently landed on the custom runtime and paid
|
|
44
|
-
* for it
|
|
44
|
+
* for it.
|
|
45
45
|
*/
|
|
46
46
|
export declare function synthesizeManifest(projectRoot: string): RebaseProjectManifest;
|
|
47
47
|
export declare function manifestPath(projectRoot: string): string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rebasepro/cli",
|
|
3
|
-
"version": "0.21.
|
|
3
|
+
"version": "0.21.1-canary.g8c5a265",
|
|
4
4
|
"description": "Developer tools for Rebase projects",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli",
|
|
@@ -43,12 +43,12 @@
|
|
|
43
43
|
"inquirer": "14.0.2",
|
|
44
44
|
"jiti": "^2.7.0",
|
|
45
45
|
"pg": "^8.22.0",
|
|
46
|
-
"@rebasepro/agent-skills": "0.21.
|
|
47
|
-
"@rebasepro/client": "0.21.
|
|
48
|
-
"@rebasepro/codegen": "0.21.
|
|
49
|
-
"@rebasepro/server": "0.21.
|
|
50
|
-
"@rebasepro/types": "0.21.
|
|
51
|
-
"@rebasepro/server-postgres": "0.21.
|
|
46
|
+
"@rebasepro/agent-skills": "0.21.1-canary.g8c5a265",
|
|
47
|
+
"@rebasepro/client": "0.21.1-canary.g8c5a265",
|
|
48
|
+
"@rebasepro/codegen": "0.21.1-canary.g8c5a265",
|
|
49
|
+
"@rebasepro/server": "0.21.1-canary.g8c5a265",
|
|
50
|
+
"@rebasepro/types": "0.21.1-canary.g8c5a265",
|
|
51
|
+
"@rebasepro/server-postgres": "0.21.1-canary.g8c5a265"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"@types/node": "^26.1.2",
|
|
@@ -9,9 +9,11 @@ the endpoints change with it.
|
|
|
9
9
|
|
|
10
10
|
## Serving a table
|
|
11
11
|
|
|
12
|
-
A table is served once it has an authorization model: row-level security
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
A table is served once it has an authorization model: row-level security
|
|
13
|
+
enabled. Until then the server skips it — deliberately, so a new table is never
|
|
14
|
+
exposed just by existing — and logs each table it skipped and why. A table with
|
|
15
|
+
row-level security on but no policy yet is served and returns no rows (the boot
|
|
16
|
+
log names it); a policy is what opens it:
|
|
15
17
|
|
|
16
18
|
```sql
|
|
17
19
|
ALTER TABLE your_table ENABLE ROW LEVEL SECURITY;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Rebase AI Coding Rules
|
|
2
|
+
|
|
3
|
+
This is a **headless** Rebase project: a REST API, auth, storage and realtime over your PostgreSQL database, with no admin panel. There are no collection files and no generated schema — the server reads the database schema at boot and serves each table that has row-level security enabled. `README.md` shows the SQL.
|
|
4
|
+
|
|
5
|
+
`.mcp.json` in this directory wires the Rebase MCP server up already — no login, no token: it reads `.rebase/state.json` while `pnpm dev` is running. For the full skills (auth, RLS, functions, storage, deployment), run `pnpm skills:install`, or `rebase skills install --agent <claude|cursor|windsurf|gemini|codex|kiro|copilot>` to pick one.
|
|
6
|
+
|
|
7
|
+
## Commands
|
|
8
|
+
|
|
9
|
+
| Command | What it does |
|
|
10
|
+
|---|---|
|
|
11
|
+
| `pnpm dev` | The backend and the managed development database, together |
|
|
12
|
+
| `rebase db url` | Print the connection string in use — it pipes straight into `psql` |
|
|
13
|
+
| `pnpm db:migrate` | Apply the migration files in `backend/drizzle/migrations`. Needs your own PostgreSQL, not the managed development database |
|
|
14
|
+
| `pnpm schema:introspect` | Existing tables → collection definitions in `config/collections/`. That directory ends headless mode; see rule 1 |
|
|
15
|
+
| `pnpm generate:sdk` | Regenerate the typed client from `config/collections/` — so in a headless project it has nothing to read until you introspect |
|
|
16
|
+
| `pnpm build` then `pnpm start` | Build the deployable bundle, then run it |
|
|
17
|
+
| `pnpm skills:install` | Install the Rebase skills for your assistant |
|
|
18
|
+
| `pnpm example` | Run `scripts/example.ts` against the running backend — the SDK, end to end |
|
|
19
|
+
| `rebase doctor` | Checks the environment and the database connection — run this before guessing |
|
|
20
|
+
| `rebase resources --write` | After declaring a database, bucket or topic in `config/resources.ts`: regenerate `rebase.resources.json` and commit it (`pnpm build` does this too) |
|
|
21
|
+
| `pnpm deploy` | Deploys this project. Never run it; see below |
|
|
22
|
+
|
|
23
|
+
## Never
|
|
24
|
+
|
|
25
|
+
- **Never deploy.** `pnpm deploy`, `rebase cloud deploy`, `firebase deploy`, `gcloud run deploy` — print the command and let the human run it, even when the task list ends in "deploy" and the tests are green.
|
|
26
|
+
- **Never edit `.env`.** It holds generated secrets and the connection string. Add a variable by asking, and document it in `.env.example`.
|
|
27
|
+
- **Never edit `rebase.resources.json`.** It is generated from `config/resources.ts` — declare there, then `rebase resources --write`.
|
|
28
|
+
- **Never pass `--allow-destructive`** to anything pointed at a database that is not the local development one. It drops columns and tables.
|
|
29
|
+
- **Never read or write application rows with raw SQL or Drizzle from code.** The schema is SQL here; the data is not. That path skips validation, hooks and row-level security.
|
|
30
|
+
|
|
31
|
+
## Core rules
|
|
32
|
+
|
|
33
|
+
1. **The database is the schema.** Change it with SQL — `rebase db url` gives `psql` the connection string — or with migration files, then restart `pnpm dev`: the server reads the tables at boot. Do not create `config/collections/` to describe a table; a project with collection files serves those instead of reading the database, which is a different project (`README.md`, "Adding an admin UI later").
|
|
34
|
+
2. **A table is served only with row-level security enabled.** Until then the server skips it and logs why — deliberately, so a table is never exposed just by existing — and with RLS on but no policy it is served and returns no rows. The policy *is* the authorization model: write the rule that says whose row it is, using the `rebase` schema's SQL functions `uid()`, `roles()` and `jwt()`, never a policy that admits everyone just to make rows appear.
|
|
35
|
+
3. **Storage is not under row-level security.** `config/storage.ts` exports `storageAuthorize`, the whole access model for files, and a production deployment with file storage enabled refuses to boot without one. Change the rule there to match your application; do not delete it.
|
|
36
|
+
4. **Use the SDK**: server-side that is `rebase.dataAsAdmin.<table>` for work done as the service identity, or `getDriver(c)` inside a function when the read should run as the caller. The server client has no plain `data` accessor — it is omitted precisely so that the choice of identity is written down.
|
|
37
|
+
5. **Guard every custom route**: routes in `backend/functions/` are mounted **without** an auth requirement — webhook receivers need that — so each one is public until you guard it. Import `requireAuth` / `requireAdmin` from `@rebasepro/server/functions` and pass them in the route's own middleware slot (`app.post("/", requireAuth, handler)`), not via `app.use()`, which only covers routes declared below it. Reading `getUser(c)` is not a guard: an anonymous caller gets `undefined` and the handler still runs. See `backend/functions/hello.ts` for all three tiers.
|
|
38
|
+
6. **In `backend/functions/`, always import from `@rebasepro/server/functions`** — never from `@rebasepro/server`. Both work today; the subpath is the portable one, and it also gives you the typed context accessors (`getUser`, `getDriver`, `requireDriver`) instead of casting `c.get("user")`. The package root is for a server entrypoint, not for route handlers.
|
|
39
|
+
7. **Never read `process.env` at the top of a function file.** A module-scope read that comes back undefined throws at import time, and the loader reports that as a *skipped function* — the route simply 404s with no error attached to it. Read configuration inside the handler with `requireEnv(c, "NAME")`, or build a client once with `lazyResource(env => new Client(env.KEY))`.
|
|
40
|
+
8. **Work that outlives the response goes in `waitUntil(c, promise)`**, not a floating promise. A floating promise is dropped when the process shuts down mid-deploy; `waitUntil` is what a graceful shutdown waits for.
|
|
@@ -34,8 +34,8 @@ pnpm dev # or: npm run dev
|
|
|
34
34
|
```
|
|
35
35
|
|
|
36
36
|
That is the whole first run. `rebase dev` generates the Drizzle schema from
|
|
37
|
-
`config/collections`, starts the database, creates
|
|
38
|
-
|
|
37
|
+
`config/collections`, starts the database, creates a table for every collection
|
|
38
|
+
declared there, and serves the API and the admin panel.
|
|
39
39
|
|
|
40
40
|
`rebase dev` prints the two URLs it actually bound. The first account you
|
|
41
41
|
register becomes the admin. `REBASE_ADMIN_EMAIL` and `REBASE_ADMIN_PASSWORD` in
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Rebase AI Coding Rules
|
|
2
2
|
|
|
3
|
-
`.mcp.json` in this directory wires the Rebase MCP server up already — no login, no token: it reads `.rebase/state.json` while `pnpm dev` is running. For the full skills (collections, auth, RLS, deployment, the UI kit), run `pnpm skills:install`, or `rebase skills install --agent <claude|cursor|windsurf|gemini>` to pick one.
|
|
3
|
+
`.mcp.json` in this directory wires the Rebase MCP server up already — no login, no token: it reads `.rebase/state.json` while `pnpm dev` is running. For the full skills (collections, auth, RLS, deployment, the UI kit), run `pnpm skills:install`, or `rebase skills install --agent <claude|cursor|windsurf|gemini|codex|kiro|copilot>` to pick one.
|
|
4
4
|
|
|
5
5
|
## Commands
|
|
6
6
|
|
|
@@ -36,4 +36,4 @@
|
|
|
36
36
|
5. **In `backend/functions/`, always import from `@rebasepro/server/functions`** — never from `@rebasepro/server`. Both work today; the subpath is the portable one, and it also gives you the typed context accessors (`getUser`, `getDriver`, `requireDriver`) instead of casting `c.get("user")`. The package root is for a server entrypoint, not for route handlers.
|
|
37
37
|
6. **Never read `process.env` at the top of a function file.** A module-scope read that comes back undefined throws at import time, and the loader reports that as a *skipped function* — the route simply 404s with no error attached to it. Read configuration inside the handler with `requireEnv(c, "NAME")`, or build a client once with `lazyResource(env => new Client(env.KEY))`.
|
|
38
38
|
7. **Work that outlives the response goes in `waitUntil(c, promise)`**, not a floating promise. A floating promise is dropped when the process shuts down mid-deploy; `waitUntil` is what a graceful shutdown waits for.
|
|
39
|
-
8. **Build UI from the kit, never from scratch**: any custom view, home page, dashboard or entity tab must be composed from `@rebasepro/ui` components (`Card`, `Typography`, `Button`, `Chip`, `Alert`, …) and the theme's
|
|
39
|
+
8. **Build UI from the kit, never from scratch**: any custom view, home page, dashboard or entity tab must be composed from `@rebasepro/ui` components (`Card`, `Typography`, `Button`, `Chip`, `Alert`, …) and the theme's tokens. Backgrounds and borders take a surface by role — `bg-surface-frame`, `bg-surface-sheet`, `bg-surface-card`, `bg-surface-raised`, `bg-surface-field`, `bg-surface-well`, `border-hairline` — and those switch with the theme on their own, so they need no `dark:` pair; text takes `<Typography>` or `text-text-primary dark:text-text-primary-dark`. Do **not** invent a palette, a type scale, or hand-written CSS: a hardcoded colour like `#111` is invisible in one of the two themes and nothing will catch it. The roles and their reasoning are in `@rebasepro/ui/theme.css` in your `node_modules`; the live reference is `import { UIReferenceView } from "@rebasepro/app/debug"` — mount it on a route and look before building a view. See [Styling Custom UI](https://rebase.pro/docs/frontend/styling).
|