@rebasepro/cli 0.22.0 → 0.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bundle.d.ts CHANGED
@@ -37,6 +37,11 @@ export interface BuildBundleOptions {
37
37
  skipSchema?: boolean;
38
38
  /** Emit progress. */
39
39
  log?: (message: string) => void;
40
+ /**
41
+ * Keep stdout for the caller's result: the compiler's output, and every
42
+ * warning the build prints, go to stderr. See `toolStdio`.
43
+ */
44
+ quietStdout?: boolean;
40
45
  }
41
46
  export interface BuildBundleResult {
42
47
  outDir: string;
@@ -247,6 +252,11 @@ export interface ComposeManifestInput {
247
252
  * declared bucket arriving as nothing, with both suites green.
248
253
  */
249
254
  export declare function composeBundleManifest(input: ComposeManifestInput): RebaseBundleManifest;
255
+ /**
256
+ * What a build refusing on {@link detectDeclaredDepConflicts} says: every name,
257
+ * both ranges and where each is declared.
258
+ */
259
+ export declare function describeDepConflicts(conflicts: DeclaredDepConflict[]): string;
250
260
  export declare function buildBundle(options: BuildBundleOptions): Promise<BuildBundleResult>;
251
261
  /** Default install target: what the published runtime image runs. */
252
262
  export declare const VENDOR_TARGET_OS = "linux";
package/dist/cli.d.ts CHANGED
@@ -18,6 +18,24 @@ export declare const ROOT_FLAGS: {
18
18
  readonly "-v": "--version";
19
19
  readonly "-h": "--help";
20
20
  };
21
+ /**
22
+ * The command and subcommand words as `cli.error` may send them: each one is a
23
+ * word this CLI dispatches, `"none"` when nothing was typed, or `"other"`.
24
+ *
25
+ * The words come from what was typed, and what is typed after a command is
26
+ * only sometimes a subcommand. `rebase init acme-payroll-internal`, `rebase
27
+ * cloud --project acme-prod deploy` and `rebase db psuh` put a project name, a
28
+ * slug and a typo in the subcommand's position — the consent screen promises
29
+ * "never project names", and `sanitize` cannot tell one of those from a
30
+ * subcommand because neither has a separator in it. So the words are held
31
+ * against the vocabulary here, where it is known, and nothing else survives.
32
+ *
33
+ * Exported for `cli.test.ts`.
34
+ */
35
+ export declare function telemetryCommandWords(command: string | undefined, subcommand: string | undefined): {
36
+ command: string;
37
+ subcommand: string;
38
+ };
21
39
  export declare function entry(args: string[]): Promise<void>;
22
40
  /** The global help. Exported so its Options block can be held against {@link ROOT_FLAGS}. */
23
41
  export declare function printHelp(): void;
@@ -1,3 +1,5 @@
1
+ /** Everything the switch below dispatches, for the did-you-mean. */
2
+ export declare const API_KEYS_SUBCOMMANDS: readonly ["list", "create", "revoke"];
1
3
  export declare function apiKeysCommand(subcommand: string | undefined, rawArgs: string[]): Promise<void>;
2
4
  /** The flags `rebase api-keys create` takes. */
3
5
  export declare const CREATE_KEY_FLAGS: {
@@ -1 +1,3 @@
1
+ /** Everything the switch below dispatches, for the did-you-mean. */
2
+ export declare const APPS_SUBCOMMANDS: readonly ["list", "init", "config"];
1
3
  export declare function appsCommand(subcommand: string | undefined, rawArgs?: string[]): Promise<void>;
@@ -1,3 +1,5 @@
1
+ /** Everything the switch below dispatches, for the did-you-mean. */
2
+ export declare const AUTH_SUBCOMMANDS: readonly ["reset-password"];
1
3
  /** A user as the admin API returns it, reduced to what this command needs. */
2
4
  export interface ResolvedUser {
3
5
  id: string;
@@ -74,3 +76,13 @@ export declare function resolveResetPasswordArgs(rawArgs: string[]): {
74
76
  * hazard, and nothing that reads like a placeholder somebody might keep.
75
77
  */
76
78
  export declare function generatePassword(): string;
79
+ /**
80
+ * The script the direct-database fallback runs under the project's own tsx, so
81
+ * it resolves the project's `@rebasepro/server-postgres` and schema.
82
+ *
83
+ * It exits 0 only when a row was updated: a missing user and a thrown error are
84
+ * both exit 1. `echoPassword` prints the new password, for a generated one.
85
+ *
86
+ * Exported so its tests can run it.
87
+ */
88
+ export declare function resetPasswordScript(echoPassword: boolean): string;
@@ -33,5 +33,13 @@ export declare function buildCommand(rawArgs?: string[]): Promise<void>;
33
33
  * packages that output into a `static`-kind bundle — the same deployable shape as
34
34
  * a backend bundle, so a frontend or admin app deploys through the identical
35
35
  * path and runs on the identical image, just serving files instead of an API.
36
+ *
37
+ * Throws when the build fails or produces nothing usable, so the caller answers
38
+ * in its own way: `rebase build` with a red line, `rebase cloud deploy --json`
39
+ * with its JSON error.
36
40
  */
37
- export declare function buildAssetApp(projectRoot: string, name: string, app: RebaseAppConfig, runtimeRange: string, outOverride?: string): Promise<string | undefined>;
41
+ export declare function buildAssetApp(projectRoot: string, name: string, app: RebaseAppConfig, runtimeRange: string, outOverride?: string,
42
+ /** `quietStdout`: every line, the build command's included, goes to stderr. See `toolStdio`. */
43
+ options?: {
44
+ quietStdout?: boolean;
45
+ }): Promise<string | undefined>;
@@ -2,15 +2,44 @@ import type { RebaseBundleManifest } from "@rebasepro/types";
2
2
  import type { RebuildSource } from "./rebuild-source.js";
3
3
  /** Read and shallow-validate a built bundle's manifest. */
4
4
  export declare function readBundleManifest(bundleDir: string): RebaseBundleManifest;
5
+ /**
6
+ * The control plane's cap on an uploaded bundle: its `MAX_BUNDLE_BYTES`, which
7
+ * it checks before reading the body.
8
+ */
9
+ export declare const MAX_BUNDLE_UPLOAD_BYTES: number;
5
10
  /**
6
11
  * Tar a built bundle into a gzipped archive.
7
12
  *
8
- * `node_modules` is excluded on purpose: the bundle ships a `package.json`, and
9
- * the managed runtime installs the declared dependencies at boot. Uploading an
10
- * installed `node_modules` would bloat the archive and could carry a
11
- * platform-specific build that will not run on the runtime image.
13
+ * `node_modules` goes in only with `withModules`: a tree the build vendored for
14
+ * the runtime's platform is the point of vendoring, while one installed into a
15
+ * prebuilt bundle by hand was installed for whatever machine ran it.
16
+ */
17
+ export declare function packBundle(bundleDir: string, outPath: string, options?: {
18
+ withModules?: boolean;
19
+ }): Promise<void>;
20
+ /**
21
+ * Pack a bundle for upload — without `node_modules`, even a vendored tree.
22
+ *
23
+ * Vendoring exists so a pod untars and boots rather than spending 35-55s of
24
+ * every start in `npm install`, and a deploy did carry the tree for one night
25
+ * (c36ea4637). It is left out again because of what the control plane does
26
+ * with the archive: `GET /bundle/:projectId/:bundleId` reads the whole object
27
+ * into memory on every pod start, and a runtime rollout restarts every tenant's
28
+ * pods at once. Bundles it was sized against are a few hundred kB; a vendored
29
+ * one is tens of MB, up to the 100 MB cap — N pods starting together would hold
30
+ * N of them. A slower cold start per pod is the status quo every deploy has
31
+ * shipped with; a control plane out of memory is every tenant's outage. The
32
+ * platform's own rebuilds build with `--no-vendor` for the same shape of
33
+ * reason. When the control plane streams bundles, this is the one switch to
34
+ * flip, and `rebase cloud deploy` builds with `vendor: false` until then.
35
+ *
36
+ * `modulesLeftOut` says a tree the build DID vendor was not uploaded — a
37
+ * prebuilt `--bundle-dir` from a plain `rebase build`, which vendors by default.
12
38
  */
13
- export declare function packBundle(bundleDir: string, outPath: string): Promise<void>;
39
+ export declare function packBundleForUpload(bundleDir: string, outPath: string, manifest: RebaseBundleManifest, maxBytes?: number): Promise<{
40
+ bytes: number;
41
+ modulesLeftOut: boolean;
42
+ }>;
14
43
  /**
15
44
  * Assemble the deploy-trigger body for a bundle deploy.
16
45
  *
@@ -18,7 +18,26 @@ export declare function setContextOrg(url: string, org: string | undefined): voi
18
18
  export declare function getContextOrg(url: string): string | undefined;
19
19
  /** Mark a host as the active context (called on login). */
20
20
  export declare function setCurrentContext(url: string): void;
21
+ /**
22
+ * Where the control-plane URL came from. `link` is the one a repository chose
23
+ * rather than the user — see {@link isKnownControlPlane}.
24
+ */
25
+ export type CloudUrlSource = "flag" | "env" | "link" | "context" | "default";
21
26
  export declare function resolveCloudUrl(rawArgs: string[]): string;
27
+ /** The control-plane URL, and which rung of the ladder above supplied it. */
28
+ export declare function resolveCloudTarget(rawArgs: string[]): {
29
+ url: string;
30
+ source: CloudUrlSource;
31
+ };
32
+ /**
33
+ * Whether a control-plane host is one the user chose: the platform's own, or a
34
+ * host already in their credentials file because they signed in to it.
35
+ *
36
+ * A link file is part of the repository, and a cloned repository is not the
37
+ * user's to trust with their password. `login` asks before sending one to a
38
+ * linked host that is neither.
39
+ */
40
+ export declare function isKnownControlPlane(url: string): boolean;
22
41
  /**
23
42
  * Refuse to run a control-plane command in a directory linked straight at a
24
43
  * backend.
@@ -40,6 +59,30 @@ export type CloudClient = ReturnType<typeof createRebaseClient>;
40
59
  * by `requireClient`.
41
60
  */
42
61
  export declare function createCloudClient(url: string): CloudClient;
62
+ /** The half of a client that holds its session — all {@link freshAccessToken} reads. */
63
+ export interface SessionHolder {
64
+ auth: {
65
+ getSession(): {
66
+ accessToken: string;
67
+ expiresAt: number;
68
+ } | null;
69
+ refreshSession(): Promise<{
70
+ accessToken: string;
71
+ }>;
72
+ };
73
+ }
74
+ /**
75
+ * An access token with time left on it, refreshed first if it is close to
76
+ * expiry. Rejects when there is no session, or it cannot be refreshed.
77
+ *
78
+ * For the requests the SDK does not make itself. Its own calls refresh and
79
+ * retry on a 401; a raw `fetch` or a tunnel handshake presents whatever token
80
+ * it was handed, and `createCloudClient` never refreshes in the background. A
81
+ * token read once at the start of a command that runs for longer than it
82
+ * lives — a deploy's build, a `db connect` left open — is refused by the time
83
+ * it is used, so it is read here at the moment it is sent.
84
+ */
85
+ export declare function freshAccessToken(client: SessionHolder): Promise<string>;
43
86
  /**
44
87
  * Return an authenticated client for the resolved host, refreshing the access
45
88
  * token if it is close to expiry. Exits with a helpful message when there is no
@@ -32,6 +32,7 @@
32
32
  * unreachable from a browser too.
33
33
  */
34
34
  import net from "node:net";
35
+ import { type SessionHolder } from "./context.js";
35
36
  /** Documented in `action-help.ts`, and paired with it by `action-help.test.ts`. */
36
37
  export declare const DB_CONNECT_FLAGS: {
37
38
  readonly "--port": NumberConstructor;
@@ -53,6 +54,20 @@ export declare function localDsn(opts: {
53
54
  password?: string;
54
55
  }): string;
55
56
  export declare function dbConnect(rawArgs: string[]): Promise<void>;
57
+ /**
58
+ * The local listener: each connection it accepts gets its own tunnel, signed in
59
+ * with a token that is current when the connection arrives.
60
+ *
61
+ * The command is left running for as long as the developer works, and the
62
+ * access token it started with lapses within the hour. Every connection is
63
+ * authenticated on its own, so each one reads the token then, refreshing it
64
+ * first when it is close to expiry — rather than the one read at startup, which
65
+ * the control plane refuses for every connection opened after it expires.
66
+ *
67
+ * The socket is paused while the token is read, so a client's first bytes wait
68
+ * for the tunnel exactly as they do once it is being established.
69
+ */
70
+ export declare function tunnelListener(client: SessionHolder, endpoint: string): net.Server;
56
71
  /**
57
72
  * One accepted connection, carried over one WebSocket.
58
73
  *
@@ -59,8 +59,22 @@ export declare function timeAgo(value: string | Date | undefined, now: Date): st
59
59
  * path.
60
60
  */
61
61
  export declare function isManagedProject(project: DeployProjectRow | undefined, latest: DeploySourceRow | undefined): boolean;
62
- /** What a `deploy` with nothing attached will build, in the words to print. */
63
- export declare function planBareDeploy(project: DeployProjectRow | undefined, latest: DeploySourceRow | undefined, now: Date): BareDeployPlan;
62
+ /**
63
+ * The deployment whose uploaded archive a bare deploy rebuilds, if any.
64
+ *
65
+ * The control plane's own rule (`reusableSourceRef`, over the newest 25 rows):
66
+ * the newest row, by its own `createdAt`, carrying a build-context ref. Not the
67
+ * newest row — a rollback or a bundle deploy carries none, and the upload
68
+ * rebuilt then is the one before it.
69
+ */
70
+ export declare function snapshotDeployment(recent: readonly DeploySourceRow[]): DeploySourceRow | undefined;
71
+ /**
72
+ * What a `deploy` with nothing attached will build, in the words to print.
73
+ *
74
+ * `recent` is the project's newest deployments, newest first — the same page
75
+ * the control plane reads to choose an archive.
76
+ */
77
+ export declare function planBareDeploy(project: DeployProjectRow | undefined, recent: readonly DeploySourceRow[], now: Date): BareDeployPlan;
64
78
  /**
65
79
  * A warning attached to a deploy: printed for the human, carried in the JSON.
66
80
  *
@@ -186,6 +200,8 @@ export declare const DEPLOY_FLAGS: {
186
200
  readonly "--bundle": BooleanConstructor;
187
201
  readonly "--bundle-dir": StringConstructor;
188
202
  readonly "--skip-type-check": BooleanConstructor;
203
+ readonly "--no-static": BooleanConstructor;
204
+ readonly "--skip-schema": BooleanConstructor;
189
205
  readonly "--eject": BooleanConstructor;
190
206
  readonly "--no-source": BooleanConstructor;
191
207
  readonly "--allow-downgrade": BooleanConstructor;
@@ -223,6 +239,8 @@ export declare function resolveDeployArgs(rawArgs: string[]): {
223
239
  readonly "--bundle": BooleanConstructor;
224
240
  readonly "--bundle-dir": StringConstructor;
225
241
  readonly "--skip-type-check": BooleanConstructor;
242
+ readonly "--no-static": BooleanConstructor;
243
+ readonly "--skip-schema": BooleanConstructor;
226
244
  readonly "--eject": BooleanConstructor;
227
245
  readonly "--no-source": BooleanConstructor;
228
246
  readonly "--allow-downgrade": BooleanConstructor;
@@ -290,6 +308,41 @@ export declare function deployedUrl(client: CloudClient, opts: {
290
308
  projectId?: string;
291
309
  url?: string;
292
310
  }): Promise<string | undefined>;
311
+ /**
312
+ * The line an in-progress build keeps rewriting at the end of its log, to prove
313
+ * to the control plane that it is still alive.
314
+ *
315
+ * The control plane's own format — `HEARTBEAT_MARKER` and `heartbeatSuffix` in
316
+ * its `functions/deploy.ts` — which appends `\n<marker><ISO time>\n` to the log
317
+ * on every write and every 30 seconds, and drops it on the terminal write.
318
+ */
319
+ export declare const BUILD_HEARTBEAT_MARKER = "\u23F3 Build in progress \u2014 control-plane heartbeat ";
320
+ /**
321
+ * A deployment's log without its trailing heartbeat line: the build log itself.
322
+ *
323
+ * Only a heartbeat that is the last line is one. The same text anywhere else is
324
+ * the build quoting it.
325
+ */
326
+ export declare function withoutHeartbeat(logs: string): string;
327
+ /**
328
+ * What to print of a deployment's log, given everything printed so far.
329
+ *
330
+ * The `logs` column is not append-only. Its heartbeat line is rewritten at the
331
+ * end on every write, and a failed static deploy replaces its whole log with
332
+ * one line. Diffing the raw column by length therefore cut the start off every
333
+ * new chunk — as many characters as the heartbeat that had been there — and
334
+ * printed heartbeat fragments in their place: a failed managed deploy lost the
335
+ * first half of its reason.
336
+ *
337
+ * So the heartbeat is stripped first, and the log printed so far is compared
338
+ * with the log now. When it has only grown, the new text is printed. When it
339
+ * was rewritten, printing resumes from the start of the first line that
340
+ * differs, on a line of its own.
341
+ */
342
+ export declare function nextLogChunk(printed: string, rowLogs: string): {
343
+ chunk: string;
344
+ printed: string;
345
+ };
293
346
  /** What `rebase cloud logs` parses. Its page pairs against this. */
294
347
  export declare const LOGS_FLAGS: {
295
348
  readonly "--runtime": BooleanConstructor;
@@ -1,11 +1,11 @@
1
1
  export declare function domainsCommand(action: string | undefined, rawArgs: string[]): Promise<void>;
2
2
  /**
3
- * The domain `domains add` was asked to register.
3
+ * The domain an action was given, or undefined.
4
4
  *
5
5
  * Exported so its tests drive the real parser. Under the old operand filter
6
6
  * `rebase cloud domains add -p acme` registered a domain called "acme" — the
7
7
  * project slug, read out of `--project`'s own value — and a registered domain
8
8
  * is a project-record write, not a no-op.
9
9
  */
10
- export declare function resolveDomainArg(rawArgs: string[]): string | undefined;
10
+ export declare function resolveDomainArg(rawArgs: string[], action?: string): string | undefined;
11
11
  export declare function printDomainsHelp(): void;
@@ -57,4 +57,18 @@ export declare function resolveEnvSetArgs(rawArgs: string[]): {
57
57
  * count of command words is the same for all of them.
58
58
  */
59
59
  export declare function resolveEnvKeyArg(rawArgs: string[], action: string): string | undefined;
60
+ /**
61
+ * One `KEY=value` line that dotenv reads back as exactly `value`, or null when
62
+ * no quoting can carry it.
63
+ *
64
+ * dotenv's quoting is not JSON's, and `JSON.stringify` was what this used: a
65
+ * double-quoted value has only `\n` and `\r` unescaped, so every other
66
+ * backslash stayed and `{"a":1}` came back as `{\"a\":1}`. Single quotes and
67
+ * backticks are literal — nothing inside is unescaped, and either may span
68
+ * lines — so they carry any value without their own quote character. Double
69
+ * quotes come last: they cannot hold a `"` or a literal backslash-n, and they
70
+ * are the only way to carry a carriage return, which dotenv folds into a
71
+ * newline everywhere else.
72
+ */
73
+ export declare function dotenvLine(key: string, value: string): string | null;
60
74
  export declare function printEnvHelp(): void;
@@ -14,6 +14,12 @@ export declare const MAX_SOURCE_UPLOAD_BYTES: number;
14
14
  * bundles are never source. Every `.env` and `.env.*` is excluded except the
15
15
  * three template names, and so is direnv's `.envrc`, which is the same thing
16
16
  * under another name.
17
+ *
18
+ * So is what the CLI keeps on this machine: `.rebase/`, which holds the
19
+ * development database, and the `.rebase-dev-*` files beside it, one of which
20
+ * is the development signing secrets. And so is a `*.dump`, which is what
21
+ * `rebase db backup` writes: every row of the database, `rebase.users`
22
+ * password hashes included.
17
23
  */
18
24
  export declare function neverUploaded(relativePath: string): boolean;
19
25
  export interface SourceListing {
@@ -45,6 +51,21 @@ export type GitRunner = (cwd: string, args: string[]) => string;
45
51
  * archive with `../`.
46
52
  */
47
53
  export declare function listSourceFiles(projectRoot: string, git?: GitRunner): SourceListing;
54
+ /**
55
+ * The files of a `--source` build context: `dir` and what is under it, relative
56
+ * to it, POSIX, sorted.
57
+ *
58
+ * The same rules as the rebuild source — git decides, and {@link neverUploaded}
59
+ * after it — restricted to `dir`, which is the context's root, so a Dockerfile
60
+ * in it still reads its paths from there. A `dir` that is a subfolder of a
61
+ * repository is held to that repository's `.gitignore`, which is where a
62
+ * monorepo keeps it.
63
+ *
64
+ * `.rebaseignore` in `dir` leaves out more, read with `.gitignore` syntax and
65
+ * anchored at `dir`. It needs git to be read, like `.gitignore` outside a
66
+ * repository; without git, a context that has one is refused.
67
+ */
68
+ export declare function listContextFiles(dir: string, git?: GitRunner): string[];
48
69
  /**
49
70
  * Pack a listing into a gzipped tarball at `outPath`.
50
71
  *
@@ -54,7 +75,7 @@ export declare function listSourceFiles(projectRoot: string, git?: GitRunner): S
54
75
  * archive, as `packBundle` does; GNU tar accepts both. Every path handed to tar
55
76
  * is absolute, because GNU tar resolves a `-T` file after it has applied `-C`.
56
77
  */
57
- export declare function packSource(listing: SourceListing, outPath: string): Promise<void>;
78
+ export declare function packSource(listing: Pick<SourceListing, "root" | "files">, outPath: string): Promise<void>;
58
79
  /** Upload a source archive; returns the control plane's id for it. */
59
80
  export declare function uploadRebuildSource(url: string, token: string, projectId: string, tarPath: string): Promise<string>;
60
81
  /**
@@ -100,7 +121,8 @@ export interface RebuildSourceSteps {
100
121
  export declare function prepareRebuildSource(opts: {
101
122
  projectRoot: string;
102
123
  url: string;
103
- token: string;
124
+ /** The access token, read when the upload is sent rather than before the packing. */
125
+ token: () => Promise<string>;
104
126
  projectId: string;
105
127
  manifest?: RebaseProjectManifest;
106
128
  progress: (line: string) => void;
@@ -157,6 +157,8 @@ export declare function runDriverDbCommand(rawArgs: string[], options?: {
157
157
  quiet?: boolean;
158
158
  }): Promise<void>;
159
159
  export declare function dbCommand(subcommand: string | undefined, rawArgs: string[]): Promise<void>;
160
+ /** Every subcommand the family dispatches — the help table's keys. */
161
+ export declare const DB_SUBCOMMANDS: string[];
160
162
  /**
161
163
  * The examples, which are not the same on the managed development database.
162
164
  *
@@ -1 +1,3 @@
1
1
  export declare function schemaCommand(subcommand: string | undefined, rawArgs: string[]): Promise<void>;
2
+ /** Every subcommand the family dispatches — the help table's keys. */
3
+ export declare const SCHEMA_SUBCOMMANDS: string[];
@@ -141,6 +141,8 @@ export declare function installForAgent(agentKey: AgentKey, skills: LoadedSkill[
141
141
  skills: number;
142
142
  assets: number;
143
143
  };
144
+ /** Everything the switch below dispatches, for the did-you-mean. */
145
+ export declare const SKILLS_SUBCOMMANDS: readonly ["install"];
144
146
  export declare function skillsCommand(subcommand: string | undefined, rawArgs: string[]): Promise<void>;
145
147
  /**
146
148
  * Agents named explicitly on the command line, e.g. `--agent claude --agent cursor`
@@ -1 +1,11 @@
1
+ /**
2
+ * `rebase telemetry` — the command that makes the rest of it inspectable.
3
+ *
4
+ * The whole subsystem asks for trust it cannot otherwise earn, and the cheapest
5
+ * way to earn it is to stop describing the payload and print it. `show` runs
6
+ * the same builder the sender uses, so what appears here is what would go, not
7
+ * a documentation comment that quietly fell out of date two releases ago.
8
+ */
9
+ /** Everything the switch below dispatches, for the did-you-mean. */
10
+ export declare const TELEMETRY_SUBCOMMANDS: readonly ["status", "show", "enable", "disable"];
1
11
  export declare function telemetryCommand(rawArgs: string[]): Promise<void>;
@@ -116,5 +116,34 @@ export declare function dumpArgs(plan: PullPlan): string[];
116
116
  * them. `--no-owner` for the same reason as the dump.
117
117
  */
118
118
  export declare function restoreArgs(plan: PullPlan, dumpFile: string): string[];
119
- /** Is `pg_dump` on PATH, and what version? Checked before anything destructive. */
120
- export declare function findPgDump(): Promise<string | null>;
119
+ /**
120
+ * Is this PostgreSQL client tool on PATH, and what version? Both are checked
121
+ * before anything destructive: discovering `pg_restore` is missing after the
122
+ * dump has been taken — or after `--clean` has emptied the target — is the
123
+ * worst possible ordering.
124
+ */
125
+ export declare function findPgTool(tool: "pg_dump" | "pg_restore"): Promise<string | null>;
126
+ /** The fields of a finished `pg_restore` run that decide {@link restoreOutcome}. */
127
+ export interface RestoreRun {
128
+ exitCode?: number;
129
+ signal?: string;
130
+ /** A spawn failure's code — `ENOENT` when the binary vanished. */
131
+ code?: string;
132
+ stderr?: string;
133
+ }
134
+ /**
135
+ * What a finished `pg_restore` says about the copy.
136
+ *
137
+ * `--clean` empties the target before anything is written, so every way this
138
+ * can end short of exit 0 leaves a partial or empty local database, and none of
139
+ * them may be reported as a copy. A non-zero exit is pg_restore saying it
140
+ * skipped statements — "errors ignored on restore: N" — and whatever those
141
+ * statements created (a table, its rows, an RLS policy) is missing locally.
142
+ *
143
+ * `started` says whether anything can have arrived, which is what decides
144
+ * whether an anonymization pass still has data to redact.
145
+ */
146
+ export declare function restoreOutcome(run: RestoreRun): {
147
+ started: boolean;
148
+ failure: string | null;
149
+ };
@@ -13,7 +13,7 @@
13
13
  * 2. `DATABASE_URL` in the shell environment
14
14
  * 3. the database branch this checkout is switched to
15
15
  * 4. `DATABASE_URL` in the project's `.env`
16
- * 5. `--docker` / a manifest preference of `docker`
16
+ * 5. `--docker`
17
17
  * 6. the managed PGlite database
18
18
  *
19
19
  * An explicit connection string always wins. That is the whole point of the
@@ -44,7 +44,7 @@ export type DevDatabaseSource =
44
44
  | "env-file"
45
45
  /** The branch this checkout is switched to, over the base connection. */
46
46
  | "branch"
47
- /** `--docker`, or `devDatabase: "docker"` in the manifest. */
47
+ /** `--docker`. */
48
48
  | "docker"
49
49
  /** Nobody said anything, so the managed database fills in. */
50
50
  | "managed";
@@ -79,8 +79,6 @@ export interface ResolveDevDatabaseInput {
79
79
  env?: Record<string, string | undefined>;
80
80
  /** Parsed `.env` from the project root. Only `DATABASE_URL` is read. */
81
81
  envFile?: Record<string, string> | null;
82
- /** `devDatabase` from `rebase.json`, if the project recorded a preference. */
83
- manifestPreference?: "managed" | "docker" | null;
84
82
  /**
85
83
  * The compose `db` service's connection string, when the project has one.
86
84
  *
@@ -17,6 +17,8 @@ export interface FoldOptions {
17
17
  /** Skip running each app's own build command; fold what is already built. */
18
18
  skipBuild?: boolean;
19
19
  log?: (message: string) => void;
20
+ /** Send each app's build output to stderr: the caller's stdout carries a result. See `toolStdio`. */
21
+ quietStdout?: boolean;
20
22
  }
21
23
  export interface FoldOutcome {
22
24
  appName: string;