Skip to content
Merged
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
17 changes: 16 additions & 1 deletion create-db/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,14 @@ npx create-db -i -e .env

# List available regions
npx create-db regions

# List available regions as JSON
npx create-db regions --json
```

### JSON Output

When using `--json`, the output includes:
When using `--json` with `create`, the output includes:

```json
{
Expand All @@ -96,6 +99,18 @@ When using `--json`, the output includes:
}
```

When using `--json` with `regions`, the output is an array of region objects:

```json
[
{
"id": "us-east-1",
"name": "US East (N. Virginia)",
"status": "available"
}
]
```

### Environment File Output

When using `--env`, the following variables are appended to the specified file:
Expand Down
1 change: 1 addition & 0 deletions create-db/__tests__/cli.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ describe("CLI help and version", () => {
const result = await runCli(["regions", "--help"]);
expect(result.exitCode).toBe(0);
expect(result.all).toContain("List available Prisma Postgres regions");
expect(result.all).toContain("--json");
});
});

Expand Down
17 changes: 17 additions & 0 deletions create-db/__tests__/create.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,21 @@ describe("CLI database creation", () => {
}
expect(allOutput).toContain("Available Prisma Postgres regions");
}, 20000);

it("lists regions as JSON with regions --json", async () => {
const result = await runCli(["regions", "--json"]);
if (result.exitCode !== 0) {
console.error("CLI failed with exit code:", result.exitCode);
console.error("stdout:", result.stdout);
console.error("stderr:", result.stderr);
}
expect(result.exitCode).toBe(0);
const trimmed = result.stdout.trim();
expect(trimmed).toMatch(/^\s*\[/);
const parsed = JSON.parse(trimmed);
expect(Array.isArray(parsed)).toBe(true);
expect(parsed.length).toBeGreaterThan(0);
expect(parsed[0]).toHaveProperty("id");
expect(parsed[0]).toHaveProperty("status");
}, 20000);
});
31 changes: 30 additions & 1 deletion create-db/__tests__/flags.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { describe, it, expect } from "vitest";
import { CreateFlags, type CreateFlagsInput } from "../src/cli/flags.js";
import {
CreateFlags,
RegionsFlags,
type CreateFlagsInput,
type RegionsFlagsInput,
} from "../src/cli/flags.js";
import { RegionSchema } from "../src/types.js";

describe("CreateFlags schema", () => {
Expand Down Expand Up @@ -219,3 +224,27 @@ describe("RegionSchema", () => {
expect(RegionSchema.safeParse({}).success).toBe(false);
});
});

describe("RegionsFlags schema", () => {
it("defaults json to false", () => {
const result = RegionsFlags.safeParse({});
expect(result.success).toBe(true);
if (result.success) {
expect(result.data.json).toBe(false);
}
});

it("accepts json=true", () => {
const result = RegionsFlags.safeParse({ json: true });
expect(result.success).toBe(true);
if (result.success) {
expect(result.data.json).toBe(true);
}
});

it("infers RegionsFlagsInput correctly", () => {
const input: RegionsFlagsInput = { json: true };
const result = RegionsFlags.parse(input);
expect(result.json).toBe(true);
});
});
9 changes: 8 additions & 1 deletion create-db/src/cli/commands/regions.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
import { log } from "@clack/prompts";
import pc from "picocolors";

import type { RegionsFlagsInput } from "../flags.js";
import { fetchRegions } from "../../core/services.js";
import { printJson } from "../output.js";

export async function handleRegions(): Promise<void> {
export async function handleRegions(input: RegionsFlagsInput): Promise<void> {
const regions = await fetchRegions();

if (input.json) {
printJson(regions);
return;
}

log.message("");
log.info(pc.bold(pc.cyan("Available Prisma Postgres regions:")));
log.message("");
Expand Down
17 changes: 16 additions & 1 deletion create-db/src/cli/flags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,19 @@ export const CreateFlags = z.object({
/** Inferred type from CreateFlags schema. */
export type CreateFlagsInput = z.infer<typeof CreateFlags>;

// GitHub issue to suppress the Alias in the help text: https://github.com/mmkal/trpc-cli/issues/154
/**
* Zod schema for CLI flags used by the `regions` command.
*/
export const RegionsFlags = z.object({
json: z
.boolean()
.optional()
.default(false)
.describe("Output machine-readable JSON")
.meta({ alias: "j" }),
});

/** Inferred type from RegionsFlags schema. */
export type RegionsFlagsInput = z.infer<typeof RegionsFlags>;

// GitHub issue to suppress the Alias in the help text: https://github.com/mmkal/trpc-cli/issues/154
15 changes: 12 additions & 3 deletions create-db/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ import {
type CreateDatabaseResult,
type ProgrammaticCreateOptions,
} from "./types.js";
import { CreateFlags } from "./cli/flags.js";
import {
CreateFlags,
RegionsFlags,
} from "./cli/flags.js";
import { getCommandName } from "./core/database.js";
import { handleCreate, handleRegions } from "./cli/commands/index.js";
import { createDatabase, fetchRegions } from "./core/services.js";
Expand All @@ -21,7 +24,12 @@ export type {
} from "./types.js";

export { isDatabaseError, isDatabaseSuccess, RegionSchema } from "./types.js";
export { CreateFlags, type CreateFlagsInput } from "./cli/flags.js";
export {
CreateFlags,
RegionsFlags,
type CreateFlagsInput,
type RegionsFlagsInput,
} from "./cli/flags.js";

const router = os.router({
create: os
Expand All @@ -34,7 +42,8 @@ const router = os.router({

regions: os
.meta({ description: "List available Prisma Postgres regions" })
.handler(async () => handleRegions()),
.input(RegionsFlags)
.handler(async ({ input }) => handleRegions(input)),
});

/**
Expand Down