@rebasepro/cli 0.9.1-canary.742f831 → 0.9.1-canary.78ab3dc
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 +67 -1
- package/dist/commands/cloud/context.d.ts +0 -6
- package/dist/commands/cloud/debug.d.ts +117 -0
- package/dist/commands/cloud/deployments.d.ts +0 -1
- package/dist/commands/cloud/power.d.ts +0 -1
- package/dist/commands/cloud/resources.d.ts +1 -1
- package/dist/commands/init.d.ts +12 -0
- package/dist/index.es.js +937 -8
- package/dist/index.es.js.map +1 -1
- package/package.json +9 -8
- package/templates/template/docker-compose.yml +7 -0
package/bin/rebase.js
CHANGED
|
@@ -1,4 +1,70 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { existsSync, readdirSync, statSync } from "node:fs";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
|
|
6
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
const distEntry = join(here, "..", "dist", "index.es.js");
|
|
8
|
+
const srcDir = join(here, "..", "src");
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Warn when the built CLI is older than the source it was built from.
|
|
12
|
+
*
|
|
13
|
+
* `rebase` runs `dist/`, and a global install of this package is usually a
|
|
14
|
+
* symlink to a working checkout — so every agent and shell on the machine runs
|
|
15
|
+
* whatever was last built, not what is in the code. A stale build is invisible:
|
|
16
|
+
* the command works, it just silently lacks the subcommand you added, which
|
|
17
|
+
* reads as "my change did nothing" rather than "you forgot to build".
|
|
18
|
+
*
|
|
19
|
+
* Development-only by construction: `src/` is not in the published `files`
|
|
20
|
+
* list, so this is skipped entirely for installed copies.
|
|
21
|
+
*
|
|
22
|
+
* Writes to **stderr**. Agents parse stdout as JSON under `--json`, and a
|
|
23
|
+
* warning there would corrupt the one guarantee those commands make.
|
|
24
|
+
*/
|
|
25
|
+
function newestMtimeMs(dir, deadline) {
|
|
26
|
+
let newest = 0;
|
|
27
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
28
|
+
if (Date.now() > deadline) break; // never let a warning cost real time
|
|
29
|
+
if (entry.name === "node_modules" || entry.name.startsWith(".")) continue;
|
|
30
|
+
const full = join(dir, entry.name);
|
|
31
|
+
if (entry.isDirectory()) {
|
|
32
|
+
newest = Math.max(newest, newestMtimeMs(full, deadline));
|
|
33
|
+
} else if (/\.tsx?$/.test(entry.name) && !/\.(test|spec)\.tsx?$/.test(entry.name)) {
|
|
34
|
+
// Tests are not bundled, so editing one does not make dist stale.
|
|
35
|
+
// Counting them cried wolf on the ordinary edit-test-run loop.
|
|
36
|
+
newest = Math.max(newest, statSync(full).mtimeMs);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return newest;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function warnIfStale() {
|
|
43
|
+
if (!existsSync(srcDir) || !existsSync(distEntry)) return;
|
|
44
|
+
const builtAt = statSync(distEntry).mtimeMs;
|
|
45
|
+
const editedAt = newestMtimeMs(srcDir, Date.now() + 150);
|
|
46
|
+
// A couple of seconds of slack: a build writes dist while src is being
|
|
47
|
+
// stat'd, and a sub-second delta is that race, not a stale build.
|
|
48
|
+
const staleByMs = editedAt - builtAt;
|
|
49
|
+
if (staleByMs <= 2000) return;
|
|
50
|
+
|
|
51
|
+
const seconds = Math.round(staleByMs / 1000);
|
|
52
|
+
const ago = seconds >= 3600
|
|
53
|
+
? `${Math.round(seconds / 3600)}h`
|
|
54
|
+
: seconds >= 60 ? `${Math.round(seconds / 60)}m` : `${seconds}s`;
|
|
55
|
+
process.stderr.write(
|
|
56
|
+
`[33m⚠ rebase CLI: dist/ is ${ago} older than src/ — you are running a stale build.[0m\n` +
|
|
57
|
+
` Rebuild with: (cd ${join(here, "..")} && npm run build)\n`
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// A broken staleness check must never stop the CLI from running.
|
|
62
|
+
try {
|
|
63
|
+
warnIfStale();
|
|
64
|
+
} catch {
|
|
65
|
+
/* ignore */
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const { entry } = await import("../dist/index.es.js");
|
|
3
69
|
|
|
4
70
|
entry(process.argv);
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
import { createRebaseClient } from "@rebasepro/client";
|
|
2
|
-
/** Default hosted control plane (the Rebase Cloud console origin). */
|
|
3
|
-
export declare const DEFAULT_CLOUD_URL = "https://app.rebase.pro";
|
|
4
2
|
/** Project-local link file: <project>/.rebase/cloud.json */
|
|
5
3
|
export declare function projectLinkPath(cwd?: string): string;
|
|
6
|
-
/** Host that a bare `rebase cloud` command should target, if any. */
|
|
7
|
-
export declare function currentContextUrl(): string | undefined;
|
|
8
4
|
/** Persist the active organization id for a host. */
|
|
9
5
|
export declare function setContextOrg(url: string, org: string | undefined): void;
|
|
10
6
|
export declare function getContextOrg(url: string): string | undefined;
|
|
@@ -104,8 +100,6 @@ export declare function initOutputMode(rawArgs: string[]): boolean;
|
|
|
104
100
|
export declare function isJsonMode(): boolean;
|
|
105
101
|
/** Force the mode (tests only — production latches it via `initOutputMode`). */
|
|
106
102
|
export declare function setJsonModeForTest(value: boolean): void;
|
|
107
|
-
/** Write one JSON value to stdout, followed by a newline. */
|
|
108
|
-
export declare function printJson(value: unknown): void;
|
|
109
103
|
/**
|
|
110
104
|
* The one output primitive every new command uses: in JSON mode emit `json`
|
|
111
105
|
* (and nothing else); otherwise run `human`. Keeping the two behind a single
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/** How a probe's outcome should be read. */
|
|
2
|
+
export type Verdict =
|
|
3
|
+
/** Behaving as a healthy deployment should. */
|
|
4
|
+
"ok"
|
|
5
|
+
/** Reachable and legal, but worth a human look (e.g. a public read). */
|
|
6
|
+
| "warn"
|
|
7
|
+
/** Broken, or wired up wrong. */
|
|
8
|
+
| "fail"
|
|
9
|
+
/** We could not classify the response. */
|
|
10
|
+
| "unknown";
|
|
11
|
+
export interface ProbeReading {
|
|
12
|
+
verdict: Verdict;
|
|
13
|
+
/** What this status code *means for this endpoint*, in one sentence. */
|
|
14
|
+
meaning: string;
|
|
15
|
+
}
|
|
16
|
+
export interface ProbeSpec {
|
|
17
|
+
id: string;
|
|
18
|
+
/** Column label in human output. */
|
|
19
|
+
label: string;
|
|
20
|
+
method: "GET" | "POST";
|
|
21
|
+
/** Path relative to the project origin. */
|
|
22
|
+
path: (opts: ProbeTargets) => string;
|
|
23
|
+
body?: unknown;
|
|
24
|
+
/** One-line statement of what a healthy deployment answers here. */
|
|
25
|
+
healthy: string;
|
|
26
|
+
interpret: (status: number | null) => ProbeReading;
|
|
27
|
+
/**
|
|
28
|
+
* Read the response body as well. Set only where the body carries a fact the
|
|
29
|
+
* status code cannot — today, the function listing.
|
|
30
|
+
*/
|
|
31
|
+
needsBody?: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Sharpen the status-code reading using the parsed body. Returning null
|
|
34
|
+
* keeps {@link interpret}'s verdict.
|
|
35
|
+
*/
|
|
36
|
+
refine?: (body: unknown, targets: ProbeTargets) => ProbeReading | null;
|
|
37
|
+
}
|
|
38
|
+
export interface ProbeTargets {
|
|
39
|
+
/** Collection used for the unauthenticated-read probe. */
|
|
40
|
+
collection: string;
|
|
41
|
+
/** Function to confirm exists, if the caller named one. */
|
|
42
|
+
fn?: string;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The probe set, in the order a failure cascades: if `health` is down, nothing
|
|
46
|
+
* below it is meaningful, so it is checked first and reported first.
|
|
47
|
+
*/
|
|
48
|
+
export declare const PROBES: ProbeSpec[];
|
|
49
|
+
/** The function names out of a listing body, or null when it is not one. */
|
|
50
|
+
export declare function functionNames(body: unknown): string[] | null;
|
|
51
|
+
export interface ProbeResult {
|
|
52
|
+
id: string;
|
|
53
|
+
label: string;
|
|
54
|
+
method: string;
|
|
55
|
+
url: string;
|
|
56
|
+
status: number | null;
|
|
57
|
+
ms: number;
|
|
58
|
+
verdict: Verdict;
|
|
59
|
+
meaning: string;
|
|
60
|
+
healthy: string;
|
|
61
|
+
/**
|
|
62
|
+
* Whether the STATUS CODE alone looked healthy. False means the code itself
|
|
63
|
+
* was wrong; true with a failing `verdict` means the code was fine and the
|
|
64
|
+
* body carried the bad news (a named function that did not load). The
|
|
65
|
+
* summary uses this so it never tells you to expect a 200 you already got.
|
|
66
|
+
*/
|
|
67
|
+
statusOk: boolean;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Run one probe. A transport failure is a `null` status, never a thrown error:
|
|
71
|
+
* "nothing answered" is a diagnosis in its own right and the other probes still
|
|
72
|
+
* need to run.
|
|
73
|
+
*/
|
|
74
|
+
export declare function runProbe(origin: string, spec: ProbeSpec, targets: ProbeTargets): Promise<ProbeResult>;
|
|
75
|
+
/** The worst verdict across probes — what the command's exit code keys off. */
|
|
76
|
+
export declare function overallVerdict(results: ProbeResult[]): Verdict;
|
|
77
|
+
export interface ParsedLogLine {
|
|
78
|
+
ts: string | null;
|
|
79
|
+
pod: string | null;
|
|
80
|
+
text: string;
|
|
81
|
+
}
|
|
82
|
+
export declare function parseLogLine(line: string): ParsedLogLine;
|
|
83
|
+
/**
|
|
84
|
+
* Lines an operator scanning for a fault wants to see.
|
|
85
|
+
*
|
|
86
|
+
* Matches the structured `severity` field first, then the shapes that show up
|
|
87
|
+
* in unstructured output. `refus`/`denied` are in the list because a permission
|
|
88
|
+
* failure often logs at info level and is exactly what one is hunting for.
|
|
89
|
+
*/
|
|
90
|
+
export declare function isErrorLine(text: string): boolean;
|
|
91
|
+
export interface RequestLogEntry {
|
|
92
|
+
status: number | null;
|
|
93
|
+
method: string;
|
|
94
|
+
path: string;
|
|
95
|
+
latencyMs: number | null;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Pull an HTTP request record out of a log line, or null when it is not one.
|
|
99
|
+
*
|
|
100
|
+
* Only structured request lines are recognised. Guessing at prose would produce
|
|
101
|
+
* a table with invented columns, which is worse than a short one.
|
|
102
|
+
*/
|
|
103
|
+
export declare function parseRequestLine(text: string): RequestLogEntry | null;
|
|
104
|
+
/**
|
|
105
|
+
* Startup lines: what the server *decided* it was going to do. Which storage
|
|
106
|
+
* backend it bound, which functions it loaded, whether auth tables were found.
|
|
107
|
+
* This is the fastest way to tell a misconfiguration from a runtime fault.
|
|
108
|
+
*/
|
|
109
|
+
export declare function isBootLine(text: string): boolean;
|
|
110
|
+
/** Render a number of seconds back as the compact duration a user would type. */
|
|
111
|
+
export declare function formatDuration(seconds: number): string;
|
|
112
|
+
/**
|
|
113
|
+
* Parse a duration like `15m`, `2h`, `90s`, `1d` (or a bare number of seconds)
|
|
114
|
+
* into seconds. Returns null when it is not a duration.
|
|
115
|
+
*/
|
|
116
|
+
export declare function parseSince(input: string | undefined): number | null;
|
|
117
|
+
export declare function debugCommand(action: string | undefined, rawArgs: string[]): Promise<void>;
|
|
@@ -19,7 +19,6 @@ export interface DeploymentRow {
|
|
|
19
19
|
gitCommitHash?: string;
|
|
20
20
|
gitCommitMessage?: string;
|
|
21
21
|
}
|
|
22
|
-
export declare function deploymentImage(dep: DeploymentRow): string | null;
|
|
23
22
|
/**
|
|
24
23
|
* The backend's rule EXACTLY: a rollback is honoured only for a successful
|
|
25
24
|
* deploy that recorded an image. Any other row 409s `deploy_not_rollbackable`.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export declare function statusCommand(rawArgs: string[]): Promise<void>;
|
|
2
2
|
export declare function metricsCommand(rawArgs: string[]): Promise<void>;
|
|
3
3
|
export declare function webhooksCommand(subcommand: string | undefined, rawArgs: string[]): Promise<void>;
|
|
4
|
-
export declare function storageCommand(rawArgs: string[]): Promise<void>;
|
|
4
|
+
export declare function storageCommand(action: string | undefined, rawArgs: string[]): Promise<void>;
|
|
5
5
|
export declare function clustersCommand(rawArgs: string[]): Promise<void>;
|
|
6
6
|
export declare function billingCommand(rawArgs: string[]): Promise<void>;
|
package/dist/commands/init.d.ts
CHANGED
|
@@ -24,6 +24,8 @@ export interface InitOptions {
|
|
|
24
24
|
introspect?: boolean;
|
|
25
25
|
/** Starter template preset. */
|
|
26
26
|
preset: TemplatePreset;
|
|
27
|
+
/** Whether `preset` came from an explicit --template rather than the default. */
|
|
28
|
+
explicitPreset?: boolean;
|
|
27
29
|
/** Which parts of Rebase to scaffold. */
|
|
28
30
|
flavor: TemplateFlavor;
|
|
29
31
|
/** Detected package manager (pnpm or npm). */
|
|
@@ -51,5 +53,15 @@ export interface BuildQuestionsParams {
|
|
|
51
53
|
* types registered by the installed version of inquirer.
|
|
52
54
|
*/
|
|
53
55
|
export declare function buildInitQuestions(params: BuildQuestionsParams): Record<string, unknown>[];
|
|
56
|
+
/**
|
|
57
|
+
* The `cd` a user must type to enter the new project.
|
|
58
|
+
*
|
|
59
|
+
* Not the project's basename: `init apps/my-app` has to say `cd apps/my-app`,
|
|
60
|
+
* and `init .` returns "" because they are already in the project.
|
|
61
|
+
*/
|
|
62
|
+
export declare function formatCdTarget(cwd: string, targetDirectory: string): string;
|
|
63
|
+
/** Help for `rebase init` — the flags were previously only discoverable by
|
|
64
|
+
* triggering the non-TTY error. */
|
|
65
|
+
export declare function printInitHelp(): void;
|
|
54
66
|
export declare function createRebaseApp(rawArgs: string[]): Promise<void>;
|
|
55
67
|
export declare function configureEnvFile(targetDirectory: string, databaseUrl?: string): Promise<void>;
|