create-db 1.0.4-pr45-DC-4829-source-flag-17244466791.0 → 1.0.4-pr48-DC-4894-posthog-fix-17272348089.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 +109 -35
- package/package.json +1 -1
- package/analytics.js +0 -63
package/index.js
CHANGED
|
@@ -9,13 +9,99 @@ dotenv.config();
|
|
|
9
9
|
import { select, spinner, intro, outro, log, cancel } from "@clack/prompts";
|
|
10
10
|
import chalk from "chalk";
|
|
11
11
|
import terminalLink from "terminal-link";
|
|
12
|
-
import { analytics } from "./analytics.js";
|
|
13
12
|
|
|
14
13
|
const CREATE_DB_WORKER_URL =
|
|
15
14
|
process.env.CREATE_DB_WORKER_URL || "https://create-db-temp.prisma.io";
|
|
16
15
|
const CLAIM_DB_WORKER_URL =
|
|
17
16
|
process.env.CLAIM_DB_WORKER_URL || "https://create-db.prisma.io";
|
|
18
17
|
|
|
18
|
+
async function sendAnalyticsToWorker(
|
|
19
|
+
eventName,
|
|
20
|
+
properties,
|
|
21
|
+
{ timeoutMs = 2000 }
|
|
22
|
+
) {
|
|
23
|
+
const controller = new AbortController();
|
|
24
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
25
|
+
try {
|
|
26
|
+
await fetch(`${CREATE_DB_WORKER_URL}/analytics`, {
|
|
27
|
+
method: "POST",
|
|
28
|
+
headers: { "Content-Type": "application/json" },
|
|
29
|
+
body: JSON.stringify({ eventName, properties }),
|
|
30
|
+
signal: controller.signal,
|
|
31
|
+
});
|
|
32
|
+
} catch (error) {
|
|
33
|
+
} finally {
|
|
34
|
+
clearTimeout(timer);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async function detectUserLocation() {
|
|
39
|
+
try {
|
|
40
|
+
const response = await fetch("https://ipapi.co/json/", {
|
|
41
|
+
method: "GET",
|
|
42
|
+
headers: {
|
|
43
|
+
"User-Agent": "create-db-cli/1.0",
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
if (!response.ok) {
|
|
48
|
+
throw new Error(`Failed to fetch location data: ${response.status}`);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const data = await response.json();
|
|
52
|
+
return {
|
|
53
|
+
country: data.country_code,
|
|
54
|
+
continent: data.continent_code,
|
|
55
|
+
city: data.city,
|
|
56
|
+
region: data.region,
|
|
57
|
+
latitude: data.latitude,
|
|
58
|
+
longitude: data.longitude,
|
|
59
|
+
};
|
|
60
|
+
} catch (error) {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const REGION_COORDINATES = {
|
|
66
|
+
"ap-southeast-1": { lat: 1.3521, lng: 103.8198 }, // Singapore
|
|
67
|
+
"ap-northeast-1": { lat: 35.6762, lng: 139.6503 }, // Tokyo
|
|
68
|
+
"eu-central-1": { lat: 50.1109, lng: 8.6821 }, // Frankfurt
|
|
69
|
+
"eu-west-3": { lat: 48.8566, lng: 2.3522 }, // Paris
|
|
70
|
+
"us-east-1": { lat: 38.9072, lng: -77.0369 }, // N. Virginia
|
|
71
|
+
"us-west-1": { lat: 37.7749, lng: -122.4194 }, // N. California
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
function getRegionClosestToLocation(userLocation) {
|
|
75
|
+
if (!userLocation) return null;
|
|
76
|
+
|
|
77
|
+
const userLat = parseFloat(userLocation.latitude);
|
|
78
|
+
const userLng = parseFloat(userLocation.longitude);
|
|
79
|
+
|
|
80
|
+
let closestRegion = null;
|
|
81
|
+
let minDistance = Infinity;
|
|
82
|
+
|
|
83
|
+
for (const [region, coordinates] of Object.entries(REGION_COORDINATES)) {
|
|
84
|
+
// Simple distance calculation using Haversine formula
|
|
85
|
+
const latDiff = ((userLat - coordinates.lat) * Math.PI) / 180;
|
|
86
|
+
const lngDiff = ((userLng - coordinates.lng) * Math.PI) / 180;
|
|
87
|
+
const a =
|
|
88
|
+
Math.sin(latDiff / 2) * Math.sin(latDiff / 2) +
|
|
89
|
+
Math.cos((userLat * Math.PI) / 180) *
|
|
90
|
+
Math.cos((coordinates.lat * Math.PI) / 180) *
|
|
91
|
+
Math.sin(lngDiff / 2) *
|
|
92
|
+
Math.sin(lngDiff / 2);
|
|
93
|
+
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
|
94
|
+
const distance = 6371 * c; // Earth radius in km
|
|
95
|
+
|
|
96
|
+
if (distance < minDistance) {
|
|
97
|
+
minDistance = distance;
|
|
98
|
+
closestRegion = region;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return closestRegion;
|
|
103
|
+
}
|
|
104
|
+
|
|
19
105
|
async function listRegions() {
|
|
20
106
|
try {
|
|
21
107
|
const regions = await getRegions();
|
|
@@ -292,14 +378,12 @@ async function promptForRegion(defaultRegion, userAgent) {
|
|
|
292
378
|
}
|
|
293
379
|
|
|
294
380
|
try {
|
|
295
|
-
|
|
381
|
+
await sendAnalyticsToWorker("create_db:region_selected", {
|
|
296
382
|
command: CLI_NAME,
|
|
297
383
|
region: region,
|
|
298
384
|
"selection-method": "interactive",
|
|
299
385
|
"user-agent": userAgent,
|
|
300
|
-
};
|
|
301
|
-
|
|
302
|
-
await analytics.capture("create_db:region_selected", analyticsProps);
|
|
386
|
+
});
|
|
303
387
|
} catch (error) {}
|
|
304
388
|
|
|
305
389
|
return region;
|
|
@@ -339,18 +423,13 @@ async function createDatabase(name, region, userAgent, returnJson = false) {
|
|
|
339
423
|
}
|
|
340
424
|
|
|
341
425
|
try {
|
|
342
|
-
|
|
426
|
+
await sendAnalyticsToWorker("create_db:database_creation_failed", {
|
|
343
427
|
command: CLI_NAME,
|
|
344
428
|
region: region,
|
|
345
429
|
"error-type": "rate_limit",
|
|
346
430
|
"status-code": 429,
|
|
347
431
|
"user-agent": userAgent,
|
|
348
|
-
};
|
|
349
|
-
|
|
350
|
-
await analytics.capture(
|
|
351
|
-
"create_db:database_creation_failed",
|
|
352
|
-
analyticsProps
|
|
353
|
-
);
|
|
432
|
+
});
|
|
354
433
|
} catch (error) {}
|
|
355
434
|
|
|
356
435
|
process.exit(1);
|
|
@@ -374,18 +453,13 @@ async function createDatabase(name, region, userAgent, returnJson = false) {
|
|
|
374
453
|
s.stop("Unexpected response from create service.");
|
|
375
454
|
}
|
|
376
455
|
try {
|
|
377
|
-
|
|
456
|
+
await sendAnalyticsToWorker("create_db:database_creation_failed", {
|
|
378
457
|
command: CLI_NAME,
|
|
379
458
|
region,
|
|
380
459
|
"error-type": "invalid_json",
|
|
381
460
|
"status-code": resp.status,
|
|
382
461
|
"user-agent": userAgent,
|
|
383
|
-
};
|
|
384
|
-
|
|
385
|
-
await analytics.capture(
|
|
386
|
-
"create_db:database_creation_failed",
|
|
387
|
-
analyticsProps
|
|
388
|
-
);
|
|
462
|
+
});
|
|
389
463
|
} catch (error) {}
|
|
390
464
|
process.exit(1);
|
|
391
465
|
}
|
|
@@ -450,18 +524,13 @@ async function createDatabase(name, region, userAgent, returnJson = false) {
|
|
|
450
524
|
}
|
|
451
525
|
|
|
452
526
|
try {
|
|
453
|
-
|
|
527
|
+
await sendAnalyticsToWorker("create_db:database_creation_failed", {
|
|
454
528
|
command: CLI_NAME,
|
|
455
529
|
region: region,
|
|
456
530
|
"error-type": "api_error",
|
|
457
531
|
"error-message": result.error.message,
|
|
458
532
|
"user-agent": userAgent,
|
|
459
|
-
};
|
|
460
|
-
|
|
461
|
-
await analytics.capture(
|
|
462
|
-
"create_db:database_creation_failed",
|
|
463
|
-
analyticsProps
|
|
464
|
-
);
|
|
533
|
+
});
|
|
465
534
|
} catch (error) {}
|
|
466
535
|
process.exit(1);
|
|
467
536
|
}
|
|
@@ -513,6 +582,14 @@ async function createDatabase(name, region, userAgent, returnJson = false) {
|
|
|
513
582
|
)
|
|
514
583
|
)
|
|
515
584
|
);
|
|
585
|
+
|
|
586
|
+
try {
|
|
587
|
+
await sendAnalyticsToWorker("create_db:database_created", {
|
|
588
|
+
command: CLI_NAME,
|
|
589
|
+
region,
|
|
590
|
+
utm_source: CLI_NAME,
|
|
591
|
+
});
|
|
592
|
+
} catch {}
|
|
516
593
|
}
|
|
517
594
|
|
|
518
595
|
async function main() {
|
|
@@ -528,7 +605,7 @@ async function main() {
|
|
|
528
605
|
}
|
|
529
606
|
|
|
530
607
|
try {
|
|
531
|
-
|
|
608
|
+
await sendAnalyticsToWorker("create_db:cli_command_ran", {
|
|
532
609
|
command: CLI_NAME,
|
|
533
610
|
"full-command": `${CLI_NAME} ${rawArgs.join(" ")}`.trim(),
|
|
534
611
|
"has-region-flag":
|
|
@@ -543,9 +620,7 @@ async function main() {
|
|
|
543
620
|
platform: process.platform,
|
|
544
621
|
arch: process.arch,
|
|
545
622
|
"user-agent": userAgent,
|
|
546
|
-
};
|
|
547
|
-
|
|
548
|
-
await analytics.capture("create_db:cli_command_ran", analyticsProps);
|
|
623
|
+
});
|
|
549
624
|
} catch (error) {
|
|
550
625
|
console.error("Error:", error.message);
|
|
551
626
|
}
|
|
@@ -555,7 +630,8 @@ async function main() {
|
|
|
555
630
|
}
|
|
556
631
|
|
|
557
632
|
let name = new Date().toISOString();
|
|
558
|
-
let
|
|
633
|
+
let userLocation = await detectUserLocation();
|
|
634
|
+
let region = getRegionClosestToLocation(userLocation) || "us-east-1";
|
|
559
635
|
let chooseRegionPrompt = false;
|
|
560
636
|
|
|
561
637
|
if (flags.help) {
|
|
@@ -571,14 +647,12 @@ async function main() {
|
|
|
571
647
|
region = flags.region;
|
|
572
648
|
|
|
573
649
|
try {
|
|
574
|
-
|
|
650
|
+
await sendAnalyticsToWorker("create_db:region_selected", {
|
|
575
651
|
command: CLI_NAME,
|
|
576
652
|
region: region,
|
|
577
653
|
"selection-method": "flag",
|
|
578
654
|
"user-agent": userAgent,
|
|
579
|
-
};
|
|
580
|
-
|
|
581
|
-
await analytics.capture("create_db:region_selected", analyticsProps);
|
|
655
|
+
});
|
|
582
656
|
} catch (error) {}
|
|
583
657
|
}
|
|
584
658
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-db",
|
|
3
|
-
"version": "1.0.4-
|
|
3
|
+
"version": "1.0.4-pr48-DC-4894-posthog-fix-17272348089.0",
|
|
4
4
|
"description": "Instantly create a temporary Prisma Postgres database with one command, then claim and persist it in your Prisma Data Platform project when ready.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"author": "",
|
package/analytics.js
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import { randomUUID } from "crypto";
|
|
2
|
-
|
|
3
|
-
class EventCaptureError extends Error {
|
|
4
|
-
constructor(event, status) {
|
|
5
|
-
super(`Failed to submit PostHog event '${event}': ${status}`);
|
|
6
|
-
}
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
class PosthogEventCapture {
|
|
10
|
-
async capture(eventName, properties = {}) {
|
|
11
|
-
const POSTHOG_API_HOST = process.env.POSTHOG_API_HOST;
|
|
12
|
-
const POSTHOG_KEY = process.env.POSTHOG_API_KEY;
|
|
13
|
-
|
|
14
|
-
if (
|
|
15
|
-
!POSTHOG_API_HOST ||
|
|
16
|
-
!POSTHOG_KEY ||
|
|
17
|
-
POSTHOG_API_HOST.trim() === "" ||
|
|
18
|
-
POSTHOG_KEY.trim() === ""
|
|
19
|
-
) {
|
|
20
|
-
if (process.env.NODE_ENV === "development") {
|
|
21
|
-
console.warn(
|
|
22
|
-
"Analytics disabled: missing POSTHOG_API_HOST or POSTHOG_API_KEY."
|
|
23
|
-
);
|
|
24
|
-
}
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const POSTHOG_CAPTURE_URL = `${POSTHOG_API_HOST.replace(/\/+$/, "")}/capture`;
|
|
29
|
-
|
|
30
|
-
const payload = {
|
|
31
|
-
api_key: POSTHOG_KEY,
|
|
32
|
-
event: eventName,
|
|
33
|
-
distinct_id: randomUUID(),
|
|
34
|
-
properties: {
|
|
35
|
-
$process_person_profile: false,
|
|
36
|
-
...properties,
|
|
37
|
-
},
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
try {
|
|
41
|
-
const response = await fetch(POSTHOG_CAPTURE_URL, {
|
|
42
|
-
method: "POST",
|
|
43
|
-
headers: {
|
|
44
|
-
"Content-Type": "application/json",
|
|
45
|
-
},
|
|
46
|
-
body: JSON.stringify(payload),
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
if (!response.ok) {
|
|
50
|
-
throw new EventCaptureError(eventName, response.statusText);
|
|
51
|
-
}
|
|
52
|
-
} catch (error) {
|
|
53
|
-
if (process.env.NODE_ENV === "development") {
|
|
54
|
-
console.error("Analytics error:", error.message);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Create a singleton instance
|
|
61
|
-
const analytics = new PosthogEventCapture();
|
|
62
|
-
|
|
63
|
-
export { analytics, EventCaptureError };
|