@rebasepro/cli 0.13.0 → 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.
Files changed (36) hide show
  1. package/dist/bundle.d.ts +4 -3
  2. package/dist/commands/api-keys.d.ts +51 -0
  3. package/dist/commands/auth.d.ts +62 -0
  4. package/dist/commands/cloud/context.d.ts +56 -7
  5. package/dist/commands/cloud/databases.d.ts +39 -0
  6. package/dist/commands/cloud/debug.d.ts +1 -0
  7. package/dist/commands/cloud/deployments.d.ts +22 -0
  8. package/dist/commands/cloud/domains.d.ts +10 -0
  9. package/dist/commands/cloud/env.d.ts +51 -0
  10. package/dist/commands/cloud/extensions.d.ts +21 -0
  11. package/dist/commands/cloud/orgs.d.ts +1 -0
  12. package/dist/commands/cloud/projects.d.ts +29 -0
  13. package/dist/commands/cloud/resources.d.ts +14 -0
  14. package/dist/commands/cloud/settings.d.ts +1 -0
  15. package/dist/commands/dev.d.ts +17 -6
  16. package/dist/commands/eject.d.ts +42 -0
  17. package/dist/commands/init.d.ts +67 -0
  18. package/dist/commands/skills.d.ts +81 -0
  19. package/dist/fold-static.d.ts +47 -0
  20. package/dist/index.es.js +1440 -415
  21. package/dist/index.es.js.map +1 -1
  22. package/dist/manifest.d.ts +16 -1
  23. package/dist/telemetry/payload.d.ts +1 -1
  24. package/dist/utils/args.d.ts +76 -0
  25. package/dist/utils/collection-drift.d.ts +27 -0
  26. package/dist/utils/project.d.ts +20 -0
  27. package/package.json +7 -7
  28. package/templates/eject/Dockerfile +29 -4
  29. package/templates/eject/backend/src/index.ts +49 -5
  30. package/templates/eject/docker-compose.custom.yml +13 -5
  31. package/templates/overlays/baas/backend/tsconfig.json +6 -1
  32. package/templates/template/.env.example +13 -4
  33. package/templates/template/backend/functions/hello.ts +8 -4
  34. package/templates/template/backend/tsconfig.json +6 -1
  35. package/templates/template/config/package.json +1 -0
  36. package/templates/template/docker-compose.yml +4 -4
package/dist/bundle.d.ts CHANGED
@@ -136,10 +136,11 @@ export declare function normalizeEsmSpecifiers(outDir: string): {
136
136
  * deployed green, and answered 404 on every one of them, with the file still
137
137
  * sitting in the repository looking exactly like the server.
138
138
  *
139
- * A project that means to keep its own entrypoint runs `rebase eject`, which
140
- * writes the entrypoint, a Dockerfile and a compose file together and flips the
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
141
141
  * backend to `runtime: "custom"`. The warning names that route rather than
142
- * 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".
143
144
  */
144
145
  export declare function findUnusedServerEntry(projectRoot: string, functionsDir: string): string | undefined;
145
146
  /**
@@ -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
+ };
@@ -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;
@@ -227,15 +228,63 @@ export declare function confirmDestructive(opts: {
227
228
  prompt: string;
228
229
  }): Promise<void>;
229
230
  /**
230
- * Positional tokens after `rebase cloud` `[group, action, arg1, …]`.
231
+ * Resolve one cloud command's flags and ARGUMENTS from the full `process.argv`.
231
232
  *
232
- * Deliberately NOT `arg({}, { permissive: true })._`: in permissive mode `arg`
233
- * pushes UNKNOWN FLAGS onto `_` too, so `rollback --yes --json` would report
234
- * `--yes` as the deployment id. Operand extraction must see operands only, so
235
- * anything starting with `-` is dropped the same filter the db backup handler
236
- * has always used.
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:
265
+ *
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.
237
276
  */
238
- export declare function cloudPositionals(rawArgs: string[]): string[];
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
+ };
239
288
  export declare function success(message: string): void;
240
289
  /** Colorize a deployment / resource status token. */
241
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;
@@ -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,2 @@
1
1
  export declare function orgsCommand(subcommand: string | undefined, rawArgs: string[]): Promise<void>;
2
+ export declare function printOrgsHelp(): void;
@@ -31,7 +31,36 @@ export declare function chooseRequestedTarget(requested: string | undefined, tar
31
31
  provider: string;
32
32
  region?: string;
33
33
  } | null;
34
+ /** The flags `rebase cloud projects create` takes. */
35
+ export declare const CREATE_PROJECT_FLAGS: {
36
+ readonly "--name": StringConstructor;
37
+ readonly "--subdomain": StringConstructor;
38
+ readonly "--repo": StringConstructor;
39
+ readonly "--branch": StringConstructor;
40
+ readonly "--provider": StringConstructor;
41
+ readonly "--region": StringConstructor;
42
+ readonly "--vm-size": StringConstructor;
43
+ readonly "--org": StringConstructor;
44
+ readonly "--link": BooleanConstructor;
45
+ readonly "-n": "--name";
46
+ };
34
47
  export declare function createProject(rawArgs: string[]): Promise<void>;
48
+ /**
49
+ * Which project `projects info` / `projects delete` acts on.
50
+ *
51
+ * The id is optional — omitted, it falls back to `--project` or the link file —
52
+ * and the dispatcher used to read it off `positionals()`, which skips only
53
+ * LEADING `-` tokens and declares only the global cloud flags. So an undeclared
54
+ * flag written after the action became the id: `rebase cloud projects delete
55
+ * --force` looked up a project named "--force" and reported it missing, rather
56
+ * than saying there is no such flag. Benign next to the deletes and writes the
57
+ * rest of this family aimed at the wrong resource, but the same mistake, and
58
+ * `positionals()` has no spec with which to do better — the handler's own
59
+ * module does.
60
+ *
61
+ * Exported so its tests drive the real parser rather than a copy of it.
62
+ */
63
+ export declare function resolveProjectArg(rawArgs: string[], action: "info" | "delete"): string;
35
64
  export declare function projectInfo(rawArgs: string[], projectRef: string): Promise<void>;
36
65
  export declare function deleteProject(rawArgs: string[], projectRef: string): Promise<void>;
37
66
  export declare function firstRow(client: CloudClient, collection: string, projectId: string): Promise<Record<string, unknown> | undefined>;
@@ -57,8 +57,22 @@ export declare function describeRuntime(project: {
57
57
  }): string;
58
58
  export declare function statusCommand(rawArgs: string[]): Promise<void>;
59
59
  export declare function metricsCommand(rawArgs: string[]): Promise<void>;
60
+ /**
61
+ * The webhook `webhooks delete` names.
62
+ *
63
+ * The worst instance of the operand-filter bug in this family, because the
64
+ * argument is consumed by a DELETE and the wrong value looks entirely
65
+ * plausible: `rebase cloud webhooks delete --project acme 42` filtered out
66
+ * `--project` and kept "acme", so the id it deleted was the project slug rather
67
+ * than the 42 the caller wrote. Strict parsing consumes the flag with its
68
+ * value, leaving `["42"]`.
69
+ *
70
+ * Exported so its tests drive the real parser.
71
+ */
72
+ export declare function resolveWebhookIdArg(rawArgs: string[]): string | undefined;
60
73
  export declare function webhooksCommand(subcommand: string | undefined, rawArgs: string[]): Promise<void>;
61
74
  export declare function storageCommand(action: string | undefined, rawArgs: string[]): Promise<void>;
75
+ export declare function printStorageHelp(): void;
62
76
  export declare function clustersCommand(rawArgs: string[]): Promise<void>;
63
77
  export declare function billingCommand(rawArgs: string[]): Promise<void>;
64
78
  export {};
@@ -6,3 +6,4 @@ export declare function buildSettingsPatch(args: {
6
6
  repo?: string;
7
7
  branch?: string;
8
8
  }): Record<string, string>;
9
+ export declare function printSettingsHelp(): void;
@@ -6,12 +6,23 @@ export declare const DEV_PORT_FILENAME = ".rebase-dev-port";
6
6
  * Two different project directories will almost always get different ports.
7
7
  */
8
8
  export declare function getProjectPort(projectRoot: string): number;
9
+ export declare function resolveStartPort(projectRoot: string, explicitPort?: number): number;
9
10
  /**
10
- * Resolve the best starting port for this project:
11
- * 1. Explicit --port flag (highest priority)
12
- * 2. PORT env var
13
- * 3. Previously used port from .rebase-dev-port (port affinity across restarts)
14
- * 4. Deterministic hash from project path (unique per project)
11
+ * The flags `rebase dev` takes.
12
+ *
13
+ * Exported so `dev.test.ts` can assert that every short alias the help
14
+ * advertises is declared here: the help said `--port, -p` while the spec has
15
+ * only ever declared `-P`, so `rebase dev -p 4000` typed straight off the help
16
+ * page passed `4000` as a positional and started on the default port.
15
17
  */
16
- export declare function resolveStartPort(projectRoot: string, explicitPort?: number): number;
18
+ export declare const DEV_FLAGS: {
19
+ readonly "--backend-only": BooleanConstructor;
20
+ readonly "--frontend-only": BooleanConstructor;
21
+ readonly "--port": NumberConstructor;
22
+ readonly "--generate": BooleanConstructor;
23
+ readonly "-b": "--backend-only";
24
+ readonly "-f": "--frontend-only";
25
+ readonly "-P": "--port";
26
+ readonly "-g": "--generate";
27
+ };
17
28
  export declare function devCommand(rawArgs: string[]): Promise<void>;
@@ -1 +1,43 @@
1
+ /**
2
+ * The two ways one project's payload differs from another's.
3
+ *
4
+ * Neither is a flag: both were decided at `rebase init` time. `--headless`
5
+ * deletes `config/collections`, `backend/src/schema.generated.ts` and
6
+ * `frontend/`, so a payload that assumes them emits an entrypoint importing
7
+ * three files that are not there and a Dockerfile whose first `COPY` fails.
8
+ */
9
+ interface ProjectShape {
10
+ /**
11
+ * Collections declared in code, under `<config>/collections`. Without them
12
+ * the server derives its API from the live database instead — the same
13
+ * signal `rebase build` reads.
14
+ */
15
+ collections: boolean;
16
+ /** A `frontend` workspace for the image to build and the entrypoint to serve. */
17
+ frontend: boolean;
18
+ }
19
+ /**
20
+ * Render one payload file for this project.
21
+ *
22
+ * The payload is one set of files rather than one per flavour, because the
23
+ * flavours differ by about a dozen lines and two copies of a 230-line
24
+ * entrypoint are how copies drift — the payload had already drifted from
25
+ * `app/backend/src/index.ts` over `cronsDir`, which silently stopped every cron
26
+ * job in an ejected project. So both branches live in the file, marked with
27
+ * lines that are comments in TypeScript, YAML and Dockerfiles alike:
28
+ *
29
+ * // {{#collections}}
30
+ * import { tables } from "./schema.generated.js";
31
+ * // {{/collections}}
32
+ * // {{^collections}}
33
+ * // No schema module: this project introspects the database.
34
+ * // {{/collections}}
35
+ *
36
+ * `{{#name}}` keeps its block when the flag is on, `{{^name}}` when it is off,
37
+ * and the marker lines themselves never reach the user. The template stays
38
+ * valid TypeScript with every marker line removed, which is the flavour a
39
+ * typechecker would see.
40
+ */
41
+ export declare function renderPayload(contents: string, shape: ProjectShape, projectName: string): string;
1
42
  export declare function ejectCommand(rawArgs?: string[]): Promise<void>;
43
+ export {};
@@ -68,4 +68,71 @@ export declare function formatCdTarget(cwd: string, targetDirectory: string): st
68
68
  * triggering the non-TTY error. */
69
69
  export declare function printInitHelp(): void;
70
70
  export declare function createRebaseApp(rawArgs: string[]): Promise<void>;
71
+ /** The flags `rebase init` takes. */
72
+ export declare const INIT_FLAGS: {
73
+ readonly "--git": BooleanConstructor;
74
+ readonly "--install": BooleanConstructor;
75
+ readonly "--database-url": StringConstructor;
76
+ readonly "--introspect": BooleanConstructor;
77
+ readonly "--template": StringConstructor;
78
+ readonly "--headless": BooleanConstructor;
79
+ readonly "--project": StringConstructor;
80
+ readonly "--setup-key": StringConstructor;
81
+ readonly "--yes": BooleanConstructor;
82
+ readonly "-g": "--git";
83
+ readonly "-i": "--install";
84
+ readonly "-t": "--template";
85
+ readonly "-y": "--yes";
86
+ };
87
+ /**
88
+ * Whether `port` is free — on the wildcard address *and* on both loopback addresses.
89
+ *
90
+ * All three, because on macOS/BSD a successful bind does not mean the port is
91
+ * unused. Sockets carry `SO_REUSEADDR` (Node sets it), under which a wildcard
92
+ * bind and a specific-address bind on the same port do not conflict — in either
93
+ * direction. So each probe alone has a blind spot, and they are different ones:
94
+ *
95
+ * - **Wildcard only** (what this used to do) misses a server bound to
96
+ * `127.0.0.1` and `[::1]` — a Homebrew or Postgres.app install, i.e. most
97
+ * developer machines. 5432 was reported free while it was already serving
98
+ * another project's database. Docker then published `*:5432` for the same
99
+ * reason and the container started cleanly, with no "port already allocated"
100
+ * error anywhere to hint at the collision. `DATABASE_URL` pointed at
101
+ * `localhost:5432`, `localhost` resolves to `::1` first, and every command
102
+ * reported success while reading and writing the *pre-existing* database — a
103
+ * `db push` would have created tables, roles and RLS policies inside it.
104
+ *
105
+ * - **Loopback only** misses the opposite case: Docker Desktop publishes a
106
+ * container's port on `*`, and a specific-address bind succeeds right past it.
107
+ * That port is free to probe and unusable to publish, so `docker compose up -d
108
+ * db` fails on "Bind for 0.0.0.0:PORT failed: port is already allocated" —
109
+ * loudly, but only after the project has been generated around the bad port.
110
+ *
111
+ * Requiring all three costs three sockets and leaves neither gap. The wildcard
112
+ * bind is the one the container itself has to make; the loopback binds are the
113
+ * addresses `DATABASE_URL` will actually name.
114
+ */
115
+ export declare function isPortAvailable(port: number): Promise<boolean>;
116
+ /**
117
+ * The runtime image tag to pin, given the version of the CLI doing the scaffolding.
118
+ *
119
+ * Only a stable release publishes `rebasepro/server` — a multi-arch build on
120
+ * every push to main would cost minutes per commit for an image nobody pulls.
121
+ * So pinning a prerelease CLI's own version writes a tag that cannot exist, and
122
+ * `docker compose up` fails on `manifest unknown`, which is the same dead end
123
+ * as the missing-repository bug this pinning was added to prevent.
124
+ *
125
+ * A prerelease therefore falls back to `latest`, which is correct rather than
126
+ * merely available: a bundle's manifest declares the runtime range it needs
127
+ * (`^1`), the image supplies only `@rebasepro/server`, and the framework a
128
+ * bundle runs is installed from its own `deps.declared` at boot. The current
129
+ * stable runtime boots a canary bundle by design.
130
+ *
131
+ * A floating tag is a real cost — it is what pinning exists to avoid — so say
132
+ * so in the file rather than leaving a reader to discover it.
133
+ */
134
+ export declare function resolveRuntimeImageTag(cliVersion: string): {
135
+ tag: string;
136
+ note?: string;
137
+ };
71
138
  export declare function configureEnvFile(targetDirectory: string, databaseUrl?: string): Promise<void>;