@rebasepro/cli 0.12.1-canary.gf5f1d39 → 0.13.1-canary.g06dbe5b
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/bin/rebase.js +27 -1
- package/dist/bundle.d.ts +40 -3
- package/dist/commands/api-keys.d.ts +51 -0
- package/dist/commands/auth.d.ts +62 -0
- package/dist/commands/cloud/context.d.ts +134 -7
- package/dist/commands/cloud/databases.d.ts +39 -0
- package/dist/commands/cloud/debug.d.ts +1 -0
- package/dist/commands/cloud/deploy.d.ts +64 -0
- package/dist/commands/cloud/deployments.d.ts +22 -0
- package/dist/commands/cloud/domains.d.ts +10 -0
- package/dist/commands/cloud/env.d.ts +51 -0
- package/dist/commands/cloud/extensions.d.ts +21 -0
- package/dist/commands/cloud/index.d.ts +23 -0
- package/dist/commands/cloud/orgs.d.ts +1 -0
- package/dist/commands/cloud/projects.d.ts +61 -1
- package/dist/commands/cloud/resources.d.ts +14 -0
- package/dist/commands/cloud/settings.d.ts +1 -0
- package/dist/commands/dev.d.ts +27 -0
- package/dist/commands/eject.d.ts +42 -0
- package/dist/commands/init.d.ts +67 -0
- package/dist/commands/skills.d.ts +81 -0
- package/dist/commands/telemetry.d.ts +9 -0
- package/dist/fold-static.d.ts +47 -0
- package/dist/index.es.js +2411 -481
- package/dist/index.es.js.map +1 -1
- package/dist/manifest.d.ts +16 -1
- package/dist/telemetry/consent.d.ts +38 -0
- package/dist/telemetry/identity.d.ts +69 -0
- package/dist/telemetry/index.d.ts +72 -0
- package/dist/telemetry/payload.d.ts +78 -0
- package/dist/telemetry/project.d.ts +34 -0
- package/dist/utils/args.d.ts +76 -0
- package/dist/utils/collection-drift.d.ts +27 -0
- package/dist/utils/project.d.ts +20 -0
- package/package.json +11 -11
- package/templates/eject/Dockerfile +29 -4
- package/templates/eject/backend/src/index.ts +49 -5
- package/templates/eject/docker-compose.custom.yml +13 -5
- package/templates/overlays/baas/backend/package.json +2 -2
- package/templates/overlays/baas/backend/tsconfig.json +6 -1
- package/templates/overlays/baas/package.json +1 -2
- package/templates/template/.env.example +13 -4
- package/templates/template/backend/functions/hello.ts +8 -4
- package/templates/template/backend/package.json +2 -2
- package/templates/template/backend/tsconfig.json +6 -1
- package/templates/template/config/collections/index.ts +9 -1
- package/templates/template/config/package.json +1 -0
- package/templates/template/docker-compose.yml +4 -4
- package/templates/template/frontend/package.json +3 -3
- package/templates/template/frontend/src/App.tsx +2 -1
- package/templates/template/frontend/src/main.tsx +2 -1
- package/templates/template/frontend/vite.config.ts +0 -1
- package/templates/template/package.json +1 -2
package/bin/rebase.js
CHANGED
|
@@ -88,4 +88,30 @@ if (!existsSync(distEntry)) {
|
|
|
88
88
|
|
|
89
89
|
const { entry } = await import("../dist/index.es.js");
|
|
90
90
|
|
|
91
|
-
|
|
91
|
+
/**
|
|
92
|
+
* The CLI's last line of defence.
|
|
93
|
+
*
|
|
94
|
+
* `entry()` returns a promise and nothing was awaiting it, so anything a
|
|
95
|
+
* command threw surfaced as an unhandled rejection: Node's own stack trace,
|
|
96
|
+
* rooted in `dist/index.es.js`, with the CLI's bundled line numbers and no
|
|
97
|
+
* exit code of its own. "Collections directory not found" is a sentence a
|
|
98
|
+
* developer can act on; the same sentence under ten frames of bundle internals
|
|
99
|
+
* reads as a crash in Rebase.
|
|
100
|
+
*
|
|
101
|
+
* The message is the error's own — commands that already print something
|
|
102
|
+
* friendly and exit never reach here. The stack is available behind
|
|
103
|
+
* `--debug`/`REBASE_DEBUG`, because when the message is *not* enough that is
|
|
104
|
+
* the only thing that helps.
|
|
105
|
+
*/
|
|
106
|
+
const wantsStack = process.argv.includes("--debug") || process.env.REBASE_DEBUG === "1";
|
|
107
|
+
|
|
108
|
+
entry(process.argv).catch((error) => {
|
|
109
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
110
|
+
process.stderr.write(`\x1b[31m✗ ${message}\x1b[0m\n`);
|
|
111
|
+
if (wantsStack && error instanceof Error && error.stack) {
|
|
112
|
+
process.stderr.write(`\n${error.stack}\n`);
|
|
113
|
+
} else {
|
|
114
|
+
process.stderr.write("\x1b[90m Re-run with --debug for the stack trace.\x1b[0m\n");
|
|
115
|
+
}
|
|
116
|
+
process.exit(1);
|
|
117
|
+
});
|
package/dist/bundle.d.ts
CHANGED
|
@@ -68,6 +68,41 @@ export declare function detectNativeDependencies(projectRoot: string, declared:
|
|
|
68
68
|
* own config package already travels inside the bundle.
|
|
69
69
|
*/
|
|
70
70
|
export declare function collectDeclaredDependencies(projectRoot: string): Record<string, string>;
|
|
71
|
+
/** One `@rebasepro/*` dependency as some package.json in the project declares it. */
|
|
72
|
+
export interface DeclaredFrameworkDep {
|
|
73
|
+
name: string;
|
|
74
|
+
range: string;
|
|
75
|
+
/** Project-relative package.json it was declared in. */
|
|
76
|
+
file: string;
|
|
77
|
+
}
|
|
78
|
+
export interface FrameworkDepDrift {
|
|
79
|
+
/** Declared at a version that can never reach the CLI's own. */
|
|
80
|
+
behind: DeclaredFrameworkDep[];
|
|
81
|
+
/**
|
|
82
|
+
* The distinct lower bounds found across all declared `@rebasepro/*`, when
|
|
83
|
+
* there is more than one — the project is pinning mixed-era framework
|
|
84
|
+
* packages against each other.
|
|
85
|
+
*/
|
|
86
|
+
disagreeing: string[];
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Find `@rebasepro/*` dependencies pinned to a version older than this CLI.
|
|
90
|
+
*
|
|
91
|
+
* This is the only place a developer can be told. In development, every
|
|
92
|
+
* `@rebasepro/*` resolves through pnpm's `link:`/`workspace:` overrides to the
|
|
93
|
+
* checkout, so the version STRINGS in package.json are never exercised — the
|
|
94
|
+
* project runs fine locally on whatever is on disk, and the declared numbers are
|
|
95
|
+
* first honoured when the runtime npm-installs them from a bundle in the cloud.
|
|
96
|
+
* A project scaffolded at 0.10.0 therefore keeps working on a developer's
|
|
97
|
+
* machine indefinitely while being, in the cloud, a 0.10.0 driver.
|
|
98
|
+
*
|
|
99
|
+
* That matters because the image supplies only `@rebasepro/server`; the database
|
|
100
|
+
* driver comes from these declarations and a newer runtime never updates it.
|
|
101
|
+
* Every package.json is scanned, `dependencies` and `devDependencies` both,
|
|
102
|
+
* because they have to be bumped together and the one that gets forgotten is the
|
|
103
|
+
* one nobody looks at.
|
|
104
|
+
*/
|
|
105
|
+
export declare function detectFrameworkDepDrift(projectRoot: string, cliVersion: string): FrameworkDepDrift;
|
|
71
106
|
/**
|
|
72
107
|
* Rewrite relative import specifiers in emitted JavaScript so Node can resolve them.
|
|
73
108
|
*
|
|
@@ -101,10 +136,11 @@ export declare function normalizeEsmSpecifiers(outDir: string): {
|
|
|
101
136
|
* deployed green, and answered 404 on every one of them, with the file still
|
|
102
137
|
* sitting in the repository looking exactly like the server.
|
|
103
138
|
*
|
|
104
|
-
* A project that means to
|
|
105
|
-
* writes
|
|
139
|
+
* A project that means to own its server process runs `rebase eject`, which
|
|
140
|
+
* writes an entrypoint, a Dockerfile and a compose file together and flips the
|
|
106
141
|
* backend to `runtime: "custom"`. The warning names that route rather than
|
|
107
|
-
* implying the file is a mistake
|
|
142
|
+
* implying the file is a mistake — but eject writes *its* entrypoint, so the
|
|
143
|
+
* warning must not read as "eject will keep what you wrote here".
|
|
108
144
|
*/
|
|
109
145
|
export declare function findUnusedServerEntry(projectRoot: string, functionsDir: string): string | undefined;
|
|
110
146
|
/**
|
|
@@ -182,3 +218,4 @@ export declare function buildStaticBundle(options: {
|
|
|
182
218
|
manifest: RebaseBundleManifest;
|
|
183
219
|
fileCount: number;
|
|
184
220
|
};
|
|
221
|
+
export declare function resolveCliVersion(): string;
|
|
@@ -1 +1,52 @@
|
|
|
1
1
|
export declare function apiKeysCommand(subcommand: string | undefined, rawArgs: string[]): Promise<void>;
|
|
2
|
+
/** The flags `rebase api-keys create` takes. */
|
|
3
|
+
export declare const CREATE_KEY_FLAGS: {
|
|
4
|
+
readonly "--name": StringConstructor;
|
|
5
|
+
readonly "--permissions": StringConstructor;
|
|
6
|
+
readonly "--full-access": BooleanConstructor;
|
|
7
|
+
readonly "--admin": BooleanConstructor;
|
|
8
|
+
readonly "--rate-limit": NumberConstructor;
|
|
9
|
+
readonly "--expires": StringConstructor;
|
|
10
|
+
readonly "-n": "--name";
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* What this invocation asks to be created.
|
|
14
|
+
*
|
|
15
|
+
* The name may be given either way — `--name "My Key"` or as the single
|
|
16
|
+
* positional — and under the old permissive parse an undeclared flag became
|
|
17
|
+
* that positional: `rebase api-keys create --debug --full-access` created a
|
|
18
|
+
* key called `--debug` with read/write/delete on every collection, and
|
|
19
|
+
* `--debug` is what the CLI prints after every failure as the thing to re-run
|
|
20
|
+
* with. Strict parsing makes the flag an error instead of a name.
|
|
21
|
+
*
|
|
22
|
+
* Exported so its tests can drive the real parser rather than a copy of it.
|
|
23
|
+
*/
|
|
24
|
+
export declare function resolveCreateKeyArgs(rawArgs: string[]): {
|
|
25
|
+
flags: import("arg").Result<{
|
|
26
|
+
readonly "--name": StringConstructor;
|
|
27
|
+
readonly "--permissions": StringConstructor;
|
|
28
|
+
readonly "--full-access": BooleanConstructor;
|
|
29
|
+
readonly "--admin": BooleanConstructor;
|
|
30
|
+
readonly "--rate-limit": NumberConstructor;
|
|
31
|
+
readonly "--expires": StringConstructor;
|
|
32
|
+
readonly "-n": "--name";
|
|
33
|
+
}>;
|
|
34
|
+
name: string;
|
|
35
|
+
};
|
|
36
|
+
/** The flags `rebase api-keys revoke` takes. */
|
|
37
|
+
export declare const REVOKE_KEY_FLAGS: {
|
|
38
|
+
readonly "--id": StringConstructor;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Which key this invocation names.
|
|
42
|
+
*
|
|
43
|
+
* The id is a positional, so the permissive parse handed one straight to the
|
|
44
|
+
* DELETE: `rebase api-keys revoke --foo` sent
|
|
45
|
+
* `DELETE /api/admin/api-keys/--foo`, and `rebase --debug api-keys revoke <id>`
|
|
46
|
+
* shifted the words along and revoked the key named `revoke`.
|
|
47
|
+
*
|
|
48
|
+
* Exported so its tests can drive the real parser rather than a copy of it.
|
|
49
|
+
*/
|
|
50
|
+
export declare function resolveRevokeKeyArgs(rawArgs: string[]): {
|
|
51
|
+
id?: string;
|
|
52
|
+
};
|
package/dist/commands/auth.d.ts
CHANGED
|
@@ -1 +1,63 @@
|
|
|
1
|
+
/** A user as the admin API returns it, reduced to what this command needs. */
|
|
2
|
+
export interface ResolvedUser {
|
|
3
|
+
id: string;
|
|
4
|
+
email: string;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Pick the user with exactly this email out of a search response.
|
|
8
|
+
*
|
|
9
|
+
* `/api/admin/users?search=` is an `ILIKE '%…%'` over email **or display
|
|
10
|
+
* name**, ordered by role count descending. This used to take row `[0]` and
|
|
11
|
+
* reset it, then print the email it had been *given* as confirmation — so two
|
|
12
|
+
* ordinary situations ended in a successful-looking reset of somebody else's
|
|
13
|
+
* account:
|
|
14
|
+
*
|
|
15
|
+
* - a substring collision: `bob@example.com` also matches
|
|
16
|
+
* `robert.bob@example.com`;
|
|
17
|
+
* - a display name, which is user-controlled and accepted up to 255
|
|
18
|
+
* characters with no constraint on its content, containing an address
|
|
19
|
+
* belonging to someone else.
|
|
20
|
+
*
|
|
21
|
+
* The ordering makes it worse rather than better — `array_length(roles) DESC
|
|
22
|
+
* NULLS LAST` puts the most privileged match first, so the account most likely
|
|
23
|
+
* to be reset by mistake is an admin's.
|
|
24
|
+
*
|
|
25
|
+
* Returns `undefined` when nothing matched exactly, which the caller reports
|
|
26
|
+
* rather than falling through to a guess. The direct-database fallback below
|
|
27
|
+
* has always matched with `eq(usersTable.email, email)`; this is the same
|
|
28
|
+
* definition, so the command no longer resets different accounts depending on
|
|
29
|
+
* whether the backend happened to be running.
|
|
30
|
+
*/
|
|
31
|
+
export declare function selectUserForEmail(payload: unknown, email: string): ResolvedUser | undefined;
|
|
1
32
|
export declare function authCommand(subcommand: string | undefined, rawArgs: string[]): Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* The flags `rebase auth reset-password` takes.
|
|
35
|
+
*
|
|
36
|
+
* `-p` was advertised in this command's own help and never declared here, so
|
|
37
|
+
* `arg` — running permissively — pushed it into the positionals and the value
|
|
38
|
+
* *after* it shifted out of reach: anyone following the help set the account's
|
|
39
|
+
* password to the two-character string `-p`. Declared now, and `auth.test.ts`
|
|
40
|
+
* asserts that the help and this spec list the same aliases.
|
|
41
|
+
*/
|
|
42
|
+
export declare const RESET_PASSWORD_FLAGS: {
|
|
43
|
+
readonly "--email": StringConstructor;
|
|
44
|
+
readonly "--password": StringConstructor;
|
|
45
|
+
readonly "-e": "--email";
|
|
46
|
+
readonly "-p": "--password";
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Which account, and which password, this invocation names.
|
|
50
|
+
*
|
|
51
|
+
* Both may still be absent — the caller reports a missing email — but neither
|
|
52
|
+
* can be a flag. `parseCommandArgs` parses the whole line strictly, so an
|
|
53
|
+
* undeclared flag is an error rather than a positional. That is what stops
|
|
54
|
+
* `rebase auth reset-password bob@example.com --debug` from setting Bob's
|
|
55
|
+
* password to `--debug`, which is the flag the CLI itself prints after every
|
|
56
|
+
* failure as the thing to re-run with.
|
|
57
|
+
*
|
|
58
|
+
* Exported so its tests can drive the real parser rather than a copy of it.
|
|
59
|
+
*/
|
|
60
|
+
export declare function resolveResetPasswordArgs(rawArgs: string[]): {
|
|
61
|
+
email?: string;
|
|
62
|
+
password?: string;
|
|
63
|
+
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import arg from "arg";
|
|
1
2
|
import { createRebaseClient } from "@rebasepro/client";
|
|
2
3
|
/** Project-local link file: <project>/.rebase/cloud.json */
|
|
3
4
|
export declare function projectLinkPath(cwd?: string): string;
|
|
@@ -24,7 +25,32 @@ export declare function requireClient(rawArgs: string[]): Promise<{
|
|
|
24
25
|
client: CloudClient;
|
|
25
26
|
url: string;
|
|
26
27
|
}>;
|
|
28
|
+
/** One place a deploy can actually land, as the control plane describes it. */
|
|
29
|
+
export interface DeployTarget {
|
|
30
|
+
clusterId?: string | null;
|
|
31
|
+
provider: string;
|
|
32
|
+
region?: string;
|
|
33
|
+
label?: string;
|
|
34
|
+
baseDomain?: string;
|
|
35
|
+
}
|
|
36
|
+
export interface PlatformConfig {
|
|
37
|
+
tenantBaseDomain?: string;
|
|
38
|
+
deployTargets?: DeployTarget[];
|
|
39
|
+
}
|
|
40
|
+
export declare function fetchPlatformConfig(client: CloudClient, url: string): Promise<PlatformConfig | undefined>;
|
|
41
|
+
/**
|
|
42
|
+
* The base domain tenant projects are served at, derived from the same
|
|
43
|
+
* TENANT_BASE_DOMAIN the ingress and the console read (see
|
|
44
|
+
* saas/backend/src/utils/tenant-domain.ts).
|
|
45
|
+
*/
|
|
27
46
|
export declare function fetchTenantBaseDomain(client: CloudClient, url: string): Promise<string | undefined>;
|
|
47
|
+
/**
|
|
48
|
+
* The infrastructure a deploy for this control plane would ACTUALLY use, in the
|
|
49
|
+
* resolver's own preference order (saas/backend/src/k8s/resolve.ts).
|
|
50
|
+
*
|
|
51
|
+
* @returns the targets, or `undefined` when the control plane cannot say.
|
|
52
|
+
*/
|
|
53
|
+
export declare function fetchDeployTargets(client: CloudClient, url: string): Promise<DeployTarget[] | undefined>;
|
|
28
54
|
/**
|
|
29
55
|
* Public host for a project — `<subdomain>.<base>`, or the bare subdomain when
|
|
30
56
|
* the base domain is unknown.
|
|
@@ -84,6 +110,39 @@ export interface ProjectLink {
|
|
|
84
110
|
export declare function readLink(cwd?: string): ProjectLink | null;
|
|
85
111
|
export declare function writeLink(link: ProjectLink, cwd?: string): void;
|
|
86
112
|
export declare function removeLink(cwd?: string): boolean;
|
|
113
|
+
/**
|
|
114
|
+
* Flags that may appear anywhere on a `rebase cloud` line, including *before*
|
|
115
|
+
* the resource group.
|
|
116
|
+
*
|
|
117
|
+
* They have to be declared wherever positionals are resolved, because `arg`'s
|
|
118
|
+
* `permissive: true` does not merely tolerate an undeclared flag — it pushes it
|
|
119
|
+
* into `_` alongside the positionals, and for a flag that takes a value it
|
|
120
|
+
* pushes the value in too. So `cloud --project acme storage create` parsed
|
|
121
|
+
* without this spec yields `_` of `["--project", "acme", "storage", "create"]`,
|
|
122
|
+
* and the group reads as `"acme"`: a real project name, in the group position,
|
|
123
|
+
* dispatching to nothing. Skipping tokens that start with `-` does not save you
|
|
124
|
+
* there — the damage is the orphaned value, which looks exactly like a
|
|
125
|
+
* positional.
|
|
126
|
+
*
|
|
127
|
+
* Only genuinely global flags belong here. Group-specific ones (`--bucket`,
|
|
128
|
+
* `--region`, …) are declared by the handler that owns them and always follow
|
|
129
|
+
* the group, so they cannot shift the group or action.
|
|
130
|
+
*
|
|
131
|
+
* `-p` is `--project` in eighteen places and `--password` in `login`. That
|
|
132
|
+
* ambiguity does not matter to the one caller that reads this spec: it resolves
|
|
133
|
+
* positionals and never looks at a flag's value, so all it needs to know is
|
|
134
|
+
* that `-p` takes one. Anything that wants the value must keep declaring it
|
|
135
|
+
* itself, with the meaning its own command gives it.
|
|
136
|
+
*/
|
|
137
|
+
export declare const GLOBAL_CLOUD_FLAGS: {
|
|
138
|
+
readonly "--json": BooleanConstructor;
|
|
139
|
+
readonly "--yes": BooleanConstructor;
|
|
140
|
+
readonly "--help": BooleanConstructor;
|
|
141
|
+
readonly "--project": StringConstructor;
|
|
142
|
+
readonly "-p": "--project";
|
|
143
|
+
readonly "-y": "--yes";
|
|
144
|
+
readonly "-h": "--help";
|
|
145
|
+
};
|
|
87
146
|
/**
|
|
88
147
|
* The raw project reference to operate on: explicit `--project` flag wins,
|
|
89
148
|
* otherwise the linked project. Exits with guidance when neither is present.
|
|
@@ -134,6 +193,26 @@ export declare function printJson(value: unknown): void;
|
|
|
134
193
|
* call is what guarantees a command can never print a table AND a JSON blob.
|
|
135
194
|
*/
|
|
136
195
|
export declare function emit(human: () => void, json: unknown): void;
|
|
196
|
+
/**
|
|
197
|
+
* Print a warning (+ optional hint) — in every output mode, always to stderr.
|
|
198
|
+
*
|
|
199
|
+
* `emit` is for a command's *result*, and JSON mode legitimately replaces the
|
|
200
|
+
* human rendering of one. A warning is not a result: it says the command is
|
|
201
|
+
* about to do something the caller may not have meant, and that is exactly as
|
|
202
|
+
* true when the output is piped. Gating one on `!isJsonMode()` deleted it
|
|
203
|
+
* precisely where nobody was watching the terminal — a `--source` deploy ejected
|
|
204
|
+
* a live project off the managed runtime and said so only to a TTY that wasn't
|
|
205
|
+
* there.
|
|
206
|
+
*
|
|
207
|
+
* stdout carries the JSON value and nothing else, so warnings go to stderr:
|
|
208
|
+
* a machine parser reading stdout cannot be corrupted by one. Only the
|
|
209
|
+
* *formatting* may depend on the mode — colour and indentation for a terminal,
|
|
210
|
+
* plain ASCII otherwise. Whether a warning is emitted at all may not.
|
|
211
|
+
*
|
|
212
|
+
* Anything a caller might branch on belongs in the JSON payload as well; stderr
|
|
213
|
+
* is for whoever reads the transcript afterwards.
|
|
214
|
+
*/
|
|
215
|
+
export declare function warn(message: string, hint?: string): void;
|
|
137
216
|
/** Print an error (+ optional hint) and exit non-zero. Never returns. */
|
|
138
217
|
export declare function fail(message: string, hint?: string, code?: string): never;
|
|
139
218
|
/**
|
|
@@ -149,15 +228,63 @@ export declare function confirmDestructive(opts: {
|
|
|
149
228
|
prompt: string;
|
|
150
229
|
}): Promise<void>;
|
|
151
230
|
/**
|
|
152
|
-
*
|
|
231
|
+
* Resolve one cloud command's flags and ARGUMENTS from the full `process.argv`.
|
|
232
|
+
*
|
|
233
|
+
* This replaces `cloudPositionals`, which was `rawArgs.slice(3).filter(a =>
|
|
234
|
+
* !a.startsWith("-"))`. Dropping `-`-prefixed tokens looks like it solves the
|
|
235
|
+
* permissive-parse problem and does not: a flag that takes a VALUE leaves the
|
|
236
|
+
* value behind, an ordinary word in the argument position that no filter can
|
|
237
|
+
* tell from a real one. `--project` is the flag every one of these commands
|
|
238
|
+
* documents, so the failure was reachable from the help page:
|
|
239
|
+
*
|
|
240
|
+
* rebase cloud env unset -p acme → removed the variable "acme"
|
|
241
|
+
* rebase cloud env set KEY -p acme → stored the value "acme"
|
|
242
|
+
* rebase cloud domains add -p acme → registered the domain "acme"
|
|
243
|
+
* rebase cloud webhooks delete -p acme 42 → deleted webhook "acme", not 42
|
|
244
|
+
* rebase cloud cancel -p acme → cancelled deployment id "acme"
|
|
245
|
+
*
|
|
246
|
+
* The filter's other half is quieter. A flag nobody declared *is* dropped by
|
|
247
|
+
* it — but only from the operands, never from the run: nothing rejects it, so
|
|
248
|
+
* the command proceeds with the argument missing or defaulted. `db backup
|
|
249
|
+
* --dry-run` listed backups, `domains remove --dry-run` detached the domain,
|
|
250
|
+
* and `env set KEY=v --secrett` stored the value as an ordinary variable that
|
|
251
|
+
* `env reveal` will hand back. The one place an undeclared flag became the
|
|
252
|
+
* argument outright is `projects info|delete`, which resolved its id through
|
|
253
|
+
* `positionals()` instead — that skips only LEADING `-` tokens, so `projects
|
|
254
|
+
* delete --force` looked up a project named "--force".
|
|
255
|
+
*
|
|
256
|
+
* So: parse the whole line strictly, through the same `parseCommandArgs` the
|
|
257
|
+
* non-cloud commands use — `arg` then consumes each declared flag *with its
|
|
258
|
+
* value* wherever it appears, and rejects the undeclared, leaving `_` holding
|
|
259
|
+
* the command words followed by the real arguments. `commandWords` counts from
|
|
260
|
+
* `cloud` itself (`cloud env set` ⇒ 3), and is applied to the parsed
|
|
261
|
+
* positionals, so a flag written before the group shifts nothing.
|
|
262
|
+
*
|
|
263
|
+
* Two things this adds over calling `parseCommandArgs` directly, and the reason
|
|
264
|
+
* it is worth a wrapper:
|
|
153
265
|
*
|
|
154
|
-
*
|
|
155
|
-
*
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
266
|
+
* - `GLOBAL_CLOUD_FLAGS` is merged in. `--json`, `--yes` and `--project` may
|
|
267
|
+
* appear anywhere on a cloud line including before the group, so a strict
|
|
268
|
+
* parse that did not declare them would reject the CLI's own documented
|
|
269
|
+
* usage. (`parseCommandArgs` adds `--debug`/`--help` on top of that.)
|
|
270
|
+
* - A parse error is reported through `fail`, not thrown. A throw reaches
|
|
271
|
+
* `bin/rebase.js`, which prints `✗ …` to stderr — which is right for every
|
|
272
|
+
* other command and wrong here: `rebase cloud` is in JSON mode whenever
|
|
273
|
+
* stdout is not a TTY, i.e. always for the agents this family is built for,
|
|
274
|
+
* and it promises them exactly one JSON value. `fail` keeps that promise,
|
|
275
|
+
* with the same `usage` code the other refusals in this family use.
|
|
159
276
|
*/
|
|
160
|
-
export declare function
|
|
277
|
+
export declare function parseCloudArgs<S extends arg.Spec>(opts: {
|
|
278
|
+
spec: S;
|
|
279
|
+
rawArgs: string[];
|
|
280
|
+
commandWords: number;
|
|
281
|
+
/** Names the command in errors, e.g. `cloud env set` (no leading `rebase`). */
|
|
282
|
+
command: string;
|
|
283
|
+
maxPositionals?: number;
|
|
284
|
+
}): {
|
|
285
|
+
flags: arg.Result<S & typeof GLOBAL_CLOUD_FLAGS>;
|
|
286
|
+
positionals: string[];
|
|
287
|
+
};
|
|
161
288
|
export declare function success(message: string): void;
|
|
162
289
|
/** Colorize a deployment / resource status token. */
|
|
163
290
|
export declare function colorStatus(status: string | undefined): string;
|
|
@@ -1 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `rebase cloud db` — database + backup management for a project.
|
|
3
|
+
*
|
|
4
|
+
* db list List databases attached to the project
|
|
5
|
+
* db create Attach a managed or bring-your-own database
|
|
6
|
+
* db test Test connectivity to the project's database
|
|
7
|
+
* db backup list|create|restore
|
|
8
|
+
*/
|
|
9
|
+
import arg from "arg";
|
|
1
10
|
export declare function dbCommand(subcommand: string | undefined, rawArgs: string[]): Promise<void>;
|
|
11
|
+
/**
|
|
12
|
+
* `db backup [action] [filename]`, resolved in one strict parse.
|
|
13
|
+
*
|
|
14
|
+
* Both halves were reachable by the old operand filter, and both are
|
|
15
|
+
* destructive: `rebase cloud db backup -p acme` read `--project`'s value as the
|
|
16
|
+
* ACTION (falling through to a list, so the flag silently changed what ran),
|
|
17
|
+
* and `db backup restore -p acme` read it as the FILENAME — a restore staged
|
|
18
|
+
* over the live database, named after the project slug. An undeclared flag was
|
|
19
|
+
* dropped instead of refused, which is the same failure one step quieter: `db
|
|
20
|
+
* backup --dry-run` ran a list, having silently discarded the flag that was
|
|
21
|
+
* supposed to change what it did.
|
|
22
|
+
*
|
|
23
|
+
* Exported so its tests drive the real parser.
|
|
24
|
+
*/
|
|
25
|
+
export declare function resolveBackupArgs(rawArgs: string[]): {
|
|
26
|
+
flags: arg.Result<{
|
|
27
|
+
"--yes": BooleanConstructor;
|
|
28
|
+
} & {
|
|
29
|
+
readonly "--json": BooleanConstructor;
|
|
30
|
+
readonly "--yes": BooleanConstructor;
|
|
31
|
+
readonly "--help": BooleanConstructor;
|
|
32
|
+
readonly "--project": StringConstructor;
|
|
33
|
+
readonly "-p": "--project";
|
|
34
|
+
readonly "-y": "--yes";
|
|
35
|
+
readonly "-h": "--help";
|
|
36
|
+
}>;
|
|
37
|
+
action: string;
|
|
38
|
+
filename: string;
|
|
39
|
+
};
|
|
40
|
+
export declare function printDbHelp(): void;
|
|
@@ -115,3 +115,4 @@ export declare function formatDuration(seconds: number): string;
|
|
|
115
115
|
*/
|
|
116
116
|
export declare function parseSince(input: string | undefined): number | null;
|
|
117
117
|
export declare function debugCommand(action: string | undefined, rawArgs: string[]): Promise<void>;
|
|
118
|
+
export declare function printDebugHelp(): void;
|
|
@@ -46,5 +46,69 @@ export declare function timeAgo(value: string | Date | undefined, now: Date): st
|
|
|
46
46
|
export declare function isManagedProject(project: DeployProjectRow | undefined, latest: DeploySourceRow | undefined): boolean;
|
|
47
47
|
/** What a `deploy` with nothing attached will build, in the words to print. */
|
|
48
48
|
export declare function planBareDeploy(project: DeployProjectRow | undefined, latest: DeploySourceRow | undefined, now: Date): BareDeployPlan;
|
|
49
|
+
/**
|
|
50
|
+
* A warning attached to a deploy: printed for the human, carried in the JSON.
|
|
51
|
+
*
|
|
52
|
+
* `code` is the stable half — the message is prose and will be reworded, so it
|
|
53
|
+
* is the code that CI or an agent branches on.
|
|
54
|
+
*/
|
|
55
|
+
export interface DeployWarning {
|
|
56
|
+
code: string;
|
|
57
|
+
message: string;
|
|
58
|
+
hint?: string;
|
|
59
|
+
}
|
|
60
|
+
/** `code` of the warning below, and the field name it sets in the payload. */
|
|
61
|
+
export declare const EJECTS_MANAGED_RUNTIME = "ejects_managed_runtime";
|
|
62
|
+
/** The one sentence that says a source build undoes `runtimeMode: managed`. */
|
|
63
|
+
export declare function ejectWarning(projectRef: string): DeployWarning;
|
|
64
|
+
/** How a container-image deploy was asked for — the input to both rules below. */
|
|
65
|
+
export interface EjectContext {
|
|
66
|
+
/** The project currently runs on the managed runtime. */
|
|
67
|
+
managed: boolean;
|
|
68
|
+
/** `--source` was passed: build this directory. */
|
|
69
|
+
source: boolean;
|
|
70
|
+
/** `--force` was passed: eject on purpose. */
|
|
71
|
+
force: boolean;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Why a container-image deploy of a managed project is refused — or `undefined`
|
|
75
|
+
* to let it through.
|
|
76
|
+
*
|
|
77
|
+
* Every path below this point builds a container image, and a successful one
|
|
78
|
+
* sets `runtimeMode: "custom"` server-side. So the question is never "which flag
|
|
79
|
+
* was used" but "did the caller ask to leave the managed runtime", and only
|
|
80
|
+
* `--force` answers it.
|
|
81
|
+
*
|
|
82
|
+
* `--source` used to be read as answering it too, on the theory that uploading a
|
|
83
|
+
* build context is self-evidently a deliberate eject. It is not: `--source`
|
|
84
|
+
* picks *which source* gets built — this directory, rather than the stale
|
|
85
|
+
* archive the control plane is holding — and the eject is a side effect of the
|
|
86
|
+
* answer. That is exactly how a live project got flipped to `custom` by someone
|
|
87
|
+
* whose actual intent was "deploy what I have here", and it is the same
|
|
88
|
+
* ignorance the bare form is refused for. Same ignorance, same refusal.
|
|
89
|
+
*/
|
|
90
|
+
export declare function ejectRefusal(opts: EjectContext, projectRef: string): {
|
|
91
|
+
message: string;
|
|
92
|
+
hint: string;
|
|
93
|
+
code: string;
|
|
94
|
+
} | undefined;
|
|
95
|
+
/**
|
|
96
|
+
* Which warnings a container-image deploy has earned.
|
|
97
|
+
*
|
|
98
|
+
* Pure, and separate from the printing, because the printing is what went
|
|
99
|
+
* wrong: the eject warning used to be written inline behind `!isJsonMode()`, so
|
|
100
|
+
* the fact that a deploy ejects a managed project existed only as a side effect
|
|
101
|
+
* of a TTY being attached. Deciding here, emitting once at the call site, means
|
|
102
|
+
* the decision cannot be output-mode-dependent again.
|
|
103
|
+
*
|
|
104
|
+
* The condition is just `managed`: anything reaching this point is a container
|
|
105
|
+
* image build that `ejectRefusal` has already let through, and on a managed
|
|
106
|
+
* project that is an eject however it was spelled. A caller who passed `--force`
|
|
107
|
+
* knows — the warning is for the transcript and the payload, which is what
|
|
108
|
+
* anyone reviewing the deploy afterwards actually reads.
|
|
109
|
+
*/
|
|
110
|
+
export declare function deployWarnings(opts: EjectContext, projectRef: string): DeployWarning[];
|
|
111
|
+
/** The warning half of a deploy's JSON payload — merged into whatever it emits. */
|
|
112
|
+
export declare function warningPayload(warnings: DeployWarning[]): Record<string, unknown>;
|
|
49
113
|
export declare function deployCommand(rawArgs: string[], projectRef: string): Promise<void>;
|
|
50
114
|
export declare function logsCommand(rawArgs: string[], projectRef: string): Promise<void>;
|
|
@@ -50,5 +50,27 @@ export declare const DEFAULT_DEPLOYMENTS_LIMIT = 20;
|
|
|
50
50
|
/** `--limit N`, bounded. A garbage value is a refusal, never a silent default. */
|
|
51
51
|
export declare function parseDeploymentsLimit(raw: number | undefined): number;
|
|
52
52
|
export declare function deploymentsListCommand(rawArgs: string[]): Promise<void>;
|
|
53
|
+
/**
|
|
54
|
+
* The deployment id `rollback`/`cancel` was given, if any.
|
|
55
|
+
*
|
|
56
|
+
* Both take an optional id, which is what made the old operand filter so easy
|
|
57
|
+
* to trip: `rebase cloud rollback -p acme` — the documented way to act on an
|
|
58
|
+
* unlinked project — read `--project`'s value as the id and refused with
|
|
59
|
+
* "Deployment acme not found", and `cancel -p acme` sent "acme" to the server
|
|
60
|
+
* as the deployment to cancel. Strict parsing consumes the flag with its value,
|
|
61
|
+
* so an id given as a flag value is never mistaken for an argument.
|
|
62
|
+
*/
|
|
63
|
+
export declare function resolveDeploymentIdArg(rawArgs: string[], command: string): {
|
|
64
|
+
flags: import("arg").Result<{
|
|
65
|
+
readonly "--json": BooleanConstructor;
|
|
66
|
+
readonly "--yes": BooleanConstructor;
|
|
67
|
+
readonly "--help": BooleanConstructor;
|
|
68
|
+
readonly "--project": StringConstructor;
|
|
69
|
+
readonly "-p": "--project";
|
|
70
|
+
readonly "-y": "--yes";
|
|
71
|
+
readonly "-h": "--help";
|
|
72
|
+
}>;
|
|
73
|
+
id: string;
|
|
74
|
+
};
|
|
53
75
|
export declare function rollbackCommand(rawArgs: string[]): Promise<void>;
|
|
54
76
|
export declare function cancelCommand(rawArgs: string[]): Promise<void>;
|
|
@@ -1 +1,11 @@
|
|
|
1
1
|
export declare function domainsCommand(action: string | undefined, rawArgs: string[]): Promise<void>;
|
|
2
|
+
/**
|
|
3
|
+
* The domain `domains add` was asked to register.
|
|
4
|
+
*
|
|
5
|
+
* Exported so its tests drive the real parser. Under the old operand filter
|
|
6
|
+
* `rebase cloud domains add -p acme` registered a domain called "acme" — the
|
|
7
|
+
* project slug, read out of `--project`'s own value — and a registered domain
|
|
8
|
+
* is a project-record write, not a no-op.
|
|
9
|
+
*/
|
|
10
|
+
export declare function resolveDomainArg(rawArgs: string[]): string | undefined;
|
|
11
|
+
export declare function printDomainsHelp(): void;
|
|
@@ -6,3 +6,54 @@ export declare function parseEnvAssignment(operands: string[]): {
|
|
|
6
6
|
} | null;
|
|
7
7
|
/** The prefix that makes `key` a build-time variable, or undefined. */
|
|
8
8
|
export declare function buildTimeEnvPrefix(key: string): string | undefined;
|
|
9
|
+
/** The flags `rebase cloud env set` takes, on top of the global cloud ones. */
|
|
10
|
+
export declare const ENV_SET_FLAGS: {
|
|
11
|
+
readonly "--secret": BooleanConstructor;
|
|
12
|
+
readonly "--force": BooleanConstructor;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* What `env set` was asked to store.
|
|
16
|
+
*
|
|
17
|
+
* The sharp one in this family: the old operand filter left `--project`'s value
|
|
18
|
+
* in the operand list, so `rebase cloud env set KEY -p acme` parsed as the
|
|
19
|
+
* `KEY VALUE` form and stored the project slug as KEY's value — a write that
|
|
20
|
+
* succeeds, reports success, and is wrong. Strict parsing consumes `-p` with
|
|
21
|
+
* its value, leaving `["KEY"]` and the documented empty value.
|
|
22
|
+
*
|
|
23
|
+
* A value beginning with `-` must use the `KEY=-v` form; the bare `KEY -v` form
|
|
24
|
+
* is refused rather than guessed at, as everywhere else strict parsing is used.
|
|
25
|
+
*
|
|
26
|
+
* Exported so its tests drive the real parser rather than a copy of it.
|
|
27
|
+
*/
|
|
28
|
+
export declare function resolveEnvSetArgs(rawArgs: string[]): {
|
|
29
|
+
flags: import("arg").Result<{
|
|
30
|
+
readonly "--secret": BooleanConstructor;
|
|
31
|
+
readonly "--force": BooleanConstructor;
|
|
32
|
+
} & {
|
|
33
|
+
readonly "--json": BooleanConstructor;
|
|
34
|
+
readonly "--yes": BooleanConstructor;
|
|
35
|
+
readonly "--help": BooleanConstructor;
|
|
36
|
+
readonly "--project": StringConstructor;
|
|
37
|
+
readonly "-p": "--project";
|
|
38
|
+
readonly "-y": "--yes";
|
|
39
|
+
readonly "-h": "--help";
|
|
40
|
+
}>;
|
|
41
|
+
assignment: {
|
|
42
|
+
key: string;
|
|
43
|
+
value: string;
|
|
44
|
+
} | null;
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* The variable `env unset` / `env reveal` names.
|
|
48
|
+
*
|
|
49
|
+
* `unset` is a delete, and the operand filter aimed it at the wrong variable:
|
|
50
|
+
* `rebase cloud env unset -p acme` removed a variable called "acme" from the
|
|
51
|
+
* linked project instead of reporting a missing KEY, and `env unset -p acme
|
|
52
|
+
* KEY` removed "acme" instead of KEY. Both read `--project`'s value as the
|
|
53
|
+
* operand — a plain word in the right position that no flag filter can catch.
|
|
54
|
+
*
|
|
55
|
+
* `action` is the word the caller used (`unset`, `rm`, `delete`, `reveal`); the
|
|
56
|
+
* count of command words is the same for all of them.
|
|
57
|
+
*/
|
|
58
|
+
export declare function resolveEnvKeyArg(rawArgs: string[], action: string): string | undefined;
|
|
59
|
+
export declare function printEnvHelp(): void;
|
|
@@ -1,3 +1,24 @@
|
|
|
1
1
|
/** The identifier CREATE EXTENSION takes. `pgvector` is a common alias. */
|
|
2
2
|
export declare function resolveExtensionAlias(name: string): string;
|
|
3
3
|
export declare function extensionsCommand(action: string | undefined, rawArgs: string[]): Promise<void>;
|
|
4
|
+
/**
|
|
5
|
+
* The extension `enable`/`disable` names, plus the flags that gate it.
|
|
6
|
+
*
|
|
7
|
+
* Under the old operand filter `rebase cloud extensions enable -p acme` read
|
|
8
|
+
* `--project`'s value as the extension name and asked the server to install one
|
|
9
|
+
* called "acme"; `extensions disable -p acme vector` dropped "acme" rather than
|
|
10
|
+
* vector. Strict parsing consumes the flag with its value.
|
|
11
|
+
*/
|
|
12
|
+
export declare function resolveExtensionArgs(rawArgs: string[], action: "enable" | "disable"): {
|
|
13
|
+
flags: import("arg").Result<{
|
|
14
|
+
readonly "--json": BooleanConstructor;
|
|
15
|
+
readonly "--yes": BooleanConstructor;
|
|
16
|
+
readonly "--help": BooleanConstructor;
|
|
17
|
+
readonly "--project": StringConstructor;
|
|
18
|
+
readonly "-p": "--project";
|
|
19
|
+
readonly "-y": "--yes";
|
|
20
|
+
readonly "-h": "--help";
|
|
21
|
+
}>;
|
|
22
|
+
name: string;
|
|
23
|
+
};
|
|
24
|
+
export declare function printExtensionsHelp(): void;
|
|
@@ -1 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Positional tokens after `rebase cloud` (group, action, …).
|
|
3
|
+
*
|
|
4
|
+
* Two things stop a flag being mistaken for the group. `GLOBAL_CLOUD_FLAGS` is
|
|
5
|
+
* declared so `arg` *consumes* the flags that may precede it — critically
|
|
6
|
+
* together with their values, which is the half that filtering cannot do. The
|
|
7
|
+
* leading-`-` skip then covers a flag nobody declared, so an unrecognised
|
|
8
|
+
* boolean shifts nothing.
|
|
9
|
+
*
|
|
10
|
+
* Only leading tokens are skipped: past the group and action, an undeclared
|
|
11
|
+
* flag and its value are somebody else's positionals and none of our business.
|
|
12
|
+
* A flag this file has never heard of, that takes a value, placed before the
|
|
13
|
+
* group, is the one shape still unresolvable here — there is no way to know
|
|
14
|
+
* whether the token after it is its value or the group, and guessing either way
|
|
15
|
+
* is worse than the handler reporting an unknown group.
|
|
16
|
+
*
|
|
17
|
+
* Exported so its tests can drive the real thing. The dispatch test used to
|
|
18
|
+
* re-implement it locally as `slice(3).filter(a => !a.startsWith("-"))` — which
|
|
19
|
+
* filtered flags, while this function did not — so the test asserted the
|
|
20
|
+
* behaviour we wanted against a copy that had it, and stayed green for as long
|
|
21
|
+
* as the real dispatcher was broken.
|
|
22
|
+
*/
|
|
23
|
+
export declare function positionals(rawArgs: string[]): string[];
|
|
1
24
|
export declare function cloudCommand(subcommand: string | undefined, rawArgs: string[]): Promise<void>;
|