@rebasepro/cli 0.23.0 → 0.24.0
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 +19 -3
- package/bin/rebase.js +1 -1
- package/dist/{branch-pointer-dBiClJ0p.js → branch-pointer-kk9F5FBO.js} +2 -2
- package/dist/{branch-pointer-dBiClJ0p.js.map → branch-pointer-kk9F5FBO.js.map} +1 -1
- package/dist/bundle.d.ts +6 -2
- package/dist/cli.d.ts +21 -0
- package/dist/commands/__test_support__/parser-specs.d.ts +13 -0
- package/dist/commands/agent-setup.d.ts +116 -0
- package/dist/commands/api-keys.d.ts +84 -23
- package/dist/commands/apps.d.ts +17 -0
- package/dist/commands/auth.d.ts +7 -0
- package/dist/commands/build.d.ts +5 -1
- package/dist/commands/cloud/auth.d.ts +4 -3
- package/dist/commands/cloud/bundle-deploy.d.ts +45 -0
- package/dist/commands/cloud/context.d.ts +44 -5
- package/dist/commands/cloud/cron.d.ts +53 -0
- package/dist/commands/cloud/debug.d.ts +134 -0
- package/dist/commands/cloud/index.d.ts +89 -12
- package/dist/commands/cloud/token-capabilities.d.ts +76 -0
- package/dist/commands/cloud/tokens.d.ts +23 -0
- package/dist/commands/db.d.ts +15 -1
- package/dist/commands/dev.d.ts +78 -7
- package/dist/commands/doctor.d.ts +5 -0
- package/dist/commands/generate_sdk.d.ts +3 -2
- package/dist/commands/init.d.ts +57 -14
- package/dist/commands/schema.d.ts +6 -0
- package/dist/commands/skills.d.ts +109 -5
- package/dist/commands/start.d.ts +29 -0
- package/dist/{daemon-DR9Tk0La.js → daemon-C8p32i-n.js} +5 -3
- package/dist/daemon-C8p32i-n.js.map +1 -0
- package/dist/dev-db/daemon.d.ts +10 -0
- package/dist/dev-db/prepare.d.ts +10 -0
- package/dist/fold-static.d.ts +26 -3
- package/dist/index.es.js +12086 -9459
- package/dist/index.es.js.map +1 -1
- package/dist/manifest.d.ts +41 -1
- package/dist/package-manager-CXQevsE1.js +193 -0
- package/dist/package-manager-CXQevsE1.js.map +1 -0
- package/dist/{project-3WCbrrfW.js → project-DmaGLmH2.js} +4 -183
- package/dist/project-DmaGLmH2.js.map +1 -0
- package/dist/upgrade.d.ts +14 -2
- package/dist/utils/path-flags.d.ts +18 -0
- package/dist/version-DsgBmP22.js +58 -0
- package/dist/version-DsgBmP22.js.map +1 -0
- package/package.json +7 -7
- package/templates/eject/backend/src/index.ts +14 -1
- package/templates/overlays/baas/ai-instructions.md +1 -1
- package/templates/overlays/baas/config/storage.ts +5 -3
- package/templates/template/.cursorrules +1 -1
- package/templates/template/.env.example +10 -6
- package/templates/template/.github/copilot-instructions.md +1 -1
- package/templates/template/.mcp.json +2 -2
- package/templates/template/.windsurfrules +1 -1
- package/templates/template/AGENTS.md +1 -1
- package/templates/template/CLAUDE.md +1 -1
- package/templates/template/README.md +10 -11
- package/templates/template/ai-instructions.md +3 -3
- package/templates/template/backend/functions/hello.ts +8 -0
- package/templates/template/backend/package.json +1 -1
- package/templates/template/config/storage.ts +5 -3
- package/templates/template/docker-compose.yml +6 -6
- package/templates/template/gitignore +6 -1
- package/templates/template/package.json +4 -3
- package/templates/template/scripts/example.ts +4 -3
- package/dist/daemon-DR9Tk0La.js.map +0 -1
- package/dist/project-3WCbrrfW.js.map +0 -1
package/README.md
CHANGED
|
@@ -22,7 +22,7 @@ The CLI is also bundled with every Rebase project as a local dependency.
|
|
|
22
22
|
| `rebase dev` | Start the development server (backend + frontend) |
|
|
23
23
|
| `rebase build` | Build the apps declared in `rebase.json` into a bundle |
|
|
24
24
|
| `rebase normalize-imports` | Complete compiled output's relative imports for Node ESM |
|
|
25
|
-
| `rebase start` |
|
|
25
|
+
| `rebase start` | Run the built bundle, as a deployment does, in the `NODE_ENV` you set |
|
|
26
26
|
| `rebase apps list` | Show the apps this repository declares |
|
|
27
27
|
| `rebase schema generate` | Generate Drizzle schema from collection definitions |
|
|
28
28
|
| `rebase schema introspect` | Introspect an existing database → Rebase collections |
|
|
@@ -36,7 +36,7 @@ The CLI is also bundled with every Rebase project as a local dependency.
|
|
|
36
36
|
| `rebase db reset` | Delete the managed development database and start over |
|
|
37
37
|
| `rebase generate-sdk` | Generate a typed TypeScript SDK from collections |
|
|
38
38
|
| `rebase auth reset-password` | Reset a user's password |
|
|
39
|
-
| `rebase api-keys list \| create \| revoke` | Manage
|
|
39
|
+
| `rebase api-keys list \| get \| create \| revoke \| scopes` | Manage service API keys and the scopes they hold |
|
|
40
40
|
| `rebase doctor` | Detect schema drift between collections, Drizzle schema, and database |
|
|
41
41
|
| `rebase status` | Show every resource this project declares and whether its variables are set |
|
|
42
42
|
| `rebase resources` | List the databases, buckets and topics this project declares |
|
|
@@ -64,7 +64,7 @@ rebase cloud status # project status at a glance
|
|
|
64
64
|
|
|
65
65
|
| Group | Commands |
|
|
66
66
|
|-------|----------|
|
|
67
|
-
| Auth | `login`, `logout`, `whoami` |
|
|
67
|
+
| Auth | `login`, `logout`, `whoami`, `tokens list \| create \| revoke` |
|
|
68
68
|
| Link/context | `link`, `unlink`, `use [org]`, `open` |
|
|
69
69
|
| Projects | `projects list \| create \| info \| delete` |
|
|
70
70
|
| Deploy/observe | `deploy`, `logs [--runtime] [-f]`, `status`, `metrics` |
|
|
@@ -75,6 +75,22 @@ rebase cloud status # project status at a glance
|
|
|
75
75
|
Most commands act on the linked project unless you pass `--project <id>`.
|
|
76
76
|
Run `rebase cloud --help` for the full list.
|
|
77
77
|
|
|
78
|
+
### Tokens for CI and agents
|
|
79
|
+
|
|
80
|
+
A token acts as your account, narrowed to what it was created for on one project.
|
|
81
|
+
Create it from a signed-in terminal, then hand it to CI as `REBASE_TOKEN` — every
|
|
82
|
+
`rebase cloud` command uses it instead of a login, and never reads or writes the
|
|
83
|
+
stored session:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
rebase cloud tokens create --project shop --can deploy,logs --expires-in 90
|
|
87
|
+
# → export REBASE_TOKEN=rk_live_… (shown once)
|
|
88
|
+
REBASE_TOKEN=rk_live_… rebase cloud deploy --project shop
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
`--can` takes `deploy`, `logs`, `env`, `database` and `backups`. A token cannot
|
|
92
|
+
create, list or revoke tokens, and none can restore a backup.
|
|
93
|
+
|
|
78
94
|
## Quick Start
|
|
79
95
|
|
|
80
96
|
```bash
|
package/bin/rebase.js
CHANGED
|
@@ -133,7 +133,7 @@ function warnIfStale() {
|
|
|
133
133
|
: seconds >= 60 ? `${Math.round(seconds / 60)}m` : `${seconds}s`;
|
|
134
134
|
process.stderr.write(
|
|
135
135
|
`${yellow(`⚠ rebase CLI: dist/ is ${ago} older than src/ — you are running a stale build.`)}\n` +
|
|
136
|
-
|
|
136
|
+
" Rebuild with: pnpm --filter @rebasepro/cli build\n"
|
|
137
137
|
);
|
|
138
138
|
}
|
|
139
139
|
|
|
@@ -106,6 +106,6 @@ function databaseNameOf(connectionString) {
|
|
|
106
106
|
}
|
|
107
107
|
}
|
|
108
108
|
//#endregion
|
|
109
|
-
export { branch_pointer_exports as n,
|
|
109
|
+
export { readActiveBranch as i, branch_pointer_exports as n, databaseNameOf as r, branchUrl as t };
|
|
110
110
|
|
|
111
|
-
//# sourceMappingURL=branch-pointer-
|
|
111
|
+
//# sourceMappingURL=branch-pointer-kk9F5FBO.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"branch-pointer-
|
|
1
|
+
{"version":3,"file":"branch-pointer-kk9F5FBO.js","names":[],"sources":["../src/dev-db/branch-pointer.ts"],"sourcesContent":["/**\n * Which database branch this checkout is working on.\n *\n * `rebase db branch create` made a full copy of the database in about a second\n * and then stopped one step short of being a feature: there was no `switch`, no\n * `--branch` on `rebase dev`, and nothing wrote the branch anywhere a command\n * would read it. The only way to *use* a branch was to hand-edit\n * `DATABASE_URL`, and the documentation claimed otherwise — \"the CLI updates\n * your local development configuration\" — which it did not; the `.env` was\n * byte-identical afterwards.\n *\n * This is that missing step, and the shape of it is chosen to avoid three\n * things:\n *\n * 1. **It does not touch `.env`.** That file holds secrets, comments and the\n * developer's own ordering, and a command that rewrites it in place will\n * eventually lose something that was not its business. The branch is\n * recorded beside the other per-checkout state in `.rebase/`, which is\n * already gitignored — a branch is a fact about one machine, never about\n * the project.\n *\n * 2. **It stores a name, not a connection string.** The credentials stay in\n * exactly one place; the URL is derived by swapping the database name on\n * the base one at resolution time. A stored URL would be a second copy of\n * the password, and would go stale the moment `.env` changed.\n *\n * 3. **It does not outrank an explicit instruction.** `--database-url` and a\n * `DATABASE_URL` in the shell are more immediate and more specific than a\n * switch made yesterday, so they still win. The pointer sits directly above\n * the project's `.env`: it is a deliberate, persistent choice, and `.env` is\n * the project default it is meant to override. Anything less and `switch`\n * would silently do nothing on every project that sets `DATABASE_URL` —\n * which is every project not using the managed database.\n */\n\nimport fs from \"fs\";\nimport path from \"path\";\n\n/** Where the pointer lives, next to the rest of the per-checkout state. */\nexport function branchPointerPath(projectRoot: string): string {\n return path.join(projectRoot, \".rebase\", \"branch.json\");\n}\n\nexport interface ActiveBranch {\n /** The name the developer typed. */\n name: string;\n /** The PostgreSQL database that name refers to. */\n database: string;\n}\n\n/**\n * The prefix `BranchService` puts on every branch database.\n *\n * Duplicated from the driver rather than imported because the CLI must answer\n * \"which database\" without loading a database driver — `rebase dev` reads this\n * before it knows which plugin the project uses. It is covered by a test that\n * fails if the driver's prefix moves.\n */\nexport const BRANCH_DB_PREFIX = \"rb_\";\n\nexport function branchDatabaseName(name: string): string {\n return `${BRANCH_DB_PREFIX}${name}`;\n}\n\n/** Read the active branch, or null when the checkout is on the main database. */\nexport function readActiveBranch(projectRoot: string): ActiveBranch | null {\n try {\n const raw = fs.readFileSync(branchPointerPath(projectRoot), \"utf-8\");\n const parsed = JSON.parse(raw) as Partial<ActiveBranch>;\n if (typeof parsed.name !== \"string\" || typeof parsed.database !== \"string\") return null;\n if (!parsed.name || !parsed.database) return null;\n\n return { name: parsed.name, database: parsed.database };\n } catch {\n // Absent is the common case and is not an error. A corrupt file is\n // treated the same way: the answer is \"no branch\", which is the state\n // the developer can always get back to with `branch switch --off`.\n return null;\n }\n}\n\nexport function writeActiveBranch(projectRoot: string, branch: ActiveBranch): void {\n const file = branchPointerPath(projectRoot);\n fs.mkdirSync(path.dirname(file), { recursive: true });\n fs.writeFileSync(file, `${JSON.stringify(branch, null, 2)}\\n`, \"utf-8\");\n}\n\n/** Return to the main database. Absent is success — this is idempotent. */\nexport function clearActiveBranch(projectRoot: string): void {\n fs.rmSync(branchPointerPath(projectRoot), { force: true });\n}\n\n/**\n * The base connection string with its database swapped for the branch's.\n *\n * Everything else is carried across untouched — credentials, host, port, and\n * the query string, which is load-bearing here: `?sslmode=disable` is what a\n * local Docker Postgres needs, and dropping it turns a switch into a TLS error\n * that says nothing about branches.\n *\n * Returns null for a connection string that cannot be parsed, so the caller can\n * say so plainly rather than emitting a mangled URL that fails later.\n */\nexport function branchUrl(baseUrl: string, database: string): string | null {\n try {\n const url = new URL(baseUrl);\n // `pathname` keeps its leading slash; a URL with no database at all\n // still gets one, which is what connecting to a named branch means.\n url.pathname = `/${database}`;\n\n return url.toString();\n } catch {\n return null;\n }\n}\n\n/** The database name in a connection string, for reporting what you are on. */\nexport function databaseNameOf(connectionString: string): string | null {\n try {\n const name = new URL(connectionString).pathname.replace(/^\\//, \"\");\n\n return name || null;\n } catch {\n return null;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuCA,SAAgB,kBAAkB,aAA6B;CAC3D,OAAO,KAAK,KAAK,aAAa,WAAW,aAAa;AAC1D;AAmBA,SAAgB,mBAAmB,MAAsB;CACrD,OAAO,MAAsB;AACjC;;AAGA,SAAgB,iBAAiB,aAA0C;CACvE,IAAI;EACA,MAAM,MAAM,GAAG,aAAa,kBAAkB,WAAW,GAAG,OAAO;EACnE,MAAM,SAAS,KAAK,MAAM,GAAG;EAC7B,IAAI,OAAO,OAAO,SAAS,YAAY,OAAO,OAAO,aAAa,UAAU,OAAO;EACnF,IAAI,CAAC,OAAO,QAAQ,CAAC,OAAO,UAAU,OAAO;EAE7C,OAAO;GAAE,MAAM,OAAO;GAAM,UAAU,OAAO;EAAS;CAC1D,QAAQ;EAIJ,OAAO;CACX;AACJ;AAEA,SAAgB,kBAAkB,aAAqB,QAA4B;CAC/E,MAAM,OAAO,kBAAkB,WAAW;CAC1C,GAAG,UAAU,KAAK,QAAQ,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;CACpD,GAAG,cAAc,MAAM,GAAG,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,KAAK,OAAO;AAC1E;;AAGA,SAAgB,kBAAkB,aAA2B;CACzD,GAAG,OAAO,kBAAkB,WAAW,GAAG,EAAE,OAAO,KAAK,CAAC;AAC7D;;;;;;;;;;;;AAaA,SAAgB,UAAU,SAAiB,UAAiC;CACxE,IAAI;EACA,MAAM,MAAM,IAAI,IAAI,OAAO;EAG3B,IAAI,WAAW,IAAI;EAEnB,OAAO,IAAI,SAAS;CACxB,QAAQ;EACJ,OAAO;CACX;AACJ;;AAGA,SAAgB,eAAe,kBAAyC;CACpE,IAAI;EAGA,OAFa,IAAI,IAAI,gBAAgB,CAAC,CAAC,SAAS,QAAQ,OAAO,EAExD,KAAQ;CACnB,QAAQ;EACJ,OAAO;CACX;AACJ"}
|
package/dist/bundle.d.ts
CHANGED
|
@@ -404,8 +404,10 @@ export declare function foldStaticIntoBundle(options: {
|
|
|
404
404
|
assetsDir: string;
|
|
405
405
|
/** The app's name in `rebase.json`. Names its directory inside the bundle. */
|
|
406
406
|
appName: string;
|
|
407
|
-
/** Public base path this app is served under. */
|
|
407
|
+
/** Public base path this app is served under. Always a path, never a URL. */
|
|
408
408
|
path: string;
|
|
409
|
+
/** The one hostname this app answers on, when its manifest `path` names one. */
|
|
410
|
+
host?: string;
|
|
409
411
|
/** Serve `index.html` for unmatched paths under `path`. */
|
|
410
412
|
spa: boolean;
|
|
411
413
|
/** Where this app mounts the Rebase CMS, if it does. */
|
|
@@ -420,8 +422,10 @@ export declare function buildStaticBundle(options: {
|
|
|
420
422
|
assetsDir: string;
|
|
421
423
|
outDir: string;
|
|
422
424
|
runtimeRange: string;
|
|
423
|
-
/** Public base path. Default `/` — a standalone bundle owns its origin. */
|
|
425
|
+
/** Public base path. Default `/` — a standalone bundle owns its origin. Always a path. */
|
|
424
426
|
path?: string;
|
|
427
|
+
/** The one hostname this app answers on, when its manifest `path` names one. */
|
|
428
|
+
host?: string;
|
|
425
429
|
/** Serve `index.html` for unmatched paths. Default `true`. */
|
|
426
430
|
spa?: boolean;
|
|
427
431
|
/** Where this app mounts the Rebase CMS, if it does. */
|
package/dist/cli.d.ts
CHANGED
|
@@ -18,6 +18,27 @@ export declare const ROOT_FLAGS: {
|
|
|
18
18
|
readonly "-v": "--version";
|
|
19
19
|
readonly "-h": "--help";
|
|
20
20
|
};
|
|
21
|
+
/**
|
|
22
|
+
* The subcommand in the words after a command, read against the subcommands the
|
|
23
|
+
* group dispatches.
|
|
24
|
+
*
|
|
25
|
+
* The first word that is not a flag is not always the subcommand: after a flag
|
|
26
|
+
* that takes a value it is that value. `rebase db --collections ./c push` was
|
|
27
|
+
* refused as an unknown db command `./c`, `rebase api-keys --name ci create` as
|
|
28
|
+
* one called `ci`, and `rebase skills --agent claude install` as `claude` —
|
|
29
|
+
* lines every one of those commands parses happily once it is reached.
|
|
30
|
+
*
|
|
31
|
+
* Which flags take a value is not known at this level, so the vocabulary decides
|
|
32
|
+
* instead: a word the group dispatches is the subcommand; a word straight after
|
|
33
|
+
* a flag (and not glued to it with `=`) may be that flag's value and is passed
|
|
34
|
+
* over. When no word is a known subcommand, the first word is returned as
|
|
35
|
+
* before, so a typo — `rebase db psuh`, `rebase db --dry-run psuh` — still
|
|
36
|
+
* reaches the group and is refused by name. A command with no vocabulary keeps
|
|
37
|
+
* the first word.
|
|
38
|
+
*
|
|
39
|
+
* Exported for its tests.
|
|
40
|
+
*/
|
|
41
|
+
export declare function resolveSubcommand(after: readonly string[], known: readonly string[]): string | undefined;
|
|
21
42
|
/**
|
|
22
43
|
* The command and subcommand words as `cli.error` may send them: each one is a
|
|
23
44
|
* word this CLI dispatches, `"none"` when nothing was typed, or `"other"`.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface ParsedCommandSpec {
|
|
2
|
+
/** The command words, as the call names them: `"build"`, `"skills install"`. */
|
|
3
|
+
command: string;
|
|
4
|
+
/** Canonical long flags: the value is a type, not another flag's name. */
|
|
5
|
+
flags: string[];
|
|
6
|
+
/** Every spelling the parser accepts, aliases and short flags included. */
|
|
7
|
+
accepted: string[];
|
|
8
|
+
file: string;
|
|
9
|
+
}
|
|
10
|
+
/** The parser calls in one file. Throws on a call it cannot read, so a new shape fails loudly. */
|
|
11
|
+
export declare function parsedCommands(file: string): ParsedCommandSpec[];
|
|
12
|
+
/** Every parser call under `src/` that the dispatch reaches: `cli.ts` and the command modules. */
|
|
13
|
+
export declare function allParsedCommands(commandsDir: string): ParsedCommandSpec[];
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { type AgentKey, type LoadedSkill } from "./skills.js";
|
|
2
|
+
import { type PackageManager } from "../utils/package-manager.js";
|
|
3
|
+
/** The name the server is registered under, in every config. */
|
|
4
|
+
export declare const MCP_SERVER_NAME = "rebase";
|
|
5
|
+
/** The MCP server's package: a devDependency of the project, pinned with the rest. */
|
|
6
|
+
export declare const MCP_PACKAGE = "@rebasepro/mcp";
|
|
7
|
+
/** The bin {@link MCP_PACKAGE} declares. */
|
|
8
|
+
export declare const MCP_BIN = "rebase-mcp";
|
|
9
|
+
/** The command an assistant spawns, and its arguments. */
|
|
10
|
+
export interface McpLaunch {
|
|
11
|
+
command: string;
|
|
12
|
+
args: string[];
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* How an assistant starts the Rebase MCP server: the project's own copy, through
|
|
16
|
+
* the project's package manager.
|
|
17
|
+
*
|
|
18
|
+
* Not `npx -y @rebasepro/mcp`, which fetched the newest release on every first
|
|
19
|
+
* start. The server drives the project's own CLI (`pnpm exec rebase …`) and calls
|
|
20
|
+
* the project's own backend (`/api/admin/schema/plan`, …), whose versions the
|
|
21
|
+
* lockfile pins — so a server from the registry ran ahead of both, at every
|
|
22
|
+
* start, and downloaded before it could answer. `@rebasepro/mcp` is a
|
|
23
|
+
* devDependency of the scaffold, pinned to the CLI's version like every other
|
|
24
|
+
* `@rebasepro` package, and this runs that copy.
|
|
25
|
+
*
|
|
26
|
+
* `npx --no`, not `npx`: an assistant spawns the server with no TTY, and npx
|
|
27
|
+
* then assumes "yes" and installs a missing package from the registry under the
|
|
28
|
+
* name it was given. `--no` makes a missing install an error instead.
|
|
29
|
+
*/
|
|
30
|
+
export declare function mcpLaunch(pm: PackageManager): McpLaunch;
|
|
31
|
+
/** What writing one MCP config did. */
|
|
32
|
+
export type McpWriteStatus =
|
|
33
|
+
/** The file was created, or the server was added beside the ones in it. */
|
|
34
|
+
"added"
|
|
35
|
+
/** A `rebase` server was already there. It is left exactly as it was. */
|
|
36
|
+
| "present"
|
|
37
|
+
/** The file exists but is not something this can edit without losing data. */
|
|
38
|
+
| "unreadable";
|
|
39
|
+
export interface McpWriteResult {
|
|
40
|
+
/** Project-relative path of the config file. */
|
|
41
|
+
file: string;
|
|
42
|
+
status: McpWriteStatus;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The Codex block, as TOML. Appended rather than merged: there is no TOML
|
|
46
|
+
* parser here, and an append keeps every byte already in the file.
|
|
47
|
+
*/
|
|
48
|
+
export declare function renderCodexServer(projectDir: string, launch: McpLaunch): string;
|
|
49
|
+
/**
|
|
50
|
+
* Register the Rebase MCP server in the agent's project-level config, started
|
|
51
|
+
* through the project's package manager (see {@link mcpLaunch}).
|
|
52
|
+
*
|
|
53
|
+
* Returns null for an agent with no project-level config to write.
|
|
54
|
+
*/
|
|
55
|
+
export declare function writeMcpConfig(agentKey: AgentKey, projectDir: string, pm?: PackageManager): McpWriteResult | null;
|
|
56
|
+
/** What making sure the project depends on the MCP server did. */
|
|
57
|
+
export type McpDependencyStatus =
|
|
58
|
+
/** Added to `devDependencies`, at this CLI's version: an install is due. */
|
|
59
|
+
"added"
|
|
60
|
+
/** Already a dependency. Left at the version the project chose. */
|
|
61
|
+
| "present"
|
|
62
|
+
/** No `package.json`, or one that is not plain JSON: left alone. */
|
|
63
|
+
| "unreadable";
|
|
64
|
+
/**
|
|
65
|
+
* Make the project depend on {@link MCP_PACKAGE}, which the config written by
|
|
66
|
+
* {@link writeMcpConfig} runs from the project's own install.
|
|
67
|
+
*
|
|
68
|
+
* Pinned to this CLI's version, as `rebase init` pins every `@rebasepro`
|
|
69
|
+
* package; a project that already lists it keeps its own choice.
|
|
70
|
+
*/
|
|
71
|
+
export declare function ensureMcpDependency(projectDir: string): McpDependencyStatus;
|
|
72
|
+
/**
|
|
73
|
+
* Point the scaffold's `.mcp.json` at the project's package manager.
|
|
74
|
+
*
|
|
75
|
+
* The template ships the pnpm spelling (`pnpm exec rebase-mcp`); an npm project
|
|
76
|
+
* has no pnpm to run it with. Only the entry the template wrote is rewritten.
|
|
77
|
+
*/
|
|
78
|
+
export declare function retargetScaffoldMcpConfig(projectDir: string, pm: PackageManager): void;
|
|
79
|
+
/**
|
|
80
|
+
* Whether the agent's project-level config already registers the Rebase
|
|
81
|
+
* server: `null` for an agent that has no such config, `false` when the file
|
|
82
|
+
* is missing or does not name it. Reads only — for the hint `rebase skills
|
|
83
|
+
* install` prints when it was not asked to write one.
|
|
84
|
+
*/
|
|
85
|
+
export declare function mcpServerRegistered(agentKey: AgentKey, projectDir: string): boolean | null;
|
|
86
|
+
/** What `configureAgents` did for one agent. */
|
|
87
|
+
export interface AgentSetupResult {
|
|
88
|
+
agent: AgentKey;
|
|
89
|
+
/** Skills written, or null when the bundle could not be loaded. */
|
|
90
|
+
skills: number | null;
|
|
91
|
+
/** An earlier agent in the same run that already wrote the skills directory. */
|
|
92
|
+
sharedWith?: AgentKey;
|
|
93
|
+
mcp: McpWriteResult | null;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Install the skills and register the MCP server for each agent.
|
|
97
|
+
*
|
|
98
|
+
* Never throws for a missing skills bundle — the scaffold it runs inside must
|
|
99
|
+
* not fail over its assistants — and reports it as `skills: null` instead.
|
|
100
|
+
*/
|
|
101
|
+
export declare function configureAgents(agents: readonly AgentKey[], projectDir: string, load?: () => LoadedSkill[], pm?: PackageManager): {
|
|
102
|
+
results: AgentSetupResult[];
|
|
103
|
+
skillsError?: string;
|
|
104
|
+
mcpDependency?: McpDependencyStatus;
|
|
105
|
+
};
|
|
106
|
+
/** The line to print when {@link ensureMcpDependency} changed or could not change the manifest. */
|
|
107
|
+
export declare function mcpDependencyNote(status: McpDependencyStatus | undefined, pm: PackageManager): string | undefined;
|
|
108
|
+
/** One line per agent, for the scaffold's output. */
|
|
109
|
+
export declare function printAgentSetup({ results, skillsError, mcpDependency }: ReturnType<typeof configureAgents>, pm?: PackageManager): void;
|
|
110
|
+
/**
|
|
111
|
+
* Ask whether to set up AI agents, then which, pre-ticking what is installed.
|
|
112
|
+
*
|
|
113
|
+
* Interactive only; the caller has already refused a non-TTY. Returns [] when
|
|
114
|
+
* the developer says no or unticks everything.
|
|
115
|
+
*/
|
|
116
|
+
export declare function promptForAgents(home?: string): Promise<AgentKey[]>;
|
|
@@ -1,40 +1,92 @@
|
|
|
1
|
+
import { type ApiKeyMasked, type ScopeSummary } from "@rebasepro/types";
|
|
1
2
|
/** Everything the switch below dispatches, for the did-you-mean. */
|
|
2
|
-
export declare const API_KEYS_SUBCOMMANDS: readonly ["list", "create", "revoke"];
|
|
3
|
+
export declare const API_KEYS_SUBCOMMANDS: readonly ["list", "get", "create", "revoke", "scopes"];
|
|
4
|
+
/**
|
|
5
|
+
* What to print when a request fails: the server's error code and message,
|
|
6
|
+
* which is what says why — `SCOPE_EXCEEDS_CREATOR`, `INVALID_SCOPES`,
|
|
7
|
+
* `ROLE_EXCEEDS_CREATOR`, `KEY_MANAGEMENT_SCOPE` — and a hint where one helps.
|
|
8
|
+
*
|
|
9
|
+
* Exported so its tests can read the lines without a server.
|
|
10
|
+
*/
|
|
11
|
+
export declare function describeFailure(action: string, error: unknown, baseUrl: string): string[];
|
|
3
12
|
export declare function apiKeysCommand(subcommand: string | undefined, rawArgs: string[]): Promise<void>;
|
|
13
|
+
/**
|
|
14
|
+
* The lines that describe one key: what it is, what it may do and whom it
|
|
15
|
+
* runs as.
|
|
16
|
+
*
|
|
17
|
+
* A service key runs as the RLS role `service` plus its own `roles`; a
|
|
18
|
+
* personal key runs as its owner's roles as they are when it is used, so it
|
|
19
|
+
* has none of its own to show.
|
|
20
|
+
*
|
|
21
|
+
* Exported so its tests can read the lines without a server.
|
|
22
|
+
*/
|
|
23
|
+
export declare function describeKey(key: ApiKeyMasked, now?: Date): string[];
|
|
24
|
+
/** The flags `rebase api-keys list` takes: none of its own. */
|
|
25
|
+
export declare const LIST_KEYS_FLAGS: {};
|
|
26
|
+
/** The flags `rebase api-keys get` takes. */
|
|
27
|
+
export declare const GET_KEY_FLAGS: {
|
|
28
|
+
readonly "--id": StringConstructor;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Which key this invocation names, as a positional or as `--id`.
|
|
32
|
+
*
|
|
33
|
+
* Exported so its tests can drive the real parser rather than a copy of it.
|
|
34
|
+
*/
|
|
35
|
+
export declare function resolveGetKeyArgs(rawArgs: string[]): {
|
|
36
|
+
id?: string;
|
|
37
|
+
};
|
|
4
38
|
/** The flags `rebase api-keys create` takes. */
|
|
5
39
|
export declare const CREATE_KEY_FLAGS: {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
40
|
+
"--name": StringConstructor;
|
|
41
|
+
"--scopes": [StringConstructor];
|
|
42
|
+
"--full-access": BooleanConstructor;
|
|
43
|
+
"--roles": [StringConstructor];
|
|
44
|
+
"--rate-limit": NumberConstructor;
|
|
45
|
+
"--expires-in": StringConstructor;
|
|
46
|
+
"--expires-at": StringConstructor;
|
|
47
|
+
"-n": string;
|
|
13
48
|
};
|
|
49
|
+
/**
|
|
50
|
+
* Options `create` refuses by name, each with the flag that does that job.
|
|
51
|
+
*
|
|
52
|
+
* Checked before the line is parsed: the strict parser would answer them
|
|
53
|
+
* "unknown option", which does not say what to type instead.
|
|
54
|
+
*/
|
|
55
|
+
export declare const RETIRED_CREATE_OPTIONS: Readonly<Record<string, string>>;
|
|
56
|
+
/** What `rebase api-keys create` was asked to mint. */
|
|
57
|
+
export interface CreateKeyPlan {
|
|
58
|
+
name: string;
|
|
59
|
+
/** The scopes named with `--scopes`, or `"held"` for `--full-access`. */
|
|
60
|
+
scopes: string[] | "held";
|
|
61
|
+
/** RLS roles beside `service`. */
|
|
62
|
+
roles: string[];
|
|
63
|
+
rate_limit: number | null;
|
|
64
|
+
expires_at: string | null;
|
|
65
|
+
}
|
|
14
66
|
/**
|
|
15
67
|
* What this invocation asks to be created.
|
|
16
68
|
*
|
|
17
69
|
* The name may be given either way — `--name "My Key"` or as the single
|
|
18
70
|
* positional — and under the old permissive parse an undeclared flag became
|
|
19
71
|
* that positional: `rebase api-keys create --debug --full-access` created a
|
|
20
|
-
* key called `--debug` with
|
|
21
|
-
*
|
|
22
|
-
*
|
|
72
|
+
* key called `--debug` with access to everything, and `--debug` is what the
|
|
73
|
+
* CLI prints after every failure as the thing to re-run with. Strict parsing
|
|
74
|
+
* makes the flag an error instead of a name.
|
|
75
|
+
*
|
|
76
|
+
* What the key may do has to be asked for by name — `--scopes` or
|
|
77
|
+
* `--full-access` — never defaulted: a forgotten flag must not mint a key that
|
|
78
|
+
* reaches everything.
|
|
23
79
|
*
|
|
24
80
|
* Exported so its tests can drive the real parser rather than a copy of it.
|
|
25
81
|
*/
|
|
26
|
-
export declare function resolveCreateKeyArgs(rawArgs: string[]):
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
readonly "-n": "--name";
|
|
35
|
-
}>;
|
|
36
|
-
name: string;
|
|
37
|
-
};
|
|
82
|
+
export declare function resolveCreateKeyArgs(rawArgs: string[], now?: Date): CreateKeyPlan;
|
|
83
|
+
/**
|
|
84
|
+
* The scopes `--full-access` puts on a key: every one the caller holds, less
|
|
85
|
+
* key management, which no key may hold.
|
|
86
|
+
*
|
|
87
|
+
* Exported so its tests can check the subtraction without a server.
|
|
88
|
+
*/
|
|
89
|
+
export declare function grantableScopes(held: readonly string[]): string[];
|
|
38
90
|
/** The flags `rebase api-keys revoke` takes. */
|
|
39
91
|
export declare const REVOKE_KEY_FLAGS: {
|
|
40
92
|
readonly "--id": StringConstructor;
|
|
@@ -52,3 +104,12 @@ export declare const REVOKE_KEY_FLAGS: {
|
|
|
52
104
|
export declare function resolveRevokeKeyArgs(rawArgs: string[]): {
|
|
53
105
|
id?: string;
|
|
54
106
|
};
|
|
107
|
+
/** The flags `rebase api-keys scopes` takes: none of its own. */
|
|
108
|
+
export declare const SCOPES_LIST_FLAGS: {};
|
|
109
|
+
/**
|
|
110
|
+
* The scope catalogue as printed lines: one section per plane, each scope with
|
|
111
|
+
* its label and what its target names, marked when the caller holds it.
|
|
112
|
+
*
|
|
113
|
+
* Exported so its tests can read the lines without a server.
|
|
114
|
+
*/
|
|
115
|
+
export declare function describeScopes(scopes: readonly ScopeSummary[], held: readonly string[]): string[];
|
package/dist/commands/apps.d.ts
CHANGED
|
@@ -1,3 +1,20 @@
|
|
|
1
|
+
import type { RebaseAppConfig } from "@rebasepro/types";
|
|
2
|
+
import { loadManifest } from "../manifest.js";
|
|
1
3
|
/** Everything the switch below dispatches, for the did-you-mean. */
|
|
2
4
|
export declare const APPS_SUBCOMMANDS: readonly ["list", "init", "config"];
|
|
3
5
|
export declare function appsCommand(subcommand: string | undefined, rawArgs?: string[]): Promise<void>;
|
|
6
|
+
/**
|
|
7
|
+
* One app's line in `rebase apps list`.
|
|
8
|
+
*
|
|
9
|
+
* A static app shows its full address — the https URL when its `path` gives it
|
|
10
|
+
* a hostname — and the CMS as the address a browser would open. `CMS at /` on
|
|
11
|
+
* an app that lives on `admin.example.com` reads as the project's own root,
|
|
12
|
+
* which is the one place that CMS is not.
|
|
13
|
+
*/
|
|
14
|
+
export declare function describeApp(name: string, app: RebaseAppConfig): string;
|
|
15
|
+
/**
|
|
16
|
+
* Whether `rebase build` folds this static app into the backend bundle, which
|
|
17
|
+
* then serves it on the API's own origin: a managed backend, and an app with
|
|
18
|
+
* built output to fold. The same predicate the build folds by.
|
|
19
|
+
*/
|
|
20
|
+
export declare function servedByBackend(manifest: ReturnType<typeof loadManifest>["manifest"], appName: string): boolean;
|
package/dist/commands/auth.d.ts
CHANGED
|
@@ -80,6 +80,13 @@ export declare function generatePassword(): string;
|
|
|
80
80
|
* The script the direct-database fallback runs under the project's own tsx, so
|
|
81
81
|
* it resolves the project's `@rebasepro/server-postgres` and schema.
|
|
82
82
|
*
|
|
83
|
+
* It ends the account's sessions in the transaction that sets the password,
|
|
84
|
+
* as every door through the API does (`replaceUserPassword`): the refresh
|
|
85
|
+
* tokens and outstanding reset links go, and `tokens_valid_after` voids the
|
|
86
|
+
* access tokens already handed out. An operator resetting a phished account
|
|
87
|
+
* with the backend down is the case this exists for, and a reset that left the
|
|
88
|
+
* attacker's refresh token minting access tokens did not recover anything.
|
|
89
|
+
*
|
|
83
90
|
* It exits 0 only when a row was updated: a missing user and a thrown error are
|
|
84
91
|
* both exit 1. `echoPassword` prints the new password, for a generated one.
|
|
85
92
|
*
|
package/dist/commands/build.d.ts
CHANGED
|
@@ -39,7 +39,11 @@ export declare function buildCommand(rawArgs?: string[]): Promise<void>;
|
|
|
39
39
|
* with its JSON error.
|
|
40
40
|
*/
|
|
41
41
|
export declare function buildAssetApp(projectRoot: string, name: string, app: RebaseAppConfig, runtimeRange: string, outOverride?: string,
|
|
42
|
-
/**
|
|
42
|
+
/**
|
|
43
|
+
* `quietStdout`: every line, the build command's included, goes to stderr. See `toolStdio`.
|
|
44
|
+
* `builtApps`: the static apps already built in this run (see `FoldOptions.builtApps`).
|
|
45
|
+
*/
|
|
43
46
|
options?: {
|
|
44
47
|
quietStdout?: boolean;
|
|
48
|
+
builtApps?: Set<string>;
|
|
45
49
|
}): Promise<string | undefined>;
|
|
@@ -20,9 +20,10 @@ export declare const LOGIN_FLAGS: {
|
|
|
20
20
|
* neither is something this CLI can redact after the fact — the same reasoning
|
|
21
21
|
* `rls-check` states for its connection string, which carries one too.
|
|
22
22
|
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
23
|
+
* CI should not need a password at all: `rebase cloud tokens create` mints a
|
|
24
|
+
* token narrowed to one project, and `REBASE_TOKEN` hands it to every cloud
|
|
25
|
+
* command. Where a login is still wanted, `REBASE_CLOUD_PASSWORD` is how a
|
|
26
|
+
* secret store hands the password over without it appearing on a command line.
|
|
26
27
|
*/
|
|
27
28
|
export declare const PASSWORD_ENV = "REBASE_CLOUD_PASSWORD";
|
|
28
29
|
export declare const EMAIL_ENV = "REBASE_CLOUD_EMAIL";
|
|
@@ -126,3 +126,48 @@ export declare function declaredAppsFrom(manifest: {
|
|
|
126
126
|
} | null | undefined): DeclaredApp[];
|
|
127
127
|
/** Upload a bundle archive; returns the control-plane bundle id. */
|
|
128
128
|
export declare function uploadBundle(url: string, token: string, projectId: string, tarPath: string): Promise<string>;
|
|
129
|
+
/** One DNS record a hostname needs, as the control plane lists it. */
|
|
130
|
+
export interface DeployHostRecord {
|
|
131
|
+
type: string;
|
|
132
|
+
name: string;
|
|
133
|
+
values: string[];
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* A hostname an app in this deploy is declared on, as the deploy found it.
|
|
137
|
+
*
|
|
138
|
+
* The control plane registers each one on the project as it deploys — an app
|
|
139
|
+
* whose `path` is `https://admin.example.com` needs that host on the project
|
|
140
|
+
* before anything can route it — and a new one starts `pending`, because it is
|
|
141
|
+
* served only once its DNS is published and verified. `records` is what to
|
|
142
|
+
* publish, present for a pending host.
|
|
143
|
+
*/
|
|
144
|
+
export interface DeployHost {
|
|
145
|
+
host: string;
|
|
146
|
+
status: "verified" | "pending";
|
|
147
|
+
records?: DeployHostRecord[];
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* The `hosts` a deploy response carries, read defensively.
|
|
151
|
+
*
|
|
152
|
+
* `undefined` when there is no such field, which is what a control plane that
|
|
153
|
+
* predates host-routed apps answers: the caller then leaves `hosts` out of its
|
|
154
|
+
* own output rather than reporting an empty set nobody looked for. An entry
|
|
155
|
+
* with no hostname is dropped, and any status but `verified` is pending — the
|
|
156
|
+
* same rule `cloud domains` reads rows by, because an unreadable status must
|
|
157
|
+
* not print as live.
|
|
158
|
+
*/
|
|
159
|
+
export declare function deployHostsFrom(response: unknown): DeployHost[] | undefined;
|
|
160
|
+
/**
|
|
161
|
+
* What to tell somebody whose deploy declared a hostname that is not live yet.
|
|
162
|
+
*
|
|
163
|
+
* A deploy that succeeds with an app on a hostname nobody can reach reads as a
|
|
164
|
+
* broken deploy, so each pending host gets its own block: that it is registered
|
|
165
|
+
* but waiting, the records to create, and the command that finishes the job.
|
|
166
|
+
* The records come from the control plane, never composed here — A or CNAME
|
|
167
|
+
* depends on apex-vs-subdomain and on the ingress behind the project, which
|
|
168
|
+
* the CLI cannot know. Plain text: the caller colours it.
|
|
169
|
+
*/
|
|
170
|
+
export declare function pendingHostNotices(hosts: DeployHost[]): Array<{
|
|
171
|
+
headline: string;
|
|
172
|
+
details: string[];
|
|
173
|
+
}>;
|
|
@@ -59,6 +59,24 @@ export type CloudClient = ReturnType<typeof createRebaseClient>;
|
|
|
59
59
|
* by `requireClient`.
|
|
60
60
|
*/
|
|
61
61
|
export declare function createCloudClient(url: string): CloudClient;
|
|
62
|
+
/**
|
|
63
|
+
* The environment variable that authenticates the cloud family with a token
|
|
64
|
+
* instead of a `cloud login` session — for CI and agents, which have no
|
|
65
|
+
* terminal to log in at and should not hold a person's password.
|
|
66
|
+
*/
|
|
67
|
+
export declare const TOKEN_ENV = "REBASE_TOKEN";
|
|
68
|
+
/** `REBASE_TOKEN`, trimmed, or undefined when it is unset or blank. */
|
|
69
|
+
export declare function envToken(): string | undefined;
|
|
70
|
+
/**
|
|
71
|
+
* A client that sends `token` as its bearer and nothing else.
|
|
72
|
+
*
|
|
73
|
+
* No session: the token is not refreshed, and the credentials file is neither
|
|
74
|
+
* read nor written — a CI job's token must not become, or replace, the login
|
|
75
|
+
* of whoever owns the machine. A 401 is answered by {@link explainRefusedToken}
|
|
76
|
+
* rather than by the SDK's session refresh, because there is no session to
|
|
77
|
+
* refresh and "log in again" is the wrong remedy for a token.
|
|
78
|
+
*/
|
|
79
|
+
export declare function createTokenClient(url: string, token: string): CloudClient;
|
|
62
80
|
/** The half of a client that holds its session — all {@link freshAccessToken} reads. */
|
|
63
81
|
export interface SessionHolder {
|
|
64
82
|
auth: {
|
|
@@ -81,17 +99,36 @@ export interface SessionHolder {
|
|
|
81
99
|
* token read once at the start of a command that runs for longer than it
|
|
82
100
|
* lives — a deploy's build, a `db connect` left open — is refused by the time
|
|
83
101
|
* it is used, so it is read here at the moment it is sent.
|
|
102
|
+
*
|
|
103
|
+
* A client built from `REBASE_TOKEN` has no session; its token is returned
|
|
104
|
+
* as it is, since there is nothing to refresh it with.
|
|
84
105
|
*/
|
|
85
106
|
export declare function freshAccessToken(client: SessionHolder): Promise<string>;
|
|
86
107
|
/**
|
|
87
|
-
* Return an authenticated client for the resolved host
|
|
88
|
-
*
|
|
89
|
-
*
|
|
108
|
+
* Return an authenticated client for the resolved host.
|
|
109
|
+
*
|
|
110
|
+
* With `REBASE_TOKEN` set, that token is the credential for every request and
|
|
111
|
+
* the stored login is not consulted at all. Otherwise it is the `cloud login`
|
|
112
|
+
* session — see {@link requireSessionClient}.
|
|
90
113
|
*/
|
|
91
114
|
export declare function requireClient(rawArgs: string[]): Promise<{
|
|
92
115
|
client: CloudClient;
|
|
93
116
|
url: string;
|
|
94
117
|
}>;
|
|
118
|
+
/**
|
|
119
|
+
* Return a client holding the `cloud login` session for the resolved host,
|
|
120
|
+
* refreshing the access token if it is close to expiry, whether or not
|
|
121
|
+
* `REBASE_TOKEN` is set. Exits with a helpful message when there is no usable
|
|
122
|
+
* session (never logged in, or the refresh token was revoked).
|
|
123
|
+
*
|
|
124
|
+
* For the commands a token cannot run — minting and revoking tokens: a key that
|
|
125
|
+
* could mint keys could mint its own successor, so the control plane refuses
|
|
126
|
+
* every key on those routes.
|
|
127
|
+
*/
|
|
128
|
+
export declare function requireSessionClient(rawArgs: string[]): Promise<{
|
|
129
|
+
client: CloudClient;
|
|
130
|
+
url: string;
|
|
131
|
+
}>;
|
|
95
132
|
/** One place a deploy can actually land, as the control plane describes it. */
|
|
96
133
|
export interface DeployTarget {
|
|
97
134
|
clusterId?: string | null;
|
|
@@ -192,8 +229,10 @@ export declare function removeLink(cwd?: string): boolean;
|
|
|
192
229
|
* positional.
|
|
193
230
|
*
|
|
194
231
|
* Only genuinely global flags belong here. Group-specific ones (`--bucket`,
|
|
195
|
-
* `--region`, …) are declared by the handler that owns them
|
|
196
|
-
* the
|
|
232
|
+
* `--region`, …) are declared by the handler that owns them. They can still
|
|
233
|
+
* precede the action — or stand in for it, on a group with a default — so the
|
|
234
|
+
* dispatcher also declares every one that takes a value: `CLOUD_VALUE_FLAGS`
|
|
235
|
+
* in `index.ts`.
|
|
197
236
|
*
|
|
198
237
|
* `-p` is `--project` in eighteen places and `--password` in `login`. That
|
|
199
238
|
* ambiguity does not matter to the one caller that reads this spec: it resolves
|