create-db 1.0.3-pr48-DC-4894-posthog-fix-17267509345.0 → 1.0.3-pr48-DC-4894-posthog-fix-17269833204.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 +116 -39
- package/package.json +1 -1
- package/analytics.js +0 -53
package/index.js
CHANGED
|
@@ -6,13 +6,101 @@ dotenv.config();
|
|
|
6
6
|
import { select, spinner, intro, outro, log, cancel } from "@clack/prompts";
|
|
7
7
|
import chalk from "chalk";
|
|
8
8
|
import terminalLink from "terminal-link";
|
|
9
|
-
|
|
9
|
+
|
|
10
|
+
async function sendAnalyticsToWorker(eventName, properties = {}) {
|
|
11
|
+
try {
|
|
12
|
+
const response = await fetch(`${CREATE_DB_WORKER_URL}/analytics`, {
|
|
13
|
+
method: "POST",
|
|
14
|
+
headers: { "Content-Type": "application/json" },
|
|
15
|
+
body: JSON.stringify({ eventName, properties }),
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
if (!response.ok) {
|
|
19
|
+
throw new Error(
|
|
20
|
+
`Analytics request failed: ${response.status} ${response.statusText}`
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const result = await response.json();
|
|
25
|
+
if (result.status === "success") {
|
|
26
|
+
} else {
|
|
27
|
+
}
|
|
28
|
+
} catch (error) {}
|
|
29
|
+
}
|
|
10
30
|
|
|
11
31
|
const CREATE_DB_WORKER_URL =
|
|
12
32
|
process.env.CREATE_DB_WORKER_URL || "https://create-db-temp.prisma.io";
|
|
13
33
|
const CLAIM_DB_WORKER_URL =
|
|
14
34
|
process.env.CLAIM_DB_WORKER_URL || "https://create-db.prisma.io";
|
|
15
35
|
|
|
36
|
+
async function detectUserLocation() {
|
|
37
|
+
try {
|
|
38
|
+
const response = await fetch("https://ipapi.co/json/", {
|
|
39
|
+
method: "GET",
|
|
40
|
+
headers: {
|
|
41
|
+
"User-Agent": "create-db-cli/1.0",
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
if (!response.ok) {
|
|
46
|
+
throw new Error(`Failed to fetch location data: ${response.status}`);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const data = await response.json();
|
|
50
|
+
return {
|
|
51
|
+
country: data.country_code,
|
|
52
|
+
continent: data.continent_code,
|
|
53
|
+
city: data.city,
|
|
54
|
+
region: data.region,
|
|
55
|
+
latitude: data.latitude,
|
|
56
|
+
longitude: data.longitude,
|
|
57
|
+
};
|
|
58
|
+
} catch (error) {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Region coordinates (latitude, longitude)
|
|
64
|
+
const REGION_COORDINATES = {
|
|
65
|
+
"ap-southeast-1": { lat: 1.3521, lng: 103.8198 }, // Singapore
|
|
66
|
+
"ap-northeast-1": { lat: 35.6762, lng: 139.6503 }, // Tokyo
|
|
67
|
+
"eu-central-1": { lat: 50.1109, lng: 8.6821 }, // Frankfurt
|
|
68
|
+
"eu-west-3": { lat: 48.8566, lng: 2.3522 }, // Paris
|
|
69
|
+
"us-east-1": { lat: 38.9072, lng: -77.0369 }, // N. Virginia
|
|
70
|
+
"us-west-1": { lat: 37.7749, lng: -122.4194 }, // N. California
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
function getRegionClosestToLocation(userLocation) {
|
|
74
|
+
if (!userLocation) return null;
|
|
75
|
+
|
|
76
|
+
const userLat = parseFloat(userLocation.latitude);
|
|
77
|
+
const userLng = parseFloat(userLocation.longitude);
|
|
78
|
+
|
|
79
|
+
let closestRegion = null;
|
|
80
|
+
let minDistance = Infinity;
|
|
81
|
+
|
|
82
|
+
for (const [region, coordinates] of Object.entries(REGION_COORDINATES)) {
|
|
83
|
+
// Simple distance calculation using Haversine formula
|
|
84
|
+
const latDiff = ((userLat - coordinates.lat) * Math.PI) / 180;
|
|
85
|
+
const lngDiff = ((userLng - coordinates.lng) * Math.PI) / 180;
|
|
86
|
+
const a =
|
|
87
|
+
Math.sin(latDiff / 2) * Math.sin(latDiff / 2) +
|
|
88
|
+
Math.cos((userLat * Math.PI) / 180) *
|
|
89
|
+
Math.cos((coordinates.lat * Math.PI) / 180) *
|
|
90
|
+
Math.sin(lngDiff / 2) *
|
|
91
|
+
Math.sin(lngDiff / 2);
|
|
92
|
+
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
|
93
|
+
const distance = 6371 * c; // Earth radius in km
|
|
94
|
+
|
|
95
|
+
if (distance < minDistance) {
|
|
96
|
+
minDistance = distance;
|
|
97
|
+
closestRegion = region;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return closestRegion;
|
|
102
|
+
}
|
|
103
|
+
|
|
16
104
|
async function listRegions() {
|
|
17
105
|
try {
|
|
18
106
|
const regions = await getRegions();
|
|
@@ -264,14 +352,12 @@ async function promptForRegion(defaultRegion) {
|
|
|
264
352
|
}
|
|
265
353
|
|
|
266
354
|
try {
|
|
267
|
-
await
|
|
355
|
+
await sendAnalyticsToWorker("create_db:region_selected", {
|
|
268
356
|
command: CLI_NAME,
|
|
269
357
|
region: region,
|
|
270
358
|
"selection-method": "interactive",
|
|
271
359
|
});
|
|
272
|
-
} catch (error) {
|
|
273
|
-
console.error("Failed to send region_selected analytics :", error.message);
|
|
274
|
-
}
|
|
360
|
+
} catch (error) {}
|
|
275
361
|
|
|
276
362
|
return region;
|
|
277
363
|
}
|
|
@@ -286,7 +372,19 @@ async function createDatabase(name, region, returnJson = false) {
|
|
|
286
372
|
const resp = await fetch(`${CREATE_DB_WORKER_URL}/create`, {
|
|
287
373
|
method: "POST",
|
|
288
374
|
headers: { "Content-Type": "application/json" },
|
|
289
|
-
body: JSON.stringify({
|
|
375
|
+
body: JSON.stringify({
|
|
376
|
+
region,
|
|
377
|
+
name,
|
|
378
|
+
utm_source: CLI_NAME,
|
|
379
|
+
analytics: {
|
|
380
|
+
eventName: "create_db:database_created",
|
|
381
|
+
properties: {
|
|
382
|
+
command: CLI_NAME,
|
|
383
|
+
region: region,
|
|
384
|
+
utm_source: CLI_NAME,
|
|
385
|
+
},
|
|
386
|
+
},
|
|
387
|
+
}),
|
|
290
388
|
});
|
|
291
389
|
|
|
292
390
|
if (resp.status === 429) {
|
|
@@ -306,18 +404,13 @@ async function createDatabase(name, region, returnJson = false) {
|
|
|
306
404
|
}
|
|
307
405
|
|
|
308
406
|
try {
|
|
309
|
-
await
|
|
407
|
+
await sendAnalyticsToWorker("create_db:database_creation_failed", {
|
|
310
408
|
command: CLI_NAME,
|
|
311
409
|
region: region,
|
|
312
410
|
"error-type": "rate_limit",
|
|
313
411
|
"status-code": 429,
|
|
314
412
|
});
|
|
315
|
-
} catch (error) {
|
|
316
|
-
console.error(
|
|
317
|
-
"Failed to send database_creation_failed analytics:",
|
|
318
|
-
error.message
|
|
319
|
-
);
|
|
320
|
-
}
|
|
413
|
+
} catch (error) {}
|
|
321
414
|
|
|
322
415
|
process.exit(1);
|
|
323
416
|
}
|
|
@@ -340,18 +433,13 @@ async function createDatabase(name, region, returnJson = false) {
|
|
|
340
433
|
s.stop("Unexpected response from create service.");
|
|
341
434
|
}
|
|
342
435
|
try {
|
|
343
|
-
await
|
|
436
|
+
await sendAnalyticsToWorker("create_db:database_creation_failed", {
|
|
344
437
|
command: CLI_NAME,
|
|
345
438
|
region,
|
|
346
439
|
"error-type": "invalid_json",
|
|
347
440
|
"status-code": resp.status,
|
|
348
441
|
});
|
|
349
|
-
} catch (error) {
|
|
350
|
-
console.error(
|
|
351
|
-
"Failed to send database_creation_failed analytics:",
|
|
352
|
-
error.message
|
|
353
|
-
);
|
|
354
|
-
}
|
|
442
|
+
} catch (error) {}
|
|
355
443
|
process.exit(1);
|
|
356
444
|
}
|
|
357
445
|
|
|
@@ -409,18 +497,13 @@ async function createDatabase(name, region, returnJson = false) {
|
|
|
409
497
|
}
|
|
410
498
|
|
|
411
499
|
try {
|
|
412
|
-
await
|
|
500
|
+
await sendAnalyticsToWorker("create_db:database_creation_failed", {
|
|
413
501
|
command: CLI_NAME,
|
|
414
502
|
region: region,
|
|
415
503
|
"error-type": "api_error",
|
|
416
504
|
"error-message": result.error.message,
|
|
417
505
|
});
|
|
418
|
-
} catch (error) {
|
|
419
|
-
console.error(
|
|
420
|
-
"Failed to send database_creation_failed analytics:",
|
|
421
|
-
error.message
|
|
422
|
-
);
|
|
423
|
-
}
|
|
506
|
+
} catch (error) {}
|
|
424
507
|
process.exit(1);
|
|
425
508
|
}
|
|
426
509
|
|
|
@@ -477,7 +560,7 @@ async function main() {
|
|
|
477
560
|
try {
|
|
478
561
|
const rawArgs = process.argv.slice(2);
|
|
479
562
|
try {
|
|
480
|
-
await
|
|
563
|
+
await sendAnalyticsToWorker("create_db:cli_command_ran", {
|
|
481
564
|
command: CLI_NAME,
|
|
482
565
|
"full-command": `${CLI_NAME} ${rawArgs.join(" ")}`.trim(),
|
|
483
566
|
"has-region-flag":
|
|
@@ -491,9 +574,7 @@ async function main() {
|
|
|
491
574
|
platform: process.platform,
|
|
492
575
|
arch: process.arch,
|
|
493
576
|
});
|
|
494
|
-
} catch (error) {
|
|
495
|
-
console.error("Failed to send cli_command_ran analytics:", error.message);
|
|
496
|
-
}
|
|
577
|
+
} catch (error) {}
|
|
497
578
|
|
|
498
579
|
const { flags } = await parseArgs();
|
|
499
580
|
|
|
@@ -502,7 +583,8 @@ async function main() {
|
|
|
502
583
|
}
|
|
503
584
|
|
|
504
585
|
let name = new Date().toISOString();
|
|
505
|
-
let
|
|
586
|
+
let userLocation = await detectUserLocation();
|
|
587
|
+
let region = getRegionClosestToLocation(userLocation) || "us-east-1";
|
|
506
588
|
let chooseRegionPrompt = false;
|
|
507
589
|
|
|
508
590
|
if (flags.help) {
|
|
@@ -518,17 +600,12 @@ async function main() {
|
|
|
518
600
|
region = flags.region;
|
|
519
601
|
|
|
520
602
|
try {
|
|
521
|
-
await
|
|
603
|
+
await sendAnalyticsToWorker("create_db:region_selected", {
|
|
522
604
|
command: CLI_NAME,
|
|
523
605
|
region: region,
|
|
524
606
|
"selection-method": "flag",
|
|
525
607
|
});
|
|
526
|
-
} catch (error) {
|
|
527
|
-
console.error(
|
|
528
|
-
"Failed to send region_selected analytics:",
|
|
529
|
-
error.message
|
|
530
|
-
);
|
|
531
|
-
}
|
|
608
|
+
} catch (error) {}
|
|
532
609
|
}
|
|
533
610
|
|
|
534
611
|
if (flags.interactive) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-db",
|
|
3
|
-
"version": "1.0.3-pr48-DC-4894-posthog-fix-
|
|
3
|
+
"version": "1.0.3-pr48-DC-4894-posthog-fix-17269833204.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,53 +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_CAPTURE_URL = process.env.POSTHOG_API_HOST + "/capture";
|
|
12
|
-
const POSTHOG_KEY = process.env.POSTHOG_API_KEY;
|
|
13
|
-
console.log("POSTHOG_KEY set?", !!POSTHOG_KEY);
|
|
14
|
-
console.log("POSTHOG_CAPTURE_URL:", POSTHOG_CAPTURE_URL);
|
|
15
|
-
const payload = {
|
|
16
|
-
api_key: POSTHOG_KEY,
|
|
17
|
-
event: eventName,
|
|
18
|
-
distinct_id: randomUUID(),
|
|
19
|
-
properties: {
|
|
20
|
-
$process_person_profile: false,
|
|
21
|
-
...properties,
|
|
22
|
-
},
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
try {
|
|
26
|
-
const response = await fetch(POSTHOG_CAPTURE_URL, {
|
|
27
|
-
method: "POST",
|
|
28
|
-
headers: {
|
|
29
|
-
"Content-Type": "application/json",
|
|
30
|
-
},
|
|
31
|
-
body: JSON.stringify(payload),
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
if (!response.ok) {
|
|
35
|
-
throw new EventCaptureError(eventName, response.statusText);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// Log success message
|
|
39
|
-
console.log(`${eventName}: Success`);
|
|
40
|
-
} catch (error) {
|
|
41
|
-
// Log all analytics errors for debugging
|
|
42
|
-
console.error(`${eventName}: Failed - ${error.message}`);
|
|
43
|
-
|
|
44
|
-
// Re-throw the error so calling code can handle it if needed
|
|
45
|
-
throw error;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// Create a singleton instance
|
|
51
|
-
const analytics = new PosthogEventCapture();
|
|
52
|
-
|
|
53
|
-
export { analytics, EventCaptureError };
|