@rebasepro/cli 0.13.0 → 0.13.1-canary.g249daa1

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.
@@ -1 +1,32 @@
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>;
@@ -1 +1,2 @@
1
1
  export declare function dbCommand(subcommand: string | undefined, rawArgs: string[]): Promise<void>;
2
+ 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;
@@ -1 +1,2 @@
1
1
  export declare function domainsCommand(action: string | undefined, rawArgs: string[]): Promise<void>;
2
+ export declare function printDomainsHelp(): void;
@@ -6,3 +6,4 @@ 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
+ export declare function printEnvHelp(): void;
@@ -1,3 +1,4 @@
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
+ 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;
@@ -59,6 +59,7 @@ export declare function statusCommand(rawArgs: string[]): Promise<void>;
59
59
  export declare function metricsCommand(rawArgs: string[]): Promise<void>;
60
60
  export declare function webhooksCommand(subcommand: string | undefined, rawArgs: string[]): Promise<void>;
61
61
  export declare function storageCommand(action: string | undefined, rawArgs: string[]): Promise<void>;
62
+ export declare function printStorageHelp(): void;
62
63
  export declare function clustersCommand(rawArgs: string[]): Promise<void>;
63
64
  export declare function billingCommand(rawArgs: string[]): Promise<void>;
64
65
  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,5 @@ 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
- /**
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)
15
- */
16
9
  export declare function resolveStartPort(projectRoot: string, explicitPort?: number): number;
17
10
  export declare function devCommand(rawArgs: string[]): Promise<void>;
@@ -68,4 +68,55 @@ 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
+ /**
72
+ * Whether `port` is free — on the wildcard address *and* on both loopback addresses.
73
+ *
74
+ * All three, because on macOS/BSD a successful bind does not mean the port is
75
+ * unused. Sockets carry `SO_REUSEADDR` (Node sets it), under which a wildcard
76
+ * bind and a specific-address bind on the same port do not conflict — in either
77
+ * direction. So each probe alone has a blind spot, and they are different ones:
78
+ *
79
+ * - **Wildcard only** (what this used to do) misses a server bound to
80
+ * `127.0.0.1` and `[::1]` — a Homebrew or Postgres.app install, i.e. most
81
+ * developer machines. 5432 was reported free while it was already serving
82
+ * another project's database. Docker then published `*:5432` for the same
83
+ * reason and the container started cleanly, with no "port already allocated"
84
+ * error anywhere to hint at the collision. `DATABASE_URL` pointed at
85
+ * `localhost:5432`, `localhost` resolves to `::1` first, and every command
86
+ * reported success while reading and writing the *pre-existing* database — a
87
+ * `db push` would have created tables, roles and RLS policies inside it.
88
+ *
89
+ * - **Loopback only** misses the opposite case: Docker Desktop publishes a
90
+ * container's port on `*`, and a specific-address bind succeeds right past it.
91
+ * That port is free to probe and unusable to publish, so `docker compose up -d
92
+ * db` fails on "Bind for 0.0.0.0:PORT failed: port is already allocated" —
93
+ * loudly, but only after the project has been generated around the bad port.
94
+ *
95
+ * Requiring all three costs three sockets and leaves neither gap. The wildcard
96
+ * bind is the one the container itself has to make; the loopback binds are the
97
+ * addresses `DATABASE_URL` will actually name.
98
+ */
99
+ export declare function isPortAvailable(port: number): Promise<boolean>;
100
+ /**
101
+ * The runtime image tag to pin, given the version of the CLI doing the scaffolding.
102
+ *
103
+ * Only a stable release publishes `rebasepro/server` — a multi-arch build on
104
+ * every push to main would cost minutes per commit for an image nobody pulls.
105
+ * So pinning a prerelease CLI's own version writes a tag that cannot exist, and
106
+ * `docker compose up` fails on `manifest unknown`, which is the same dead end
107
+ * as the missing-repository bug this pinning was added to prevent.
108
+ *
109
+ * A prerelease therefore falls back to `latest`, which is correct rather than
110
+ * merely available: a bundle's manifest declares the runtime range it needs
111
+ * (`^1`), the image supplies only `@rebasepro/server`, and the framework a
112
+ * bundle runs is installed from its own `deps.declared` at boot. The current
113
+ * stable runtime boots a canary bundle by design.
114
+ *
115
+ * A floating tag is a real cost — it is what pinning exists to avoid — so say
116
+ * so in the file rather than leaving a reader to discover it.
117
+ */
118
+ export declare function resolveRuntimeImageTag(cliVersion: string): {
119
+ tag: string;
120
+ note?: string;
121
+ };
71
122
  export declare function configureEnvFile(targetDirectory: string, databaseUrl?: string): Promise<void>;
@@ -62,6 +62,53 @@ export declare function foldableApps(manifest: FoldableManifest): {
62
62
  * evidence of a misbuild.
63
63
  */
64
64
  export declare function assertBuiltForPath(indexHtml: string, basePath: string, appName: string): void;
65
+ /**
66
+ * The environment every static app is built with, wherever that build is driven from.
67
+ *
68
+ * Shared because there are two drivers — `foldFrontendIntoBundle` here, and
69
+ * `buildAssetApp` in `build.ts` for a standalone `type: "static"` app — and they
70
+ * had already drifted: the path variables were duplicated into both, so a fix
71
+ * applied to one shipped a bundle built the old way from the other. One function
72
+ * makes that impossible rather than merely unlikely.
73
+ *
74
+ * ## REBASE_APP_*
75
+ *
76
+ * The declared path is a build-time input, not only a serving concern: Vite
77
+ * reads `base` from REBASE_APP_BASE, and the trailing slash is that field's
78
+ * convention. See `assertBuiltForPath`.
79
+ *
80
+ * ## NODE_ENV
81
+ *
82
+ * A built app is a production artifact by construction, so build it as one. Not
83
+ * a formality: the scaffold's `.env` carries `NODE_ENV=development` for the dev
84
+ * backend, and Vite's `loadEnv` promotes a `NODE_ENV` found in an env file into
85
+ * the build unless the environment already sets one. So `rebase build` and
86
+ * `rebase cloud deploy` shipped a *development* bundle — `import.meta.env.DEV
87
+ * === true`, development React, dev-only branches live — from commands whose
88
+ * whole purpose is to produce something deployable. Setting it here is what
89
+ * closes it: Vite consults the env file's NODE_ENV only when `process.env`
90
+ * has none.
91
+ *
92
+ * ## VITE_API_URL
93
+ *
94
+ * An app served by the backend it talks to has its API on its own origin by
95
+ * construction, so a baked-in absolute URL can only be wrong. It was: that same
96
+ * `.env` carries `VITE_API_URL=http://localhost:3001` and
97
+ * `frontend/vite.config.ts` reads the project root via `envDir: ".."`, so a
98
+ * stock deploy shipped a site whose every request went to whoever ran the build
99
+ * — passing every server-side health check on the way out. Blanking it here
100
+ * fixes the bundle even for a project whose `.env` predates the `init` fix, or
101
+ * was written by hand. Empty is the right value rather than a missing one: the
102
+ * client falls back to `window.location.origin`, which keeps working when a
103
+ * custom domain is added.
104
+ *
105
+ * Vite prioritises `process.env.VITE_*` over `.env` files, so an explicit
106
+ * `VITE_API_URL=https://api.example.com rebase cloud deploy` still wins — the
107
+ * cross-origin escape hatch stays open, it just has to be deliberate. Nothing on
108
+ * this path loads the project `.env` into `process.env`, so a value inherited
109
+ * here really was set by the caller.
110
+ */
111
+ export declare function staticBuildEnv(appPath: string, appName: string): Record<string, string>;
65
112
  /**
66
113
  * Build the project's static apps and fold them into the backend bundle.
67
114
  *