diff --git a/create-db/README.md b/create-db/README.md index b382485..a308958 100644 --- a/create-db/README.md +++ b/create-db/README.md @@ -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 { @@ -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: diff --git a/create-db/__tests__/cli.test.ts b/create-db/__tests__/cli.test.ts index a5b0c62..aa0e6b8 100644 --- a/create-db/__tests__/cli.test.ts +++ b/create-db/__tests__/cli.test.ts @@ -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"); }); }); diff --git a/create-db/__tests__/create.test.ts b/create-db/__tests__/create.test.ts index 33116a6..0bb113e 100644 --- a/create-db/__tests__/create.test.ts +++ b/create-db/__tests__/create.test.ts @@ -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); }); diff --git a/create-db/__tests__/flags.test.ts b/create-db/__tests__/flags.test.ts index 8071562..f133cff 100644 --- a/create-db/__tests__/flags.test.ts +++ b/create-db/__tests__/flags.test.ts @@ -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", () => { @@ -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); + }); +}); diff --git a/create-db/src/cli/commands/regions.ts b/create-db/src/cli/commands/regions.ts index 2049148..e2f1347 100644 --- a/create-db/src/cli/commands/regions.ts +++ b/create-db/src/cli/commands/regions.ts @@ -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 { +export async function handleRegions(input: RegionsFlagsInput): Promise { const regions = await fetchRegions(); + if (input.json) { + printJson(regions); + return; + } + log.message(""); log.info(pc.bold(pc.cyan("Available Prisma Postgres regions:"))); log.message(""); diff --git a/create-db/src/cli/flags.ts b/create-db/src/cli/flags.ts index 356fca5..dc90549 100644 --- a/create-db/src/cli/flags.ts +++ b/create-db/src/cli/flags.ts @@ -35,4 +35,19 @@ export const CreateFlags = z.object({ /** Inferred type from CreateFlags schema. */ export type CreateFlagsInput = z.infer; -// GitHub issue to suppress the Alias in the help text: https://github.com/mmkal/trpc-cli/issues/154 \ No newline at end of file +/** + * 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; + +// GitHub issue to suppress the Alias in the help text: https://github.com/mmkal/trpc-cli/issues/154 diff --git a/create-db/src/index.ts b/create-db/src/index.ts index 0214b14..b854318 100644 --- a/create-db/src/index.ts +++ b/create-db/src/index.ts @@ -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"; @@ -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 @@ -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)), }); /**