Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ Every command that returns account data outputs JSON, so you can pipe to `jq`. T
upstash start-redis # free temporary DB, no account needed
upstash redis list
upstash redis create --name my-db --region us-east-1
upstash redis create-branch --db-id $DB_ID --name staging # a copy of the data to test against
upstash redis exec --db-url $URL --db-token $TOKEN GET key

# Vector
Expand Down
20 changes: 20 additions & 0 deletions src/commands/redis/create-branch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Command } from "commander";
import { resolveAuth } from "../../auth.js";
import { request } from "../../client.js";
import { printJSON } from "../../output.js";
import type { Database } from "../../types.js";

export function registerCreateBranch(redis: Command): void {
redis
.command("create-branch")
.description(
"Create a branch: a point-in-time copy of a Redis database with its own endpoint and password, billed as pay-as-you-go. It starts in state creating; poll `redis get` until state is active.",
)
.requiredOption("--db-id <id>", "ID of the database or branch to copy")
.requiredOption("--name <name>", "Branch name, unique among the branches of the database")
.action(async (flags: { dbId: string; name: string }, command: Command) => {
const auth = resolveAuth(command);
const branch = await request<Database>(auth, "POST", `/v2/redis/database/${flags.dbId}/branch`, { name: flags.name });
printJSON(branch);
});
}
2 changes: 2 additions & 0 deletions src/commands/redis/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Command } from "commander";
import { registerCreate } from "./create.js";
import { registerCreateBranch } from "./create-branch.js";
import { registerList } from "./list.js";
import { registerGet } from "./get.js";
import { registerDelete } from "./delete.js";
Expand All @@ -22,6 +23,7 @@ export function registerRedis(program: Command): void {
const redis = program.command("redis").description("Manage Redis databases");

registerCreate(redis);
registerCreateBranch(redis);
registerList(redis);
registerGet(redis);
registerDelete(redis);
Expand Down
2 changes: 2 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ export type Region = (typeof REGIONS)[number];
export interface Database {
database_id: string;
database_name: string;
root_database_id?: string;
source_database_id?: string;
password?: string;
endpoint?: string;
port?: number;
Expand Down
29 changes: 29 additions & 0 deletions tests/unit/redis-branch.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { createRedisProgram, runCommand } from "../helpers/program.js";

const originalEnv = { ...process.env };

beforeEach(() => {
process.env = { ...originalEnv, UPSTASH_EMAIL: "user@example.com", UPSTASH_API_KEY: "api-key" };
});

afterEach(() => {
vi.restoreAllMocks();
process.env = { ...originalEnv };
});

describe("redis create-branch", () => {
it("posts the name to the source database's branch route and prints the branch", async () => {
const branch = { database_id: "branch_1", database_name: "staging", root_database_id: "db_123", state: "creating" };
const fetchSpy = vi.spyOn(globalThis, "fetch").mockResolvedValue(Response.json(branch));
const program = await createRedisProgram();

const output = await runCommand(program, ["redis", "create-branch", "--db-id", "db_123", "--name", "staging"]);

const [url, init] = fetchSpy.mock.calls[0] as [string, RequestInit];
expect(url).toBe("https://api.upstash.com/v2/redis/database/db_123/branch");
expect(init.method).toBe("POST");
expect(JSON.parse(init.body as string)).toEqual({ name: "staging" });
expect(output).toEqual(branch);
});
});
Loading