Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 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
39 changes: 37 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,41 @@ This monorepo contains tools and services that enable developers to quickly prov
2. **Cloudflare Workers** - Backend services for database management and OAuth authentication
3. **Monorepo Infrastructure** - Shared tooling and versioning

## CLI Reference

### Available Flags

| Flag | Description | Example |
| ---------------- | ----------------------------------- | -------------------- |
| `--region` | Specify database region | `--region us-east-1` |
| `--list-regions` | List available regions | `--list-regions` |
| `--interactive` | Enable interactive region selection | `--interactive` |
| `--help` | Show help information | `--help` |
| `--json` | Output the info in a JSON format | `--json` |

### Examples

```bash
# Create database with specific region
npx create-db --region eu-west-1

# List available regions
npx create-db --list-regions

# Interactive mode
npx create-db --interactive

# Output in JSON format
npx create-db --json

# Show help
npx create-db --help

# Alternative command shorthand names work the same way
npx create-pg -r us-east-1
npx create-pg -j
```

## Packages

### CLI Tools
Expand Down Expand Up @@ -107,7 +142,7 @@ CLAIM_DB_WORKER_URL="http://127.0.0.1:9999"

### Installation

```bash
````bash
# Clone the repository
git clone https://github.com/prisma/create-db.git
cd create-db
Expand All @@ -128,7 +163,7 @@ cd ../create-db && pnpm install

```env
INTEGRATION_TOKEN=your_prisma_integration_token
```
````

**Claim DB Worker** (`claim-db-worker/.dev.vars`):

Expand Down
74 changes: 65 additions & 9 deletions create-db/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -194,13 +194,15 @@ Options:
${chalk.yellow("--json, -j")} Output machine-readable JSON and exit
${chalk.yellow("--list-regions")} List available regions and exit
${chalk.yellow("--help, -h")} Show this help message
${chalk.yellow("--env, -e")} Prints DATABASE_URL to the terminal

Examples:
${chalk.gray(`npx ${CLI_NAME} --region us-east-1`)}
${chalk.gray(`npx ${CLI_NAME} -r us-east-1`)}
${chalk.gray(`npx ${CLI_NAME} --interactive`)}
${chalk.gray(`npx ${CLI_NAME} -i`)}
${chalk.gray(`npx ${CLI_NAME} --json --region us-east-1`)}
${chalk.gray(`npx ${CLI_NAME} --env --region us-east-1`)}
`);
process.exit(0);
}
Expand All @@ -215,12 +217,14 @@ async function parseArgs() {
"list-regions",
"interactive",
"json",
"env",
];
const shorthandMap = {
r: "region",
i: "interactive",
h: "help",
j: "json",
e: "env",
};

const exitWithError = (message) => {
Expand Down Expand Up @@ -293,6 +297,30 @@ async function parseArgs() {
return { flags };
}

function validateFlagCombinations(flags) {
const conflictingFlags = [
["env", "json"],
["list-regions", "env"],
["list-regions", "json"],
["list-regions", "interactive"],
["list-regions", "region"],
["interactive", "env"],
["interactive", "json"],
];

for (const [flag1, flag2] of conflictingFlags) {
if (flags[flag1] && flags[flag2]) {
console.error(
chalk.red.bold(
`\n✖ Error: Cannot use --${flag1} and --${flag2} together.\n`
)
);
console.error(chalk.gray("Use --help or -h to see available options.\n"));
process.exit(1);
}
}
}

export async function getRegions(returnJson = false) {
const url = `${CREATE_DB_WORKER_URL}/regions`;
const res = await fetch(url);
Expand Down Expand Up @@ -389,9 +417,9 @@ async function promptForRegion(defaultRegion, userAgent) {
return region;
}

async function createDatabase(name, region, userAgent, returnJson = false) {
async function createDatabase(name, region, userAgent, silent = false) {
let s;
if (!returnJson) {
if (!silent) {
s = spinner();
s.start("Creating your database...");
}
Expand All @@ -407,7 +435,7 @@ async function createDatabase(name, region, userAgent, returnJson = false) {
});

if (resp.status === 429) {
if (returnJson) {
if (silent) {
return {
error: "rate_limit_exceeded",
message:
Expand Down Expand Up @@ -439,7 +467,7 @@ async function createDatabase(name, region, userAgent, returnJson = false) {
raw = await resp.text();
result = JSON.parse(raw);
} catch (e) {
if (returnJson) {
if (silent) {
return {
error: "invalid_json",
message: "Unexpected response from create service.",
Expand Down Expand Up @@ -485,10 +513,10 @@ async function createDatabase(name, region, userAgent, returnJson = false) {
? `postgresql://${directUser}:${directPass}@${directHost}${directPort}/${directDbName}?sslmode=require`
: null;

const claimUrl = `${CLAIM_DB_WORKER_URL}?projectID=${projectId}&utm_source=${userAgent}&utm_medium=cli`;
const claimUrl = `${CLAIM_DB_WORKER_URL}?projectID=${projectId}&utm_source=${userAgent || CLI_NAME}&utm_medium=cli`;
const expiryDate = new Date(Date.now() + 24 * 60 * 60 * 1000);

if (returnJson && !result.error) {
if (silent && !result.error) {
const jsonResponse = {
connectionString: prismaConn,
directConnectionString: directConn,
Expand All @@ -507,11 +535,12 @@ async function createDatabase(name, region, userAgent, returnJson = false) {
}

if (result.error) {
if (returnJson) {
if (silent) {
return {
error: "api_error",
message: result.error.message || "Unknown error",
details: result.error,
status: result.error.status ?? resp.status,
};
}

Expand Down Expand Up @@ -593,6 +622,8 @@ async function main() {

const { flags } = await parseArgs();

validateFlagCombinations(flags);

let userAgent;
const userEnvVars = readUserEnvFile();
if (userEnvVars.PRISMA_ACTOR_NAME && userEnvVars.PRISMA_ACTOR_PROJECT) {
Expand All @@ -608,6 +639,7 @@ async function main() {
"has-help-flag": rawArgs.includes("--help") || rawArgs.includes("-h"),
"has-list-regions-flag": rawArgs.includes("--list-regions"),
"has-json-flag": rawArgs.includes("--json") || rawArgs.includes("-j"),
"has-env-flag": rawArgs.includes("--env") || rawArgs.includes("-e"),
"has-user-agent-from-env": !!userAgent,
"node-version": process.version,
platform: process.platform,
Expand All @@ -620,8 +652,11 @@ async function main() {
}

let name = new Date().toISOString();
let userLocation = await detectUserLocation();
let region = getRegionClosestToLocation(userLocation) || "us-east-1";
let region = flags.region || "us-east-1";
if (!flags.region || !flags.interactive) {
const userLocation = await detectUserLocation();
region = getRegionClosestToLocation(userLocation) || region;
}
let chooseRegionPrompt = false;

if (flags.help) {
Expand Down Expand Up @@ -670,6 +705,27 @@ async function main() {
}
}

if (flags.env) {
try {
if (chooseRegionPrompt) {
region = await promptForRegion(region, userAgent);
} else {
await validateRegion(region, true);
}
const result = await createDatabase(name, region, userAgent, true);
if (result.error) {
console.error(result.message || "Unknown error");
process.exit(1);
}
console.log(`DATABASE_URL="${result.directConnectionString}"`);
console.error("\n# Claim your database at: " + result.claimUrl);
process.exit(0);
} catch (e) {
console.error(e?.message || String(e));
process.exit(1);
}
}

intro(chalk.cyan.bold("🚀 Creating a Prisma Postgres database"));
log.message(
chalk.white(`Provisioning a temporary database in ${region}...`)
Expand Down
2 changes: 1 addition & 1 deletion create-db/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "create-db",
"version": "1.0.6",
"version": "1.0.7",
"description": "Instantly create a temporary Prisma Postgres database with one command, then claim and persist it in your Prisma Data Platform project when ready.",
"main": "index.js",
"author": "",
Expand Down
2 changes: 1 addition & 1 deletion create-pg/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "create-pg",
"version": "1.0.6",
"version": "1.0.7",
"description": "Instantly create a temporary Prisma Postgres database with one command, then claim and persist it in your Prisma Data Platform project when ready.",
"main": "index.js",
"author": "",
Expand Down
2 changes: 1 addition & 1 deletion create-postgres/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "create-postgres",
"version": "1.0.6",
"version": "1.0.7",
"description": "Instantly create a temporary Prisma Postgres database with one command, then claim and persist it in your Prisma Data Platform project when ready.",
"main": "index.js",
"author": "",
Expand Down