From 591affcd079de508eae00342fcaa0477afbebfd3 Mon Sep 17 00:00:00 2001 From: Aman Varshney Date: Sat, 7 Jun 2025 21:55:00 +0530 Subject: [PATCH] add neondb support (#308) --- .changeset/poor-loops-tan.md | 5 + .../helpers/database-providers/neon-setup.ts | 112 +++++++++++++----- 2 files changed, 89 insertions(+), 28 deletions(-) create mode 100644 .changeset/poor-loops-tan.md diff --git a/.changeset/poor-loops-tan.md b/.changeset/poor-loops-tan.md new file mode 100644 index 0000000..e157540 --- /dev/null +++ b/.changeset/poor-loops-tan.md @@ -0,0 +1,5 @@ +--- +"create-better-t-stack": patch +--- + +add neondb cli support diff --git a/apps/cli/src/helpers/database-providers/neon-setup.ts b/apps/cli/src/helpers/database-providers/neon-setup.ts index 77f0615..31b7298 100644 --- a/apps/cli/src/helpers/database-providers/neon-setup.ts +++ b/apps/cli/src/helpers/database-providers/neon-setup.ts @@ -114,6 +114,36 @@ async function writeEnvFile(projectDir: string, config?: NeonConfig) { return true; } +async function setupWithNeonDb( + projectDir: string, + packageManager: PackageManager, +) { + try { + const s = spinner(); + s.start("Creating Neon database using neondb..."); + + const serverDir = path.join(projectDir, "apps/server"); + await fs.ensureDir(serverDir); + + const packageCmd = getPackageExecutionCommand( + packageManager, + "neondb --yes", + ); + + await execa(packageCmd, { + shell: true, + cwd: serverDir, + }); + + s.stop(pc.green("Neon database created successfully!")); + + return true; + } catch (error) { + consola.error(pc.red("Failed to create database with neondb")); + throw error; + } +} + function displayManualSetupInstructions() { log.info(`Manual Neon PostgreSQL Setup Instructions: @@ -129,43 +159,69 @@ export async function setupNeonPostgres(config: ProjectConfig): Promise { const { packageManager, projectDir } = config; try { - const suggestedProjectName = path.basename(projectDir); - const projectName = await text({ - message: "Enter a name for your Neon project:", - defaultValue: suggestedProjectName, - initialValue: suggestedProjectName, + const setupMethod = await select({ + message: "Choose your Neon setup method:", + options: [ + { + label: "Quick setup with neondb", + value: "neondb", + hint: "fastest, no auth required", + }, + { + label: "Custom setup with neonctl", + value: "neonctl", + hint: "More control - choose project name and region", + }, + ], + initialValue: "neondb", }); - const regionId = await select({ - message: "Select a region for your Neon project:", - options: NEON_REGIONS, - initialValue: NEON_REGIONS[0].value, - }); - - if (isCancel(projectName) || isCancel(regionId)) { + if (isCancel(setupMethod)) { cancel(pc.red("Operation cancelled")); process.exit(0); } - const config = await createNeonProject( - projectName as string, - regionId, - packageManager, - ); + if (setupMethod === "neondb") { + await setupWithNeonDb(projectDir, packageManager); + } else { + const suggestedProjectName = path.basename(projectDir); + const projectName = await text({ + message: "Enter a name for your Neon project:", + defaultValue: suggestedProjectName, + initialValue: suggestedProjectName, + }); - if (!config) { - throw new Error( - "Failed to create project - couldn't get connection information", + const regionId = await select({ + message: "Select a region for your Neon project:", + options: NEON_REGIONS, + initialValue: NEON_REGIONS[0].value, + }); + + if (isCancel(projectName) || isCancel(regionId)) { + cancel(pc.red("Operation cancelled")); + process.exit(0); + } + + const neonConfig = await createNeonProject( + projectName as string, + regionId, + packageManager, ); + + if (!neonConfig) { + throw new Error( + "Failed to create project - couldn't get connection information", + ); + } + + const finalSpinner = spinner(); + finalSpinner.start("Configuring database connection"); + + await fs.ensureDir(path.join(projectDir, "apps/server")); + await writeEnvFile(projectDir, neonConfig); + + finalSpinner.stop("Neon database configured!"); } - - const finalSpinner = spinner(); - finalSpinner.start("Configuring database connection"); - - await fs.ensureDir(path.join(projectDir, "apps/server")); - await writeEnvFile(projectDir, config); - - finalSpinner.stop("Neon database configured!"); } catch (error) { if (error instanceof Error) { consola.error(pc.red(error.message));