create-db 1.1.1-pr66-version-bump-19346362281.0 → 1.1.1-pr67-overhaul-20068192317.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js DELETED
@@ -1,836 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- import { select, spinner, intro, outro, log, cancel } from "@clack/prompts";
4
- import { randomUUID } from "crypto";
5
- import dotenv from "dotenv";
6
- import fs from "fs";
7
- import path from "path";
8
- import terminalLink from "terminal-link";
9
- import chalk from "chalk";
10
-
11
- dotenv.config();
12
-
13
- const CREATE_DB_WORKER_URL =
14
- process.env.CREATE_DB_WORKER_URL || "https://create-db-temp.prisma.io";
15
- const CLAIM_DB_WORKER_URL =
16
- process.env.CLAIM_DB_WORKER_URL || "https://create-db.prisma.io";
17
-
18
- // Track pending analytics promises to ensure they complete before exit
19
- const pendingAnalytics = [];
20
-
21
- async function sendAnalyticsToWorker(eventName, properties, cliRunId) {
22
- const controller = new AbortController();
23
- const timer = setTimeout(() => controller.abort(), 5000);
24
-
25
- const analyticsPromise = (async () => {
26
- try {
27
- const payload = {
28
- eventName,
29
- properties: { distinct_id: cliRunId, ...(properties || {}) },
30
- };
31
- await fetch(`${CREATE_DB_WORKER_URL}/analytics`, {
32
- method: "POST",
33
- headers: { "Content-Type": "application/json" },
34
- body: JSON.stringify(payload),
35
- signal: controller.signal,
36
- });
37
- } catch (error) {
38
- // Silently fail - analytics shouldn't block CLI
39
- } finally {
40
- clearTimeout(timer);
41
- }
42
- })();
43
-
44
- pendingAnalytics.push(analyticsPromise);
45
- return analyticsPromise;
46
- }
47
-
48
- // Wait for all pending analytics with a timeout
49
- async function flushAnalytics(maxWaitMs = 500) {
50
- if (pendingAnalytics.length === 0) return;
51
-
52
- const timeout = new Promise((resolve) => setTimeout(resolve, maxWaitMs));
53
- const allAnalytics = Promise.all(pendingAnalytics);
54
-
55
- await Promise.race([allAnalytics, timeout]);
56
- }
57
-
58
- async function detectUserLocation() {
59
- try {
60
- const response = await fetch("https://ipapi.co/json/", {
61
- method: "GET",
62
- headers: {
63
- "User-Agent": "create-db-cli/1.0",
64
- },
65
- });
66
-
67
- if (!response.ok) {
68
- throw new Error(`Failed to fetch location data: ${response.status}`);
69
- }
70
-
71
- const data = await response.json();
72
- return {
73
- country: data.country_code,
74
- continent: data.continent_code,
75
- city: data.city,
76
- region: data.region,
77
- latitude: data.latitude,
78
- longitude: data.longitude,
79
- };
80
- } catch (error) {
81
- return null;
82
- }
83
- }
84
-
85
- const REGION_COORDINATES = {
86
- "ap-southeast-1": { lat: 1.3521, lng: 103.8198 }, // Singapore
87
- "ap-northeast-1": { lat: 35.6762, lng: 139.6503 }, // Tokyo
88
- "eu-central-1": { lat: 50.1109, lng: 8.6821 }, // Frankfurt
89
- "eu-west-3": { lat: 48.8566, lng: 2.3522 }, // Paris
90
- "us-east-1": { lat: 38.9072, lng: -77.0369 }, // N. Virginia
91
- "us-west-1": { lat: 37.7749, lng: -122.4194 }, // N. California
92
- };
93
-
94
- export function getRegionClosestToLocation(userLocation) {
95
- if (!userLocation) return null;
96
-
97
- const userLat = parseFloat(userLocation.latitude);
98
- const userLng = parseFloat(userLocation.longitude);
99
-
100
- let closestRegion = null;
101
- let minDistance = Infinity;
102
-
103
- for (const [region, coordinates] of Object.entries(REGION_COORDINATES)) {
104
- // Simple distance calculation using Haversine formula
105
- const latDiff = ((userLat - coordinates.lat) * Math.PI) / 180;
106
- const lngDiff = ((userLng - coordinates.lng) * Math.PI) / 180;
107
- const a =
108
- Math.sin(latDiff / 2) * Math.sin(latDiff / 2) +
109
- Math.cos((userLat * Math.PI) / 180) *
110
- Math.cos((coordinates.lat * Math.PI) / 180) *
111
- Math.sin(lngDiff / 2) *
112
- Math.sin(lngDiff / 2);
113
- const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
114
- const distance = 6371 * c; // Earth radius in km
115
-
116
- if (distance < minDistance) {
117
- minDistance = distance;
118
- closestRegion = region;
119
- }
120
- }
121
-
122
- return closestRegion;
123
- }
124
-
125
- async function listRegions() {
126
- try {
127
- const regions = await getRegions();
128
- console.log(chalk.cyan.bold("\n🌐 Available Prisma Postgres regions:\n"));
129
- regions.forEach((r) =>
130
- console.log(`- ${chalk.green(r.id)}, ${r.name || r.id}`)
131
- );
132
- console.log("");
133
- } catch (e) {
134
- handleError("Failed to fetch regions.", e);
135
- }
136
- }
137
-
138
- async function isOffline() {
139
- const healthUrl = `${CREATE_DB_WORKER_URL}/health`;
140
-
141
- try {
142
- const res = await fetch(healthUrl, { method: "GET" });
143
- if (!res.ok) {
144
- throw new Error(`Prisma Postgres API returned a status of ${res.status}`);
145
- }
146
- return false; // Online
147
- } catch {
148
- console.error(
149
- chalk.red.bold("\nāœ– Error: Cannot reach Prisma Postgres API server.\n")
150
- );
151
- console.error(
152
- chalk.gray(
153
- `Check your internet connection or visit ${chalk.green("https://www.prisma-status.com/\n")}`
154
- )
155
- );
156
- await flushAnalytics();
157
- process.exit(1);
158
- }
159
- }
160
-
161
- export function getCommandName() {
162
- const executable = process.argv[1] || "create-db";
163
- if (executable.includes("create-pg")) return "create-pg";
164
- if (executable.includes("create-postgres")) return "create-postgres";
165
- return "create-db";
166
- }
167
-
168
- const CLI_NAME = getCommandName();
169
-
170
- function readUserEnvFile() {
171
- const userCwd = process.cwd();
172
- const envPath = path.join(userCwd, ".env");
173
-
174
- if (!fs.existsSync(envPath)) {
175
- return {};
176
- }
177
-
178
- const envContent = fs.readFileSync(envPath, "utf8");
179
- const envVars = {};
180
-
181
- envContent.split("\n").forEach((line) => {
182
- const trimmed = line.trim();
183
- if (trimmed && !trimmed.startsWith("#")) {
184
- const [key, ...valueParts] = trimmed.split("=");
185
- if (key && valueParts.length > 0) {
186
- const value = valueParts.join("=").replace(/^["']|["']$/g, "");
187
- envVars[key.trim()] = value.trim();
188
- }
189
- }
190
- });
191
-
192
- return envVars;
193
- }
194
-
195
- async function showHelp() {
196
- let regionExamples = "us-east-1, eu-west-1";
197
- try {
198
- const regions = await getRegions();
199
- if (regions && regions.length > 0) {
200
- regionExamples = regions.map((r) => r.id).join(", ");
201
- }
202
- } catch {}
203
-
204
- console.log(`
205
- ${chalk.cyan.bold("Prisma Postgres Create DB")}
206
-
207
- Usage:
208
- ${chalk.green(`npx ${CLI_NAME} [options]`)}
209
-
210
- Options:
211
- ${chalk.yellow(`--region <region>, -r <region>`)} Specify the region (e.g., ${regionExamples})
212
- ${chalk.yellow("--interactive, -i")} Run in interactive mode to select a region and create the database
213
- ${chalk.yellow("--json, -j")} Output machine-readable JSON and exit
214
- ${chalk.yellow("--list-regions")} List available regions and exit
215
- ${chalk.yellow("--help, -h")} Show this help message
216
- ${chalk.yellow("--env, -e")} Prints DATABASE_URL to the terminal. ${chalk.gray(`To write to .env, use --env >> .env`)}
217
-
218
- Examples:
219
- ${chalk.gray(`npx ${CLI_NAME} --region us-east-1`)}
220
- ${chalk.gray(`npx ${CLI_NAME} -r us-east-1`)}
221
- ${chalk.gray(`npx ${CLI_NAME} --interactive`)}
222
- ${chalk.gray(`npx ${CLI_NAME} -i`)}
223
- ${chalk.gray(`npx ${CLI_NAME} --json --region us-east-1`)}
224
- ${chalk.gray(`npx ${CLI_NAME} --env --region us-east-1`)}
225
- ${chalk.gray(`npx ${CLI_NAME} --env >> .env`)}
226
- `);
227
- await flushAnalytics();
228
- process.exit(0);
229
- }
230
-
231
- async function parseArgs() {
232
- const args = process.argv.slice(2);
233
- const flags = {};
234
-
235
- const allowedFlags = [
236
- "region",
237
- "help",
238
- "list-regions",
239
- "interactive",
240
- "json",
241
- "env",
242
- ];
243
- const shorthandMap = {
244
- r: "region",
245
- i: "interactive",
246
- h: "help",
247
- j: "json",
248
- e: "env",
249
- };
250
-
251
- const exitWithError = (message) => {
252
- console.error(chalk.red.bold("\nāœ– " + message));
253
- console.error(chalk.gray("\nUse --help or -h to see available options.\n"));
254
- process.exit(1);
255
- };
256
-
257
- for (let i = 0; i < args.length; i++) {
258
- const arg = args[i];
259
-
260
- if (arg.startsWith("--")) {
261
- const flag = arg.slice(2);
262
- if (flag === "help") await showHelp();
263
- if (!allowedFlags.includes(flag))
264
- exitWithError(`Invalid flag: --${flag}`);
265
- if (flag === "region") {
266
- const region = args[i + 1];
267
- if (!region || region.startsWith("-"))
268
- exitWithError("Missing value for --region flag.");
269
- flags.region = region;
270
- i++;
271
- } else {
272
- flags[flag] = true;
273
- }
274
- continue;
275
- }
276
-
277
- if (arg.startsWith("-")) {
278
- const short = arg.slice(1);
279
-
280
- if (shorthandMap[short]) {
281
- const mappedFlag = shorthandMap[short];
282
- if (mappedFlag === "help") showHelp();
283
- if (mappedFlag === "region") {
284
- const region = args[i + 1];
285
- if (!region || region.startsWith("-"))
286
- exitWithError("Missing value for -r flag.");
287
- flags.region = region;
288
- i++;
289
- } else {
290
- flags[mappedFlag] = true;
291
- }
292
- continue;
293
- }
294
-
295
- for (const letter of short.split("")) {
296
- const mappedFlag = shorthandMap[letter];
297
- if (!mappedFlag) exitWithError(`Invalid flag: -${letter}`);
298
- if (mappedFlag === "help") {
299
- await showHelp();
300
- return;
301
- }
302
- if (mappedFlag === "region") {
303
- const region = args[i + 1];
304
- if (!region || region.startsWith("-"))
305
- exitWithError("Missing value for -r flag.");
306
- flags.region = region;
307
- i++;
308
- } else {
309
- flags[mappedFlag] = true;
310
- }
311
- }
312
- continue;
313
- }
314
-
315
- exitWithError(`Invalid argument: ${arg}`);
316
- }
317
-
318
- return { flags };
319
- }
320
-
321
- function validateFlagCombinations(flags) {
322
- const conflictingFlags = [
323
- ["env", "json"],
324
- ["list-regions", "env"],
325
- ["list-regions", "json"],
326
- ["list-regions", "interactive"],
327
- ["list-regions", "region"],
328
- ["interactive", "env"],
329
- ["interactive", "json"],
330
- ];
331
-
332
- for (const [flag1, flag2] of conflictingFlags) {
333
- if (flags[flag1] && flags[flag2]) {
334
- console.error(
335
- chalk.red.bold(
336
- `\nāœ– Error: Cannot use --${flag1} and --${flag2} together.\n`
337
- )
338
- );
339
- console.error(chalk.gray("Use --help or -h to see available options.\n"));
340
- process.exit(1);
341
- }
342
- }
343
- }
344
-
345
- export async function getRegions(returnJson = false) {
346
- const url = `${CREATE_DB_WORKER_URL}/regions`;
347
- const res = await fetch(url);
348
-
349
- if (!res.ok) {
350
- if (returnJson) {
351
- throw new Error(
352
- `Failed to fetch regions. Status: ${res.status} ${res.statusText}`
353
- );
354
- }
355
- handleError(
356
- `Failed to fetch regions. Status: ${res.status} ${res.statusText}`
357
- );
358
- }
359
-
360
- try {
361
- const data = await res.json();
362
- const regions = Array.isArray(data) ? data : data.data;
363
- return regions.filter((region) => region.status === "available");
364
- } catch (e) {
365
- if (returnJson) {
366
- throw new Error("Failed to parse JSON from /regions endpoint.");
367
- }
368
- handleError("Failed to parse JSON from /regions endpoint.", e);
369
- }
370
- }
371
-
372
- export async function validateRegion(region, returnJson = false) {
373
- const regions = await getRegions(returnJson);
374
- const regionIds = regions.map((r) => r.id);
375
-
376
- if (!regionIds.includes(region)) {
377
- if (returnJson) {
378
- throw new Error(
379
- `Invalid region: ${region}. Available regions: ${regionIds.join(", ")}`
380
- );
381
- }
382
- handleError(
383
- `Invalid region: ${chalk.yellow(region)}.\nAvailable regions: ${chalk.green(
384
- regionIds.join(", ")
385
- )}`
386
- );
387
- }
388
-
389
- return region;
390
- }
391
-
392
- function handleError(message, extra = "") {
393
- console.error(
394
- "\n" +
395
- chalk.red.bold("āœ– An error occurred!") +
396
- "\n\n" +
397
- chalk.white("Message: ") +
398
- chalk.yellow(message) +
399
- (extra
400
- ? "\n" + chalk.white("Available regions: ") + chalk.green(extra)
401
- : "") +
402
- "\n"
403
- );
404
- process.exit(1);
405
- }
406
-
407
- async function promptForRegion(defaultRegion, userAgent, cliRunId) {
408
- let regions;
409
- try {
410
- regions = await getRegions();
411
- } catch (e) {
412
- handleError("Failed to fetch regions.", e);
413
- }
414
-
415
- if (!regions || regions.length === 0) {
416
- handleError("No regions available to select.");
417
- }
418
-
419
- const region = await select({
420
- message: "Choose a region:",
421
- options: regions.map((r) => ({ value: r.id, label: r.id })),
422
- initialValue:
423
- regions.find((r) => r.id === defaultRegion)?.id || regions[0]?.id,
424
- });
425
-
426
- if (region === null) {
427
- cancel(chalk.red("Operation cancelled."));
428
- await flushAnalytics();
429
- process.exit(0);
430
- }
431
-
432
- void sendAnalyticsToWorker(
433
- "create_db:region_selected",
434
- {
435
- command: CLI_NAME,
436
- region: region,
437
- "selection-method": "interactive",
438
- "user-agent": userAgent,
439
- },
440
- cliRunId
441
- );
442
-
443
- return region;
444
- }
445
-
446
- async function createDatabase(
447
- name,
448
- region,
449
- userAgent,
450
- cliRunId,
451
- silent = false
452
- ) {
453
- let s;
454
- if (!silent) {
455
- s = spinner();
456
- s.start("Creating your database...");
457
- }
458
-
459
- const resp = await fetch(`${CREATE_DB_WORKER_URL}/create`, {
460
- method: "POST",
461
- headers: { "Content-Type": "application/json" },
462
- body: JSON.stringify({
463
- region,
464
- name,
465
- utm_source: CLI_NAME,
466
- userAgent,
467
- }),
468
- });
469
-
470
- if (resp.status === 429) {
471
- if (silent) {
472
- return {
473
- error: "rate_limit_exceeded",
474
- message:
475
- "We're experiencing a high volume of requests. Please try again later.",
476
- status: 429,
477
- };
478
- }
479
-
480
- if (s) {
481
- s.stop(
482
- "We're experiencing a high volume of requests. Please try again later."
483
- );
484
- }
485
-
486
- void sendAnalyticsToWorker(
487
- "create_db:database_creation_failed",
488
- {
489
- command: CLI_NAME,
490
- region: region,
491
- "error-type": "rate_limit",
492
- "status-code": 429,
493
- "user-agent": userAgent,
494
- },
495
- cliRunId
496
- );
497
-
498
- await flushAnalytics();
499
- process.exit(1);
500
- }
501
-
502
- let result;
503
- let raw;
504
- try {
505
- raw = await resp.text();
506
- result = JSON.parse(raw);
507
- } catch (e) {
508
- if (silent) {
509
- return {
510
- error: "invalid_json",
511
- message: "Unexpected response from create service.",
512
- raw,
513
- status: resp.status,
514
- };
515
- }
516
- if (s) {
517
- s.stop("Unexpected response from create service.");
518
- }
519
-
520
- void sendAnalyticsToWorker(
521
- "create_db:database_creation_failed",
522
- {
523
- command: CLI_NAME,
524
- region,
525
- "error-type": "invalid_json",
526
- "status-code": resp.status,
527
- "user-agent": userAgent,
528
- },
529
- cliRunId
530
- );
531
-
532
- await flushAnalytics();
533
- process.exit(1);
534
- }
535
-
536
- const database = result.data ? result.data.database : result.databases?.[0];
537
- const projectId = result.data ? result.data.id : result.id;
538
-
539
- const directConnDetails = result.data
540
- ? database?.apiKeys?.[0]?.directConnection
541
- : result.databases?.[0]?.apiKeys?.[0]?.ppgDirectConnection;
542
- const directUser = directConnDetails?.user
543
- ? encodeURIComponent(directConnDetails.user)
544
- : "";
545
- const directPass = directConnDetails?.pass
546
- ? encodeURIComponent(directConnDetails.pass)
547
- : "";
548
- const directHost = directConnDetails?.host;
549
- const directPort = directConnDetails?.port
550
- ? `:${directConnDetails.port}`
551
- : "";
552
- const directDbName = directConnDetails?.database || "postgres";
553
- const directConn =
554
- directConnDetails && directHost
555
- ? `postgresql://${directUser}:${directPass}@${directHost}${directPort}/${directDbName}?sslmode=require`
556
- : null;
557
-
558
- const claimUrl = `${CLAIM_DB_WORKER_URL}/claim?projectID=${projectId}&utm_source=${userAgent || CLI_NAME}&utm_medium=cli`;
559
- const expiryDate = new Date(Date.now() + 24 * 60 * 60 * 1000);
560
-
561
- if (silent && !result.error) {
562
- const jsonResponse = {
563
- connectionString: directConn,
564
- claimUrl: claimUrl,
565
- deletionDate: expiryDate.toISOString(),
566
- region: database?.region?.id || region,
567
- name: database?.name,
568
- projectId: projectId,
569
- };
570
-
571
- if (userAgent) {
572
- jsonResponse.userAgent = userAgent;
573
- }
574
-
575
- return jsonResponse;
576
- }
577
-
578
- if (result.error) {
579
- if (silent) {
580
- return {
581
- error: "api_error",
582
- message: result.error.message || "Unknown error",
583
- details: result.error,
584
- status: result.error.status ?? resp.status,
585
- };
586
- }
587
-
588
- if (s) {
589
- s.stop(
590
- `Error creating database: ${result.error.message || "Unknown error"}`
591
- );
592
- }
593
-
594
- void sendAnalyticsToWorker(
595
- "create_db:database_creation_failed",
596
- {
597
- command: CLI_NAME,
598
- region: region,
599
- "error-type": "api_error",
600
- "error-message": result.error.message,
601
- "user-agent": userAgent,
602
- },
603
- cliRunId
604
- );
605
-
606
- await flushAnalytics();
607
- process.exit(1);
608
- }
609
-
610
- if (s) {
611
- s.stop("Database created successfully!");
612
- }
613
-
614
- const expiryFormatted = expiryDate.toLocaleString();
615
-
616
- log.message("");
617
- log.info(chalk.bold("Database Connection"));
618
- log.message("");
619
-
620
- // Direct connection (only output this one)
621
- if (directConn) {
622
- log.message(chalk.cyan(" Connection String:"));
623
- log.message(" " + chalk.yellow(directConn));
624
- log.message("");
625
- } else {
626
- log.warning(chalk.yellow(" Connection details are not available."));
627
- log.message("");
628
- }
629
-
630
-
631
- // Claim database section
632
- const clickableUrl = terminalLink(claimUrl, claimUrl, { fallback: false });
633
- log.success(chalk.bold("Claim Your Database"));
634
- log.message(chalk.cyan(" Keep your database for free:"));
635
- log.message(" " + chalk.yellow(clickableUrl));
636
- log.message(
637
- chalk.italic(
638
- chalk.gray(
639
- ` Database will be deleted on ${expiryFormatted} if not claimed.`
640
- )
641
- )
642
- );
643
-
644
- void sendAnalyticsToWorker(
645
- "create_db:database_created",
646
- {
647
- command: CLI_NAME,
648
- region,
649
- utm_source: CLI_NAME,
650
- },
651
- cliRunId
652
- );
653
- }
654
-
655
- export async function main() {
656
- try {
657
- // Generate unique ID for this CLI run
658
- const cliRunId = randomUUID();
659
-
660
- const rawArgs = process.argv.slice(2);
661
-
662
- const { flags } = await parseArgs();
663
-
664
- validateFlagCombinations(flags);
665
-
666
- let userAgent;
667
- const userEnvVars = readUserEnvFile();
668
- if (userEnvVars.PRISMA_ACTOR_NAME && userEnvVars.PRISMA_ACTOR_PROJECT) {
669
- userAgent = `${userEnvVars.PRISMA_ACTOR_NAME}/${userEnvVars.PRISMA_ACTOR_PROJECT}`;
670
- }
671
-
672
- void sendAnalyticsToWorker(
673
- "create_db:cli_command_ran",
674
- {
675
- command: CLI_NAME,
676
- "full-command": `${CLI_NAME} ${rawArgs.join(" ")}`.trim(),
677
- "has-region-flag":
678
- rawArgs.includes("--region") || rawArgs.includes("-r"),
679
- "has-interactive-flag":
680
- rawArgs.includes("--interactive") || rawArgs.includes("-i"),
681
- "has-help-flag": rawArgs.includes("--help") || rawArgs.includes("-h"),
682
- "has-list-regions-flag": rawArgs.includes("--list-regions"),
683
- "has-json-flag": rawArgs.includes("--json") || rawArgs.includes("-j"),
684
- "has-env-flag": rawArgs.includes("--env") || rawArgs.includes("-e"),
685
- "has-user-agent-from-env": !!userAgent,
686
- "node-version": process.version,
687
- platform: process.platform,
688
- arch: process.arch,
689
- "user-agent": userAgent,
690
- },
691
- cliRunId
692
- );
693
-
694
- if (!flags.help && !flags.json) {
695
- await isOffline();
696
- }
697
-
698
- let name = new Date().toISOString();
699
- let region = flags.region || "us-east-1";
700
- if (!flags.region || !flags.interactive) {
701
- const userLocation = await detectUserLocation();
702
- region = getRegionClosestToLocation(userLocation) || region;
703
- }
704
- let chooseRegionPrompt = false;
705
-
706
- if (flags.help) {
707
- return;
708
- }
709
-
710
- if (flags["list-regions"]) {
711
- await listRegions();
712
- await flushAnalytics();
713
- process.exit(0);
714
- }
715
-
716
- if (flags.region) {
717
- region = flags.region;
718
-
719
- void sendAnalyticsToWorker(
720
- "create_db:region_selected",
721
- {
722
- command: CLI_NAME,
723
- region: region,
724
- "selection-method": "flag",
725
- "user-agent": userAgent,
726
- },
727
- cliRunId
728
- );
729
- }
730
-
731
- if (flags.interactive) {
732
- chooseRegionPrompt = true;
733
- }
734
-
735
- if (flags.json) {
736
- try {
737
- if (chooseRegionPrompt) {
738
- region = await promptForRegion(region, userAgent, cliRunId);
739
- } else {
740
- await validateRegion(region, true);
741
- }
742
- const result = await createDatabase(
743
- name,
744
- region,
745
- userAgent,
746
- cliRunId,
747
- true
748
- );
749
- console.log(JSON.stringify(result, null, 2));
750
- await flushAnalytics();
751
- process.exit(0);
752
- } catch (e) {
753
- console.log(
754
- JSON.stringify(
755
- { error: "cli_error", message: e?.message || String(e) },
756
- null,
757
- 2
758
- )
759
- );
760
- await flushAnalytics();
761
- process.exit(1);
762
- }
763
- }
764
-
765
- if (flags.env) {
766
- try {
767
- if (chooseRegionPrompt) {
768
- region = await promptForRegion(region, userAgent, cliRunId);
769
- } else {
770
- await validateRegion(region, true);
771
- }
772
- const result = await createDatabase(
773
- name,
774
- region,
775
- userAgent,
776
- cliRunId,
777
- true
778
- );
779
- if (result.error) {
780
- console.error(result.message || "Unknown error");
781
- await flushAnalytics();
782
- process.exit(1);
783
- }
784
- console.log(`DATABASE_URL="${result.connectionString}"`);
785
- console.error("\n# Claim your database at: " + result.claimUrl);
786
- await flushAnalytics();
787
- process.exit(0);
788
- } catch (e) {
789
- console.error(e?.message || String(e));
790
- await flushAnalytics();
791
- process.exit(1);
792
- }
793
- }
794
-
795
- intro(chalk.cyan.bold("šŸš€ Creating a Prisma Postgres database"));
796
- log.message(
797
- chalk.white(`Provisioning a temporary database in ${region}...`)
798
- );
799
- log.message(
800
- chalk.gray(
801
- `It will be automatically deleted in 24 hours, but you can claim it.`
802
- )
803
- );
804
- if (chooseRegionPrompt) {
805
- region = await promptForRegion(region, userAgent, cliRunId);
806
- }
807
-
808
- region = await validateRegion(region);
809
-
810
- await createDatabase(name, region, userAgent, cliRunId);
811
-
812
- outro("");
813
- await flushAnalytics();
814
- } catch (error) {
815
- console.error("Error:", error.message);
816
- await flushAnalytics();
817
- process.exit(1);
818
- }
819
- }
820
-
821
- // Run main() if this file is being executed directly
822
- const isDirectExecution =
823
- import.meta.url.endsWith("/index.js") ||
824
- process.argv[1] === import.meta.url.replace("file://", "") ||
825
- process.argv[1].includes("create-db") ||
826
- process.argv[1].includes("create-pg") ||
827
- process.argv[1].includes("create-postgres");
828
-
829
- if (isDirectExecution && !process.env.__CREATE_DB_EXECUTING) {
830
- process.env.__CREATE_DB_EXECUTING = "true";
831
- main().catch(console.error);
832
- }
833
-
834
- // if (import.meta.url.endsWith('/index.js') || process.argv[1] === import.meta.url.replace('file://', '')) {
835
- // main().catch(console.error);
836
- // }