@rebasepro/cli 0.9.1-canary.c0d4c07 → 0.9.1-canary.d906fb7
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 +1 -67
- package/dist/commands/cloud/context.d.ts +6 -0
- package/dist/commands/cloud/deployments.d.ts +1 -0
- package/dist/commands/cloud/power.d.ts +1 -0
- package/dist/commands/cloud/resources.d.ts +1 -1
- package/dist/commands/skills.d.ts +1 -1
- package/dist/index.es.js +39 -223
- package/dist/index.es.js.map +1 -1
- package/dist/utils/package-manager.d.ts +5 -19
- package/package.json +7 -7
- package/templates/overlays/baas/backend/package.json +1 -1
- package/templates/overlays/baas/backend/tsconfig.json +1 -2
- package/templates/template/backend/src/env.ts +1 -30
- package/templates/template/config/collections/users.ts +0 -2
package/bin/rebase.js
CHANGED
|
@@ -1,70 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
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");
|
|
2
|
+
import { entry } from "../dist/index.es.js";
|
|
69
3
|
|
|
70
4
|
entry(process.argv);
|
|
@@ -1,6 +1,10 @@
|
|
|
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";
|
|
2
4
|
/** Project-local link file: <project>/.rebase/cloud.json */
|
|
3
5
|
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;
|
|
4
8
|
/** Persist the active organization id for a host. */
|
|
5
9
|
export declare function setContextOrg(url: string, org: string | undefined): void;
|
|
6
10
|
export declare function getContextOrg(url: string): string | undefined;
|
|
@@ -100,6 +104,8 @@ export declare function initOutputMode(rawArgs: string[]): boolean;
|
|
|
100
104
|
export declare function isJsonMode(): boolean;
|
|
101
105
|
/** Force the mode (tests only — production latches it via `initOutputMode`). */
|
|
102
106
|
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;
|
|
103
109
|
/**
|
|
104
110
|
* The one output primitive every new command uses: in JSON mode emit `json`
|
|
105
111
|
* (and nothing else); otherwise run `human`. Keeping the two behind a single
|
|
@@ -19,6 +19,7 @@ export interface DeploymentRow {
|
|
|
19
19
|
gitCommitHash?: string;
|
|
20
20
|
gitCommitMessage?: string;
|
|
21
21
|
}
|
|
22
|
+
export declare function deploymentImage(dep: DeploymentRow): string | null;
|
|
22
23
|
/**
|
|
23
24
|
* The backend's rule EXACTLY: a rollback is honoured only for a successful
|
|
24
25
|
* 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(
|
|
4
|
+
export declare function storageCommand(rawArgs: string[]): Promise<void>;
|
|
5
5
|
export declare function clustersCommand(rawArgs: string[]): Promise<void>;
|
|
6
6
|
export declare function billingCommand(rawArgs: string[]): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare function skillsCommand(subcommand: string | undefined,
|
|
1
|
+
export declare function skillsCommand(subcommand: string | undefined, _args: string[]): Promise<void>;
|
package/dist/index.es.js
CHANGED
|
@@ -9,8 +9,8 @@ import { execa, execaCommandSync } from "execa";
|
|
|
9
9
|
import { cp } from "fs/promises";
|
|
10
10
|
import { fileURLToPath } from "url";
|
|
11
11
|
import crypto from "crypto";
|
|
12
|
-
import { execSync, spawn, spawnSync } from "child_process";
|
|
13
12
|
import os from "os";
|
|
13
|
+
import { execSync, spawn } from "child_process";
|
|
14
14
|
import { createRebaseClient } from "@rebasepro/client";
|
|
15
15
|
import { generateSDK } from "@rebasepro/codegen";
|
|
16
16
|
import { createRequire } from "module";
|
|
@@ -23,45 +23,28 @@ import { createRequire } from "module";
|
|
|
23
23
|
* the rest of the CLI never has to hardcode a specific PM.
|
|
24
24
|
*/
|
|
25
25
|
/**
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* Used to decide whether a fresh project can be scaffolded with pnpm. Kept
|
|
29
|
-
* cheap and non-interactive (short timeout, output discarded) so it never
|
|
30
|
-
* hangs detection if a corepack shim misbehaves.
|
|
31
|
-
*/
|
|
32
|
-
function isPnpmAvailable() {
|
|
33
|
-
try {
|
|
34
|
-
return spawnSync("pnpm", ["--version"], {
|
|
35
|
-
stdio: "ignore",
|
|
36
|
-
timeout: 3e3
|
|
37
|
-
}).status === 0;
|
|
38
|
-
} catch {
|
|
39
|
-
return false;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Detect the package manager for a Rebase project.
|
|
44
|
-
*
|
|
45
|
-
* Rebase recommends pnpm, so detection prefers it. Crucially, *how the CLI was
|
|
46
|
-
* invoked* (`npx` vs `pnpm dlx`, i.e. `npm_config_user_agent`) is deliberately
|
|
47
|
-
* ignored: running `npx @rebasepro/cli init` says nothing about how the user
|
|
48
|
-
* wants to manage the project they're creating, and letting it pin the scaffold
|
|
49
|
-
* to npm is what made every `npx`-invoked project an npm project.
|
|
26
|
+
* Detect the package manager from the environment or the target directory.
|
|
50
27
|
*
|
|
51
28
|
* Detection order:
|
|
52
|
-
* 1.
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
29
|
+
* 1. Explicit override (if provided)
|
|
30
|
+
* 2. `npm_config_user_agent` env var (set by npm/pnpm when running via `npx`/`pnpm dlx`)
|
|
31
|
+
* 3. Lock-file presence in the target directory
|
|
32
|
+
* 4. Default to pnpm (Rebase's recommended PM)
|
|
56
33
|
*/
|
|
57
34
|
function detectPackageManager(targetDir) {
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
35
|
+
const userAgent = process.env.npm_config_user_agent ?? "";
|
|
36
|
+
if (userAgent.startsWith("npm/")) return "npm";
|
|
37
|
+
if (userAgent.startsWith("pnpm/")) return "pnpm";
|
|
38
|
+
if (targetDir) {
|
|
39
|
+
if (fs.existsSync(path.join(targetDir, "package-lock.json"))) return "npm";
|
|
40
|
+
if (fs.existsSync(path.join(targetDir, "pnpm-lock.yaml"))) return "pnpm";
|
|
62
41
|
}
|
|
63
|
-
|
|
64
|
-
|
|
42
|
+
const cwd = process.cwd();
|
|
43
|
+
if (cwd !== targetDir) {
|
|
44
|
+
if (fs.existsSync(path.join(cwd, "package-lock.json"))) return "npm";
|
|
45
|
+
if (fs.existsSync(path.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
46
|
+
}
|
|
47
|
+
return "pnpm";
|
|
65
48
|
}
|
|
66
49
|
/** Build the command helpers for a given package manager. */
|
|
67
50
|
function getPMCommands(pm) {
|
|
@@ -135,8 +118,7 @@ function getPMCommands(pm) {
|
|
|
135
118
|
runWorkspace: (workspace, script) => [
|
|
136
119
|
"pnpm",
|
|
137
120
|
"--filter",
|
|
138
|
-
|
|
139
|
-
"run",
|
|
121
|
+
workspace,
|
|
140
122
|
script
|
|
141
123
|
],
|
|
142
124
|
dlx: (pkg, args) => [
|
|
@@ -943,13 +925,6 @@ async function promptForOptions(rawArgs, pm) {
|
|
|
943
925
|
cloudUrl: resolveCloudUrl(rawArgs)
|
|
944
926
|
};
|
|
945
927
|
}
|
|
946
|
-
if (!process.stdin.isTTY) {
|
|
947
|
-
console.error(chalk.red("Cannot prompt: this is a non-interactive terminal (no TTY)."));
|
|
948
|
-
console.error(chalk.yellow(" Re-run with --yes to accept defaults, passing any choices as flags, e.g.:"));
|
|
949
|
-
console.error(chalk.yellow(` rebase init ${nameArg || "my-app"} --yes --template blog --flavor cms`));
|
|
950
|
-
console.error(chalk.gray(" Options: --template <blog|ecommerce|blank> --flavor <cms|baas> --database-url <url> --install --git"));
|
|
951
|
-
process.exit(1);
|
|
952
|
-
}
|
|
953
928
|
const questions = buildInitQuestions({
|
|
954
929
|
nameArg,
|
|
955
930
|
templateArg,
|
|
@@ -2477,43 +2452,22 @@ function installForAgent(agentKey, skills, projectDir) {
|
|
|
2477
2452
|
}
|
|
2478
2453
|
return count;
|
|
2479
2454
|
}
|
|
2480
|
-
async function skillsCommand(subcommand,
|
|
2455
|
+
async function skillsCommand(subcommand, _args) {
|
|
2481
2456
|
switch (subcommand) {
|
|
2482
2457
|
case "install":
|
|
2483
|
-
await skillsInstall(
|
|
2458
|
+
await skillsInstall();
|
|
2484
2459
|
break;
|
|
2485
2460
|
case "--help":
|
|
2486
2461
|
case void 0:
|
|
2487
2462
|
printSkillsHelp();
|
|
2488
2463
|
break;
|
|
2489
2464
|
default:
|
|
2490
|
-
console.
|
|
2465
|
+
console.log(chalk.red(`Unknown skills subcommand: ${subcommand}`));
|
|
2491
2466
|
console.log("");
|
|
2492
2467
|
printSkillsHelp();
|
|
2493
|
-
process.exit(1);
|
|
2494
|
-
}
|
|
2495
|
-
}
|
|
2496
|
-
/**
|
|
2497
|
-
* Agents named explicitly on the command line, e.g. `--agent claude --agent cursor`
|
|
2498
|
-
* (also accepts a comma-separated list). Returns null when none were given.
|
|
2499
|
-
*/
|
|
2500
|
-
function parseAgentFlags(rawArgs) {
|
|
2501
|
-
const requested = [];
|
|
2502
|
-
for (let i = 0; i < rawArgs.length; i++) {
|
|
2503
|
-
if (rawArgs[i] !== "--agent" && rawArgs[i] !== "-a") continue;
|
|
2504
|
-
const value = rawArgs[i + 1];
|
|
2505
|
-
if (value && !value.startsWith("-")) requested.push(...value.split(",").map((v) => v.trim()).filter(Boolean));
|
|
2506
|
-
}
|
|
2507
|
-
if (requested.length === 0) return null;
|
|
2508
|
-
const valid = Object.keys(AGENTS);
|
|
2509
|
-
const unknown = requested.filter((a) => !valid.includes(a));
|
|
2510
|
-
if (unknown.length > 0) {
|
|
2511
|
-
console.error(chalk.red(`Unknown agent(s): ${unknown.join(", ")}. Available: ${valid.join(", ")}`));
|
|
2512
|
-
process.exit(1);
|
|
2513
2468
|
}
|
|
2514
|
-
return requested;
|
|
2515
2469
|
}
|
|
2516
|
-
async function skillsInstall(
|
|
2470
|
+
async function skillsInstall() {
|
|
2517
2471
|
const projectDir = process.cwd();
|
|
2518
2472
|
let skillsDir;
|
|
2519
2473
|
try {
|
|
@@ -2527,14 +2481,8 @@ async function skillsInstall(rawArgs = []) {
|
|
|
2527
2481
|
console.error(`${chalk.red.bold("ERROR")} No skills found in ${skillsDir}`);
|
|
2528
2482
|
process.exit(1);
|
|
2529
2483
|
}
|
|
2530
|
-
let agents =
|
|
2484
|
+
let agents = detectAgents(projectDir);
|
|
2531
2485
|
if (agents.length === 0) {
|
|
2532
|
-
if (!process.stdin.isTTY) {
|
|
2533
|
-
console.error(chalk.red("Cannot prompt: this is a non-interactive terminal (no TTY)."));
|
|
2534
|
-
console.error(chalk.yellow(` Name the agents explicitly, e.g. rebase skills install --agent ${Object.keys(AGENTS)[0]}`));
|
|
2535
|
-
console.error(chalk.gray(` Available: ${Object.keys(AGENTS).join(", ")}`));
|
|
2536
|
-
process.exit(1);
|
|
2537
|
-
}
|
|
2538
2486
|
const choices = Object.entries(AGENTS).map(([key, agent]) => ({
|
|
2539
2487
|
name: agent.label,
|
|
2540
2488
|
value: key,
|
|
@@ -2576,15 +2524,8 @@ ${chalk.green.bold("Subcommands")}
|
|
|
2576
2524
|
${chalk.blue.bold("install")} Install Rebase agent skills for your AI coding assistant
|
|
2577
2525
|
Supports: Cursor, Claude Code, Windsurf, Gemini CLI, Antigravity
|
|
2578
2526
|
|
|
2579
|
-
${chalk.green.bold("Options")}
|
|
2580
|
-
${chalk.blue("--agent, -a")} Agent(s) to install for, skipping detection and the prompt.
|
|
2581
|
-
Repeat the flag or pass a comma-separated list.
|
|
2582
|
-
Available: ${Object.keys(AGENTS).join(", ")}
|
|
2583
|
-
|
|
2584
2527
|
${chalk.green.bold("Examples")}
|
|
2585
2528
|
${chalk.cyan("rebase skills install")}
|
|
2586
|
-
${chalk.cyan("rebase skills install --agent claude")}
|
|
2587
|
-
${chalk.cyan("rebase skills install --agent claude,cursor")}
|
|
2588
2529
|
`);
|
|
2589
2530
|
}
|
|
2590
2531
|
//#endregion
|
|
@@ -2616,16 +2557,9 @@ function loadEnv(projectRoot) {
|
|
|
2616
2557
|
}
|
|
2617
2558
|
return env;
|
|
2618
2559
|
}
|
|
2619
|
-
function resolveBaseUrl(env
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
const urlFile = path.join(projectRoot, ".rebase-dev-url");
|
|
2623
|
-
if (fs.existsSync(urlFile)) {
|
|
2624
|
-
const devUrl = fs.readFileSync(urlFile, "utf-8").trim();
|
|
2625
|
-
if (devUrl) return devUrl;
|
|
2626
|
-
}
|
|
2627
|
-
} catch {}
|
|
2628
|
-
return `http://localhost:${env.PORT || env.REBASE_PORT || "3001"}`;
|
|
2560
|
+
function resolveBaseUrl(env) {
|
|
2561
|
+
const port = env.PORT || env.REBASE_PORT || "3001";
|
|
2562
|
+
return env.REBASE_BASE_URL || `http://localhost:${port}`;
|
|
2629
2563
|
}
|
|
2630
2564
|
async function apiKeysCommand(subcommand, rawArgs) {
|
|
2631
2565
|
if (!subcommand || subcommand === "--help") {
|
|
@@ -2650,9 +2584,8 @@ async function apiKeysCommand(subcommand, rawArgs) {
|
|
|
2650
2584
|
}
|
|
2651
2585
|
}
|
|
2652
2586
|
async function listKeys(_rawArgs) {
|
|
2653
|
-
const
|
|
2654
|
-
const
|
|
2655
|
-
const baseUrl = resolveBaseUrl(env, projectRoot);
|
|
2587
|
+
const env = loadEnv(requireProjectRoot());
|
|
2588
|
+
const baseUrl = resolveBaseUrl(env);
|
|
2656
2589
|
const serviceKey = env.SERVICE_KEY || env.REBASE_SERVICE_KEY;
|
|
2657
2590
|
if (!serviceKey) {
|
|
2658
2591
|
console.error(chalk.red("✗ SERVICE_KEY not found in .env — required for admin operations."));
|
|
@@ -2757,9 +2690,8 @@ async function createKey(rawArgs) {
|
|
|
2757
2690
|
expires_at = parsed.toISOString();
|
|
2758
2691
|
}
|
|
2759
2692
|
}
|
|
2760
|
-
const
|
|
2761
|
-
const
|
|
2762
|
-
const baseUrl = resolveBaseUrl(env, projectRoot);
|
|
2693
|
+
const env = loadEnv(requireProjectRoot());
|
|
2694
|
+
const baseUrl = resolveBaseUrl(env);
|
|
2763
2695
|
const serviceKey = env.SERVICE_KEY || env.REBASE_SERVICE_KEY;
|
|
2764
2696
|
if (!serviceKey) {
|
|
2765
2697
|
console.error(chalk.red("✗ SERVICE_KEY not found in .env — required for admin operations."));
|
|
@@ -2816,9 +2748,8 @@ async function revokeKey(rawArgs) {
|
|
|
2816
2748
|
console.log(chalk.gray(" Usage: rebase api-keys revoke <key-id>"));
|
|
2817
2749
|
process.exit(1);
|
|
2818
2750
|
}
|
|
2819
|
-
const
|
|
2820
|
-
const
|
|
2821
|
-
const baseUrl = resolveBaseUrl(env, projectRoot);
|
|
2751
|
+
const env = loadEnv(requireProjectRoot());
|
|
2752
|
+
const baseUrl = resolveBaseUrl(env);
|
|
2822
2753
|
const serviceKey = env.SERVICE_KEY || env.REBASE_SERVICE_KEY;
|
|
2823
2754
|
if (!serviceKey) {
|
|
2824
2755
|
console.error(chalk.red("✗ SERVICE_KEY not found in .env — required for admin operations."));
|
|
@@ -3287,18 +3218,13 @@ function fmtDate(value) {
|
|
|
3287
3218
|
*/
|
|
3288
3219
|
var POLL_INTERVAL_MS = 1500;
|
|
3289
3220
|
var POLL_TIMEOUT_MS = 900 * 1e3;
|
|
3290
|
-
var MAX_SOURCE_UPLOAD_BYTES = 100 * 1024 * 1024;
|
|
3291
3221
|
function sleep(ms) {
|
|
3292
3222
|
return new Promise((r) => setTimeout(r, ms));
|
|
3293
3223
|
}
|
|
3294
|
-
function run(cmd, cmdArgs, cwd
|
|
3224
|
+
function run(cmd, cmdArgs, cwd) {
|
|
3295
3225
|
return new Promise((resolve, reject) => {
|
|
3296
3226
|
const child = spawn(cmd, cmdArgs, {
|
|
3297
3227
|
cwd,
|
|
3298
|
-
env: env ? {
|
|
3299
|
-
...process.env,
|
|
3300
|
-
...env
|
|
3301
|
-
} : void 0,
|
|
3302
3228
|
stdio: [
|
|
3303
3229
|
"ignore",
|
|
3304
3230
|
"ignore",
|
|
@@ -3328,7 +3254,7 @@ async function createSourceTarball(sourceDir) {
|
|
|
3328
3254
|
for (const ignore of [".gitignore", ".rebaseignore"]) if (fs.existsSync(path.join(dir, ignore))) tarArgs.push(`--exclude-from=${ignore}`);
|
|
3329
3255
|
tarArgs.push(".");
|
|
3330
3256
|
try {
|
|
3331
|
-
await run("tar", tarArgs, dir
|
|
3257
|
+
await run("tar", tarArgs, dir);
|
|
3332
3258
|
} catch (e) {
|
|
3333
3259
|
fail(`Failed to package source: ${e instanceof Error ? e.message : String(e)}`);
|
|
3334
3260
|
}
|
|
@@ -3338,7 +3264,6 @@ async function createSourceTarball(sourceDir) {
|
|
|
3338
3264
|
async function uploadSource(url, token, projectId, tarPath) {
|
|
3339
3265
|
const bytes = fs.readFileSync(tarPath);
|
|
3340
3266
|
const sizeMb = (bytes.length / 1024 / 1024).toFixed(1);
|
|
3341
|
-
if (bytes.length > MAX_SOURCE_UPLOAD_BYTES) fail(`Source context is ${sizeMb} MB — the upload cap is ${Math.round(MAX_SOURCE_UPLOAD_BYTES / 1024 / 1024)} MB.`, "Trim the build context: exclude sourcemaps (*.map), build output and large assets via .rebaseignore or .gitignore.");
|
|
3342
3267
|
console.log(chalk.gray(` Uploading source (${sizeMb} MB)...`));
|
|
3343
3268
|
const res = await fetch(`${url}/api/functions/deploy/upload?projectId=${encodeURIComponent(projectId)}`, {
|
|
3344
3269
|
method: "POST",
|
|
@@ -4318,8 +4243,6 @@ ${chalk.green.bold("Options")}
|
|
|
4318
4243
|
${chalk.blue("--secret")} Mark a variable write-only ${chalk.gray("(set)")}
|
|
4319
4244
|
${chalk.blue("--json")} Machine-readable output
|
|
4320
4245
|
${chalk.blue("--project, -p")} Project slug ${chalk.gray("(defaults to the linked project)")}
|
|
4321
|
-
|
|
4322
|
-
${chalk.gray("Values are encrypted at rest (AES-256-GCM) and only decrypted at deploy time.")}
|
|
4323
4246
|
`);
|
|
4324
4247
|
}
|
|
4325
4248
|
function printEnvHelpJson() {
|
|
@@ -5227,10 +5150,7 @@ async function webhooksCommand(subcommand, rawArgs) {
|
|
|
5227
5150
|
reportError(e, "Webhook operation failed");
|
|
5228
5151
|
}
|
|
5229
5152
|
}
|
|
5230
|
-
async function storageCommand(
|
|
5231
|
-
if (action === "create") return storageCreateCommand(rawArgs);
|
|
5232
|
-
if (action === "attach") return storageAttachCommand(rawArgs);
|
|
5233
|
-
if (action === "help") return printStorageHelp();
|
|
5153
|
+
async function storageCommand(rawArgs) {
|
|
5234
5154
|
const { client } = await requireClient(rawArgs);
|
|
5235
5155
|
const projectId = await requireProject(rawArgs, client);
|
|
5236
5156
|
try {
|
|
@@ -5255,107 +5175,6 @@ async function storageCommand(action, rawArgs) {
|
|
|
5255
5175
|
reportError(e, "Failed to list storage");
|
|
5256
5176
|
}
|
|
5257
5177
|
}
|
|
5258
|
-
function printStorageHelp() {
|
|
5259
|
-
console.log("");
|
|
5260
|
-
console.log(chalk.bold(" rebase cloud storage"));
|
|
5261
|
-
console.log("");
|
|
5262
|
-
console.log(" " + chalk.blue.bold("storage") + " List this project's storage");
|
|
5263
|
-
console.log(" " + chalk.blue.bold("storage create") + " Provision platform-managed storage");
|
|
5264
|
-
console.log(" " + chalk.blue.bold("storage attach") + " Attach your own S3-compatible bucket");
|
|
5265
|
-
console.log("");
|
|
5266
|
-
console.log(chalk.gray(" attach options:"));
|
|
5267
|
-
console.log(chalk.gray(" --bucket <name> Bucket name (required)"));
|
|
5268
|
-
console.log(chalk.gray(" --access-key-id <id> Access key ID (required)"));
|
|
5269
|
-
console.log(chalk.gray(" --secret-access-key <s> Secret access key (required)"));
|
|
5270
|
-
console.log(chalk.gray(" --endpoint <url> S3 endpoint; omit for AWS"));
|
|
5271
|
-
console.log(chalk.gray(" --region <region> Region"));
|
|
5272
|
-
console.log(chalk.gray(" --force-path-style Required by MinIO and some gateways"));
|
|
5273
|
-
console.log("");
|
|
5274
|
-
console.log(chalk.gray(" Without either, a tenant falls back to the container filesystem and"));
|
|
5275
|
-
console.log(chalk.gray(" loses uploaded files on its next restart."));
|
|
5276
|
-
console.log("");
|
|
5277
|
-
}
|
|
5278
|
-
async function storageCreateCommand(rawArgs) {
|
|
5279
|
-
const { client } = await requireClient(rawArgs);
|
|
5280
|
-
const projectId = await requireProject(rawArgs, client);
|
|
5281
|
-
try {
|
|
5282
|
-
console.log("");
|
|
5283
|
-
console.log(chalk.gray(" Provisioning managed storage — this creates a bucket and its credentials..."));
|
|
5284
|
-
const res = await client.functions.invoke(`storage-provision/${encodeURIComponent(projectId)}`, void 0, { method: "POST" });
|
|
5285
|
-
const info = res.data ?? res.data;
|
|
5286
|
-
success(`Managed storage provisioned for ${displayProjectRef(rawArgs)}.`);
|
|
5287
|
-
keyValues([
|
|
5288
|
-
["Bucket", info.bucketName],
|
|
5289
|
-
["Region", info.region],
|
|
5290
|
-
["Endpoint", info.endpoint],
|
|
5291
|
-
["Access key", info.accessKeyId]
|
|
5292
|
-
]);
|
|
5293
|
-
console.log("");
|
|
5294
|
-
console.log(chalk.gray(" The secret key is stored encrypted and injected at deploy time; it is not displayed."));
|
|
5295
|
-
console.log(chalk.gray(" Redeploy for the tenant to pick it up: ") + chalk.bold("rebase cloud deploy"));
|
|
5296
|
-
console.log("");
|
|
5297
|
-
} catch (e) {
|
|
5298
|
-
reportError(e, "Failed to provision managed storage");
|
|
5299
|
-
}
|
|
5300
|
-
}
|
|
5301
|
-
async function storageAttachCommand(rawArgs) {
|
|
5302
|
-
const parsed = arg({
|
|
5303
|
-
"--bucket": String,
|
|
5304
|
-
"--access-key-id": String,
|
|
5305
|
-
"--secret-access-key": String,
|
|
5306
|
-
"--endpoint": String,
|
|
5307
|
-
"--region": String,
|
|
5308
|
-
"--force-path-style": Boolean
|
|
5309
|
-
}, {
|
|
5310
|
-
argv: rawArgs.slice(3),
|
|
5311
|
-
permissive: true
|
|
5312
|
-
});
|
|
5313
|
-
const bucket = parsed["--bucket"];
|
|
5314
|
-
const accessKeyId = parsed["--access-key-id"];
|
|
5315
|
-
const secretAccessKey = parsed["--secret-access-key"];
|
|
5316
|
-
const missing = [
|
|
5317
|
-
!bucket && "--bucket",
|
|
5318
|
-
!accessKeyId && "--access-key-id",
|
|
5319
|
-
!secretAccessKey && "--secret-access-key"
|
|
5320
|
-
].filter(Boolean);
|
|
5321
|
-
if (missing.length > 0) fail(`Missing ${missing.join(", ")}.`, "A bucket without credentials cannot be used, and would be stored as though it could. Run `rebase cloud storage --help` for the full list.");
|
|
5322
|
-
const { client } = await requireClient(rawArgs);
|
|
5323
|
-
const projectId = await requireProject(rawArgs, client);
|
|
5324
|
-
try {
|
|
5325
|
-
const existing = (await client.data.collection("storages").find({
|
|
5326
|
-
where: { project: ["==", projectId] },
|
|
5327
|
-
limit: 1
|
|
5328
|
-
})).data[0];
|
|
5329
|
-
const row = {
|
|
5330
|
-
project: projectId,
|
|
5331
|
-
type: "byos",
|
|
5332
|
-
status: "active",
|
|
5333
|
-
s3Bucket: bucket,
|
|
5334
|
-
s3AccessKeyId: accessKeyId,
|
|
5335
|
-
s3SecretAccessKey: secretAccessKey,
|
|
5336
|
-
bucketName: bucket
|
|
5337
|
-
};
|
|
5338
|
-
if (parsed["--endpoint"]) row.s3Endpoint = parsed["--endpoint"];
|
|
5339
|
-
if (parsed["--region"]) {
|
|
5340
|
-
row.s3Region = parsed["--region"];
|
|
5341
|
-
row.region = parsed["--region"];
|
|
5342
|
-
}
|
|
5343
|
-
if (parsed["--force-path-style"]) row.s3ForcePathStyle = true;
|
|
5344
|
-
if (existing?.id) await client.data.collection("storages").update(String(existing.id), row);
|
|
5345
|
-
else await client.data.collection("storages").create(row);
|
|
5346
|
-
success(`Storage attached to ${displayProjectRef(rawArgs)}.`);
|
|
5347
|
-
keyValues([
|
|
5348
|
-
["Bucket", bucket],
|
|
5349
|
-
["Endpoint", parsed["--endpoint"] ?? "AWS S3"],
|
|
5350
|
-
["Region", parsed["--region"] ?? "(default)"]
|
|
5351
|
-
]);
|
|
5352
|
-
console.log("");
|
|
5353
|
-
console.log(chalk.gray(" Redeploy for the tenant to pick it up: ") + chalk.bold("rebase cloud deploy"));
|
|
5354
|
-
console.log("");
|
|
5355
|
-
} catch (e) {
|
|
5356
|
-
reportError(e, "Failed to attach storage");
|
|
5357
|
-
}
|
|
5358
|
-
}
|
|
5359
5178
|
async function clustersCommand(rawArgs) {
|
|
5360
5179
|
const { client } = await requireClient(rawArgs);
|
|
5361
5180
|
try {
|
|
@@ -5573,7 +5392,7 @@ async function cloudCommand(subcommand, rawArgs) {
|
|
|
5573
5392
|
await webhooksCommand(action, rawArgs);
|
|
5574
5393
|
break;
|
|
5575
5394
|
case "storage":
|
|
5576
|
-
await storageCommand(
|
|
5395
|
+
await storageCommand(rawArgs);
|
|
5577
5396
|
break;
|
|
5578
5397
|
case "clusters":
|
|
5579
5398
|
await clustersCommand(rawArgs);
|
|
@@ -5676,8 +5495,6 @@ ${chalk.green.bold("Databases")}
|
|
|
5676
5495
|
${chalk.green.bold("Other resources")}
|
|
5677
5496
|
${chalk.blue.bold("webhooks list|create|delete")}
|
|
5678
5497
|
${chalk.blue.bold("storage")} List storage buckets
|
|
5679
|
-
${chalk.blue.bold("storage create")} Provision platform-managed storage
|
|
5680
|
-
${chalk.blue.bold("storage attach")} Attach your own S3-compatible bucket
|
|
5681
5498
|
${chalk.blue.bold("clusters")} List compute clusters
|
|
5682
5499
|
${chalk.blue.bold("billing setup")} Attach a card to the org ${chalk.gray("(one-time, opens browser)")}
|
|
5683
5500
|
${chalk.blue.bold("billing")} Show billing account + card on file
|
|
@@ -5786,10 +5603,9 @@ async function entry(args) {
|
|
|
5786
5603
|
await cloudCommand(effectiveSubcommand, args);
|
|
5787
5604
|
break;
|
|
5788
5605
|
default:
|
|
5789
|
-
console.
|
|
5606
|
+
console.log(chalk.red(`Unknown command: ${command}`));
|
|
5790
5607
|
console.log("");
|
|
5791
5608
|
printHelp();
|
|
5792
|
-
process.exit(1);
|
|
5793
5609
|
}
|
|
5794
5610
|
}
|
|
5795
5611
|
function printHelp() {
|
|
@@ -5849,6 +5665,6 @@ ${chalk.gray("Documentation: https://rebase.pro/docs")}
|
|
|
5849
5665
|
`);
|
|
5850
5666
|
}
|
|
5851
5667
|
//#endregion
|
|
5852
|
-
export { authCommand, buildCommand, buildInitQuestions, cloudCommand, configureEnvFile, createRebaseApp, dbCommand, detectPackageManager, devCommand, doctorCommand, entry, findBackendDir, findEnvFile, findFrontendDir, findProjectRoot, generateSdkCommand, getActiveBackendPlugin, getPMCommands,
|
|
5668
|
+
export { authCommand, buildCommand, buildInitQuestions, cloudCommand, configureEnvFile, createRebaseApp, dbCommand, detectPackageManager, devCommand, doctorCommand, entry, findBackendDir, findEnvFile, findFrontendDir, findProjectRoot, generateSdkCommand, getActiveBackendPlugin, getPMCommands, requireBackendDir, requireProjectRoot, resolveLocalBin, resolvePluginCliScript, resolveTsx, schemaCommand, startCommand, validateProjectName, validateTsxInstallation };
|
|
5853
5669
|
|
|
5854
5670
|
//# sourceMappingURL=index.es.js.map
|