@rebasepro/cli 0.21.0 → 0.21.1
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/bundle-deploy.d.ts +9 -0
- package/dist/commands/cloud/deploy.d.ts +33 -0
- package/dist/commands/cloud/errors.d.ts +5 -0
- package/dist/commands/cloud/rebuild-source.d.ts +110 -0
- package/dist/commands/cloud/settings.d.ts +6 -1
- package/dist/commands/upgrade.d.ts +38 -0
- package/dist/index.es.js +1605 -62
- package/dist/index.es.js.map +1 -1
- package/dist/manifest.d.ts +1 -1
- package/dist/upgrade.d.ts +145 -0
- 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/README.md
CHANGED
|
@@ -9,8 +9,8 @@ pnpm add -g @rebasepro/cli
|
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
ESM-only: `"type": "module"` with no CommonJS build, so it is loaded with
|
|
12
|
-
`import`.
|
|
13
|
-
`require(esm)
|
|
12
|
+
`import`. It needs Node `>=22.22.0` (its `engines` floor), where `require()`
|
|
13
|
+
of it resolves too: Node has supported `require(esm)` since 22.12.
|
|
14
14
|
|
|
15
15
|
The CLI is also bundled with every Rebase project as a local dependency.
|
|
16
16
|
|
|
@@ -20,19 +20,29 @@ The CLI is also bundled with every Rebase project as a local dependency.
|
|
|
20
20
|
|---------|-------------|
|
|
21
21
|
| `rebase init` | Scaffold a new Rebase project |
|
|
22
22
|
| `rebase dev` | Start the development server (backend + frontend) |
|
|
23
|
-
| `rebase build` | Build
|
|
23
|
+
| `rebase build` | Build the apps declared in `rebase.json` into a bundle |
|
|
24
|
+
| `rebase normalize-imports` | Complete compiled output's relative imports for Node ESM |
|
|
24
25
|
| `rebase start` | Start the backend server (production) |
|
|
26
|
+
| `rebase apps list` | Show the apps this repository declares |
|
|
25
27
|
| `rebase schema generate` | Generate Drizzle schema from collection definitions |
|
|
26
28
|
| `rebase schema introspect` | Introspect an existing database → Rebase collections |
|
|
29
|
+
| `rebase schema stale` | Report generated schema files the collections have moved past |
|
|
27
30
|
| `rebase db push` | Apply schema directly to database (dev). Previews the plan and refuses destructive changes (e.g. dropped columns) unless confirmed interactively or run with `--allow-destructive`. |
|
|
28
31
|
| `rebase db generate` | Generate SQL migration files |
|
|
29
32
|
| `rebase db migrate` | Run pending migrations |
|
|
33
|
+
| `rebase db pull` | Copy another database into local development |
|
|
34
|
+
| `rebase db branch` | Create, list, switch and delete database branches |
|
|
35
|
+
| `rebase db stop` | Stop the managed development database (data is kept) |
|
|
36
|
+
| `rebase db reset` | Delete the managed development database and start over |
|
|
30
37
|
| `rebase generate-sdk` | Generate a typed TypeScript SDK from collections |
|
|
31
38
|
| `rebase auth reset-password` | Reset a user's password |
|
|
39
|
+
| `rebase api-keys list \| create \| revoke` | Manage scoped service API keys |
|
|
32
40
|
| `rebase doctor` | Detect schema drift between collections, Drizzle schema, and database |
|
|
33
41
|
| `rebase status` | Show every resource this project declares and whether its variables are set |
|
|
34
42
|
| `rebase resources` | List the databases, buckets and topics this project declares |
|
|
43
|
+
| `rebase eject` | Own the server process and the image (one-way) |
|
|
35
44
|
| `rebase skills install` | Install Rebase agent skills for your AI coding assistant |
|
|
45
|
+
| `rebase telemetry` | Anonymous usage sharing (opt-in, off by default) |
|
|
36
46
|
| `rebase cloud <command>` | Manage your apps on Rebase Cloud (auth, deploy, databases, …) |
|
|
37
47
|
|
|
38
48
|
Run `rebase --help` or `rebase <command> --help` for detailed usage.
|
package/bin/rebase.js
CHANGED
|
@@ -188,7 +188,10 @@ const { entry } = await import("../dist/index.es.js");
|
|
|
188
188
|
* `utils/args.ts` marks those with `isUsageError` rather than a class, because
|
|
189
189
|
* this file imports the bundle and `instanceof` cannot reach across it.
|
|
190
190
|
*/
|
|
191
|
-
|
|
191
|
+
// After the bundle, which already imports this package, and spelled as the
|
|
192
|
+
// commands spell it: `wantsRawError` in `commands/cloud/errors.ts`.
|
|
193
|
+
const { parseEnvBoolean } = await import("@rebasepro/types");
|
|
194
|
+
const wantsStack = process.argv.includes("--debug") || parseEnvBoolean(process.env.REBASE_DEBUG) === true;
|
|
192
195
|
|
|
193
196
|
entry(process.argv).catch((error) => {
|
|
194
197
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { RebaseBundleManifest } from "@rebasepro/types";
|
|
2
|
+
import type { RebuildSource } from "./rebuild-source.js";
|
|
2
3
|
/** Read and shallow-validate a built bundle's manifest. */
|
|
3
4
|
export declare function readBundleManifest(bundleDir: string): RebaseBundleManifest;
|
|
4
5
|
/**
|
|
@@ -65,6 +66,14 @@ export declare function bundleDeployBody(input: {
|
|
|
65
66
|
* look" indistinguishable from "we looked and there was nothing".
|
|
66
67
|
*/
|
|
67
68
|
commit?: BundleCommit | null;
|
|
69
|
+
/**
|
|
70
|
+
* The source this bundle was built from, uploaded so a platform upgrade can
|
|
71
|
+
* rebuild it on a newer release. Omitted when none was uploaded — `--no-source`,
|
|
72
|
+
* a static app, or an upload that failed — never sent empty.
|
|
73
|
+
*/
|
|
74
|
+
rebuildSource?: RebuildSource | null;
|
|
75
|
+
/** `--allow-downgrade`: deploy a bundle built on an older release than the project runs. */
|
|
76
|
+
allowFrameworkDowngrade?: boolean;
|
|
68
77
|
}): Record<string, unknown>;
|
|
69
78
|
/** An app as `rebase.json` declares it, reduced to what the registry stores. */
|
|
70
79
|
export interface DeclaredApp {
|
|
@@ -187,6 +187,8 @@ export declare const DEPLOY_FLAGS: {
|
|
|
187
187
|
readonly "--bundle-dir": StringConstructor;
|
|
188
188
|
readonly "--skip-type-check": BooleanConstructor;
|
|
189
189
|
readonly "--eject": BooleanConstructor;
|
|
190
|
+
readonly "--no-source": BooleanConstructor;
|
|
191
|
+
readonly "--allow-downgrade": BooleanConstructor;
|
|
190
192
|
readonly "-m": "--message";
|
|
191
193
|
};
|
|
192
194
|
/**
|
|
@@ -222,6 +224,8 @@ export declare function resolveDeployArgs(rawArgs: string[]): {
|
|
|
222
224
|
readonly "--bundle-dir": StringConstructor;
|
|
223
225
|
readonly "--skip-type-check": BooleanConstructor;
|
|
224
226
|
readonly "--eject": BooleanConstructor;
|
|
227
|
+
readonly "--no-source": BooleanConstructor;
|
|
228
|
+
readonly "--allow-downgrade": BooleanConstructor;
|
|
225
229
|
readonly "-m": "--message";
|
|
226
230
|
} & {
|
|
227
231
|
readonly "--json": BooleanConstructor;
|
|
@@ -238,6 +242,35 @@ export declare function resolveDeployArgs(rawArgs: string[]): {
|
|
|
238
242
|
export declare function deployCommand(rawArgs: string[], projectRef: string): Promise<void>;
|
|
239
243
|
/** `--timeout <seconds>` for a deploy, or the 15-minute default. */
|
|
240
244
|
export declare function resolveDeployTimeout(value: string | undefined): number;
|
|
245
|
+
/**
|
|
246
|
+
* Whether the project's owner turned platform rebuilds off.
|
|
247
|
+
*
|
|
248
|
+
* Only an explicit `false` counts: a project row that predates the switch, or
|
|
249
|
+
* one that could not be read, is on — which is the default, and the control
|
|
250
|
+
* plane refuses an upload it should not have anyway.
|
|
251
|
+
*/
|
|
252
|
+
export declare function platformRebuildsOff(client: CloudClient, projectId: string): Promise<boolean>;
|
|
253
|
+
/** The intake code for a bundle built on an older framework release than the project runs. */
|
|
254
|
+
export declare const FRAMEWORK_DOWNGRADE = "FRAMEWORK_DOWNGRADE";
|
|
255
|
+
/**
|
|
256
|
+
* An intake refusal, which is a decision about what was deployed rather than a
|
|
257
|
+
* transport error — or undefined for anything else.
|
|
258
|
+
*
|
|
259
|
+
* It carries a stable code in `details.intakeCode` and usually a remedy in
|
|
260
|
+
* `details.hint`, and both used to be discarded: the deploy printed `Failed to
|
|
261
|
+
* trigger deployment (400): …` and threw the hint away. The managed path, where
|
|
262
|
+
* bundles are refused, never looked for either. Both paths answer through this
|
|
263
|
+
* now, in the three-argument shape `fail` takes, so `--json` carries the code
|
|
264
|
+
* and a person sees the fix.
|
|
265
|
+
*
|
|
266
|
+
* A downgrade gets one more line, because its two remedies are both in this
|
|
267
|
+
* CLI: move the project forward, or say the step back is meant.
|
|
268
|
+
*/
|
|
269
|
+
export declare function intakeRefusal(e: unknown): {
|
|
270
|
+
message: string;
|
|
271
|
+
hint: string;
|
|
272
|
+
code: string;
|
|
273
|
+
} | undefined;
|
|
241
274
|
/**
|
|
242
275
|
* Poll a deployment record and print new log output as it arrives. Returns the
|
|
243
276
|
* terminal status; a non-success still exits non-zero, as it always has.
|
|
@@ -76,5 +76,10 @@ export declare function summarizeError(error: unknown, context: string): ErrorSu
|
|
|
76
76
|
* `--debug` is already what `bin/rebase.js` prints after every failure as the
|
|
77
77
|
* thing to add, so the raw payload hangs off the flag people are told to reach
|
|
78
78
|
* for rather than off one invented here.
|
|
79
|
+
*
|
|
80
|
+
* The one reader of `REBASE_DEBUG` in the commands, spelled as the bin spells
|
|
81
|
+
* it. It used to be `=== "1"` here while the quote fallbacks in `resources.ts`
|
|
82
|
+
* tested the raw string for truthiness, so `=true` hid the body and `=0`
|
|
83
|
+
* printed the fallback.
|
|
79
84
|
*/
|
|
80
85
|
export declare function wantsRawError(argv?: readonly string[]): boolean;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import type { RebaseProjectManifest } from "@rebasepro/types";
|
|
2
|
+
/**
|
|
3
|
+
* The control plane's cap on an uploaded source archive.
|
|
4
|
+
*
|
|
5
|
+
* Keep in sync with its build-context cap (deploy/upload `MAX_BYTES` and the
|
|
6
|
+
* backend's `maxBodySize`). Checked before uploading, so an oversized archive is
|
|
7
|
+
* a message in milliseconds rather than a bare 413 after the upload.
|
|
8
|
+
*/
|
|
9
|
+
export declare const MAX_SOURCE_UPLOAD_BYTES: number;
|
|
10
|
+
/**
|
|
11
|
+
* Whether a file must never be uploaded, whatever the ignore rules said.
|
|
12
|
+
*
|
|
13
|
+
* `relativePath` is POSIX. Installed packages, git's own directory and built
|
|
14
|
+
* bundles are never source. Every `.env` and `.env.*` is excluded except the
|
|
15
|
+
* three template names, and so is direnv's `.envrc`, which is the same thing
|
|
16
|
+
* under another name.
|
|
17
|
+
*/
|
|
18
|
+
export declare function neverUploaded(relativePath: string): boolean;
|
|
19
|
+
export interface SourceListing {
|
|
20
|
+
/** The directory the archive is rooted at: the repository's top level, or the project root. */
|
|
21
|
+
root: string;
|
|
22
|
+
/** Regular files to pack, relative to `root`, POSIX, sorted. */
|
|
23
|
+
files: string[];
|
|
24
|
+
/** The project root relative to `root`, POSIX; `""` when they are the same directory. */
|
|
25
|
+
projectPath: string;
|
|
26
|
+
/** Whether git chose the files. */
|
|
27
|
+
fromGit: boolean;
|
|
28
|
+
}
|
|
29
|
+
/** `git -C <cwd> …`, returning stdout. Throws when git is missing or refuses. */
|
|
30
|
+
export type GitRunner = (cwd: string, args: string[]) => string;
|
|
31
|
+
/**
|
|
32
|
+
* The files a source upload carries, and where they are rooted.
|
|
33
|
+
*
|
|
34
|
+
* The project's repository first — or the project walked, outside git. Then
|
|
35
|
+
* every repository a local `link:`/`file:` dependency reaches outside it, until
|
|
36
|
+
* nothing new is reached, rooted together at their deepest common directory.
|
|
37
|
+
* That is dadaki's shape: its Rebase project is a repository of its own, nested
|
|
38
|
+
* inside the editor's repository (which ignores it), and its frontend links
|
|
39
|
+
* `../../packages/editor` from there. A listing of the project's repository
|
|
40
|
+
* alone rebuilt into "Rollup failed to resolve import @dadaki/editor".
|
|
41
|
+
*
|
|
42
|
+
* Paths are resolved through `realpath` first: git reports its top level with
|
|
43
|
+
* symlinks resolved (`/private/var/…` for a macOS temp directory), and a
|
|
44
|
+
* project path computed against the unresolved one would climb out of the
|
|
45
|
+
* archive with `../`.
|
|
46
|
+
*/
|
|
47
|
+
export declare function listSourceFiles(projectRoot: string, git?: GitRunner): SourceListing;
|
|
48
|
+
/**
|
|
49
|
+
* Pack a listing into a gzipped tarball at `outPath`.
|
|
50
|
+
*
|
|
51
|
+
* The list goes to tar as a NUL-separated file (`--null -T`), so a path with a
|
|
52
|
+
* space or a newline in it is one path. `--no-xattrs` and `COPYFILE_DISABLE`
|
|
53
|
+
* keep macOS's extended attributes and AppleDouble `._*` sidecars out of the
|
|
54
|
+
* archive, as `packBundle` does; GNU tar accepts both. Every path handed to tar
|
|
55
|
+
* is absolute, because GNU tar resolves a `-T` file after it has applied `-C`.
|
|
56
|
+
*/
|
|
57
|
+
export declare function packSource(listing: SourceListing, outPath: string): Promise<void>;
|
|
58
|
+
/** Upload a source archive; returns the control plane's id for it. */
|
|
59
|
+
export declare function uploadRebuildSource(url: string, token: string, projectId: string, tarPath: string): Promise<string>;
|
|
60
|
+
/**
|
|
61
|
+
* The `VITE_*` values a rebuild of this project's frontend needs.
|
|
62
|
+
*
|
|
63
|
+
* The `.env` files are never uploaded, so the values a static app is built with
|
|
64
|
+
* have to travel separately — and only the `VITE_*` ones, which Vite inlines
|
|
65
|
+
* into the client bundle and are public by construction. Nothing else is read.
|
|
66
|
+
*
|
|
67
|
+
* Read the way Vite reads them for `vite build`: `.env`, `.env.local`,
|
|
68
|
+
* `.env.production`, `.env.production.local`, later winning — from the project
|
|
69
|
+
* root, then from each static app's own `root`, which is where its Vite config
|
|
70
|
+
* usually points. `process.env` wins over every file, as it does in Vite.
|
|
71
|
+
*
|
|
72
|
+
* `VITE_API_URL` is the one exception, taken from `process.env` only.
|
|
73
|
+
* `staticBuildEnv` sets it to `process.env.VITE_API_URL ?? ""` for every
|
|
74
|
+
* static build, so a value in a `.env` file never reaches a deployed bundle —
|
|
75
|
+
* it is the `http://localhost:3001` of local development. Sending it would make
|
|
76
|
+
* the rebuild bake in exactly the address the local build refuses to.
|
|
77
|
+
*/
|
|
78
|
+
export declare function collectBuildEnv(projectRoot: string, appRoots: string[], env?: NodeJS.ProcessEnv): Record<string, string>;
|
|
79
|
+
/** The `root` of every static app a manifest declares, in declaration order. */
|
|
80
|
+
export declare function staticAppRoots(manifest: RebaseProjectManifest | undefined): string[];
|
|
81
|
+
/** What the deploy trigger carries about an uploaded source. */
|
|
82
|
+
export interface RebuildSource {
|
|
83
|
+
sourceId: string;
|
|
84
|
+
projectPath: string;
|
|
85
|
+
buildEnv: Record<string, string>;
|
|
86
|
+
}
|
|
87
|
+
/** The steps, injectable so a test can fail any one of them. */
|
|
88
|
+
export interface RebuildSourceSteps {
|
|
89
|
+
list: (projectRoot: string) => SourceListing;
|
|
90
|
+
pack: (listing: SourceListing, outPath: string) => Promise<void>;
|
|
91
|
+
upload: (url: string, token: string, projectId: string, tarPath: string) => Promise<string>;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* List, pack and upload the project's source. Never throws.
|
|
95
|
+
*
|
|
96
|
+
* Returns what the trigger should carry, or null — after a warning saying why
|
|
97
|
+
* and what it costs — when the source could not be sent. The caller deploys
|
|
98
|
+
* either way.
|
|
99
|
+
*/
|
|
100
|
+
export declare function prepareRebuildSource(opts: {
|
|
101
|
+
projectRoot: string;
|
|
102
|
+
url: string;
|
|
103
|
+
token: string;
|
|
104
|
+
projectId: string;
|
|
105
|
+
manifest?: RebaseProjectManifest;
|
|
106
|
+
progress: (line: string) => void;
|
|
107
|
+
warn: (message: string, hint?: string) => void;
|
|
108
|
+
steps?: Partial<RebuildSourceSteps>;
|
|
109
|
+
maxBytes?: number;
|
|
110
|
+
}): Promise<RebuildSource | null>;
|
|
@@ -1,16 +1,21 @@
|
|
|
1
1
|
export declare function settingsCommand(action: string | undefined, rawArgs: string[]): Promise<void>;
|
|
2
|
+
/** `on`/`off` (or `true`/`false`) as a boolean, or null for anything else. */
|
|
3
|
+
export declare function parseOnOff(value: string): boolean | null;
|
|
2
4
|
/** Build the update patch from the flags actually supplied (pure/testable). */
|
|
3
5
|
export declare function buildSettingsPatch(args: {
|
|
4
6
|
name?: string;
|
|
5
7
|
subdomain?: string;
|
|
6
8
|
repo?: string;
|
|
7
9
|
branch?: string;
|
|
8
|
-
}
|
|
10
|
+
/** Already parsed with {@link parseOnOff}. */
|
|
11
|
+
platformRebuilds?: boolean;
|
|
12
|
+
}): Record<string, string | boolean>;
|
|
9
13
|
/** What `rebase cloud settings set` parses. Its page is the group's own. */
|
|
10
14
|
export declare const SET_SETTINGS_FLAGS: {
|
|
11
15
|
readonly "--name": StringConstructor;
|
|
12
16
|
readonly "--subdomain": StringConstructor;
|
|
13
17
|
readonly "--repo": StringConstructor;
|
|
14
18
|
readonly "--branch": StringConstructor;
|
|
19
|
+
readonly "--platform-rebuilds": StringConstructor;
|
|
15
20
|
};
|
|
16
21
|
export declare function printSettingsHelp(): void;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { type ChangedPin, type OverrideFinding, type SkippedSpec, type UnreadableFile } from "../upgrade.js";
|
|
2
|
+
/** Every flag `rebase upgrade` accepts. Its help page and the docs verifier read this. */
|
|
3
|
+
export declare const UPGRADE_FLAGS: {
|
|
4
|
+
readonly "--to": StringConstructor;
|
|
5
|
+
readonly "--drop-local-overrides": BooleanConstructor;
|
|
6
|
+
readonly "--no-install": BooleanConstructor;
|
|
7
|
+
readonly "--dry-run": BooleanConstructor;
|
|
8
|
+
readonly "--json": BooleanConstructor;
|
|
9
|
+
};
|
|
10
|
+
/** What the command reports, human or `--json`. */
|
|
11
|
+
export interface UpgradeResult {
|
|
12
|
+
target: string;
|
|
13
|
+
changed: ChangedPin[];
|
|
14
|
+
skipped: SkippedSpec[];
|
|
15
|
+
overrides: OverrideFinding[];
|
|
16
|
+
unreadable: UnreadableFile[];
|
|
17
|
+
installed: boolean;
|
|
18
|
+
dryRun: boolean;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* The two things this command does outside the project's files: ask the
|
|
22
|
+
* registry what a tag points at, and install. Injectable, so a test runs the
|
|
23
|
+
* whole command without either.
|
|
24
|
+
*/
|
|
25
|
+
export interface UpgradeIo {
|
|
26
|
+
npmView: (spec: string, cwd: string) => Promise<string>;
|
|
27
|
+
/** `quietStdout`: route the installer's stdout to stderr, so `--json` keeps stdout to itself. */
|
|
28
|
+
install: (command: [string, string[]], cwd: string, quietStdout: boolean) => Promise<void>;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* The one line of a failed `npm view` worth printing.
|
|
32
|
+
*
|
|
33
|
+
* execa's own message is the command line that failed, which says nothing the
|
|
34
|
+
* reader does not know. npm's stderr says why — `404 No match found for version
|
|
35
|
+
* nosuchtag` — under an `npm error code E404` line that says less.
|
|
36
|
+
*/
|
|
37
|
+
export declare function npmFailure(err: unknown): string;
|
|
38
|
+
export declare function upgradeCommand(rawArgs: string[], io?: UpgradeIo): Promise<void>;
|