@@ -10,31 +10,49 @@ import chalk from "chalk";
1010
1111dotenv . config ( ) ;
1212
13- const CLI_RUN_ID = randomUUID ( ) ;
14-
1513const CREATE_DB_WORKER_URL =
1614 process . env . CREATE_DB_WORKER_URL || "https://create-db-temp.prisma.io" ;
1715const CLAIM_DB_WORKER_URL =
1816 process . env . CLAIM_DB_WORKER_URL || "https://create-db.prisma.io" ;
1917
20- async function sendAnalyticsToWorker ( eventName , properties ) {
18+ // Track pending analytics promises to ensure they complete before exit
19+ const pendingAnalytics = [ ] ;
20+
21+ async function sendAnalyticsToWorker ( eventName , properties , cliRunId ) {
2122 const controller = new AbortController ( ) ;
22- const timer = setTimeout ( ( ) => controller . abort ( ) , 2000 ) ;
23- try {
24- const payload = {
25- eventName,
26- properties : { distinct_id : CLI_RUN_ID , ...( properties || { } ) } ,
27- } ;
28- await fetch ( `${ CREATE_DB_WORKER_URL } /analytics` , {
29- method : "POST" ,
30- headers : { "Content-Type" : "application/json" } ,
31- body : JSON . stringify ( payload ) ,
32- signal : controller . signal ,
33- } ) ;
34- } catch ( error ) {
35- } finally {
36- clearTimeout ( timer ) ;
37- }
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 ] ) ;
3856}
3957
4058async function detectUserLocation ( ) {
@@ -135,6 +153,7 @@ async function isOffline() {
135153 `Check your internet connection or visit ${ chalk . green ( "https://www.prisma-status.com/\n" ) } `
136154 )
137155 ) ;
156+ await flushAnalytics ( ) ;
138157 process . exit ( 1 ) ;
139158 }
140159}
@@ -205,6 +224,7 @@ Examples:
205224 ${ chalk . gray ( `npx ${ CLI_NAME } --env --region us-east-1` ) }
206225 ${ chalk . gray ( `npx ${ CLI_NAME } --env >> .env` ) }
207226` ) ;
227+ await flushAnalytics ( ) ;
208228 process . exit ( 0 ) ;
209229}
210230
@@ -384,7 +404,7 @@ function handleError(message, extra = "") {
384404 process . exit ( 1 ) ;
385405}
386406
387- async function promptForRegion ( defaultRegion , userAgent ) {
407+ async function promptForRegion ( defaultRegion , userAgent , cliRunId ) {
388408 let regions ;
389409 try {
390410 regions = await getRegions ( ) ;
@@ -405,6 +425,7 @@ async function promptForRegion(defaultRegion, userAgent) {
405425
406426 if ( region === null ) {
407427 cancel ( chalk . red ( "Operation cancelled." ) ) ;
428+ await flushAnalytics ( ) ;
408429 process . exit ( 0 ) ;
409430 }
410431
@@ -413,12 +434,12 @@ async function promptForRegion(defaultRegion, userAgent) {
413434 region : region ,
414435 "selection-method" : "interactive" ,
415436 "user-agent" : userAgent ,
416- } ) ;
437+ } , cliRunId ) ;
417438
418439 return region ;
419440}
420441
421- async function createDatabase ( name , region , userAgent , silent = false ) {
442+ async function createDatabase ( name , region , userAgent , cliRunId , silent = false ) {
422443 let s ;
423444 if ( ! silent ) {
424445 s = spinner ( ) ;
@@ -458,8 +479,9 @@ async function createDatabase(name, region, userAgent, silent = false) {
458479 "error-type" : "rate_limit" ,
459480 "status-code" : 429 ,
460481 "user-agent" : userAgent ,
461- } ) ;
482+ } , cliRunId ) ;
462483
484+ await flushAnalytics ( ) ;
463485 process . exit ( 1 ) ;
464486 }
465487
@@ -487,8 +509,9 @@ async function createDatabase(name, region, userAgent, silent = false) {
487509 "error-type" : "invalid_json" ,
488510 "status-code" : resp . status ,
489511 "user-agent" : userAgent ,
490- } ) ;
512+ } , cliRunId ) ;
491513
514+ await flushAnalytics ( ) ;
492515 process . exit ( 1 ) ;
493516 }
494517
@@ -558,8 +581,9 @@ async function createDatabase(name, region, userAgent, silent = false) {
558581 "error-type" : "api_error" ,
559582 "error-message" : result . error . message ,
560583 "user-agent" : userAgent ,
561- } ) ;
584+ } , cliRunId ) ;
562585
586+ await flushAnalytics ( ) ;
563587 process . exit ( 1 ) ;
564588 }
565589
@@ -615,11 +639,14 @@ async function createDatabase(name, region, userAgent, silent = false) {
615639 command : CLI_NAME ,
616640 region,
617641 utm_source : CLI_NAME ,
618- } ) ;
642+ } , cliRunId ) ;
619643}
620644
621- async function main ( ) {
645+ export async function main ( ) {
622646 try {
647+ // Generate unique ID for this CLI run
648+ const cliRunId = randomUUID ( ) ;
649+
623650 const rawArgs = process . argv . slice ( 2 ) ;
624651
625652 const { flags } = await parseArgs ( ) ;
@@ -647,7 +674,7 @@ async function main() {
647674 platform : process . platform ,
648675 arch : process . arch ,
649676 "user-agent" : userAgent ,
650- } ) ;
677+ } , cliRunId ) ;
651678
652679 if ( ! flags . help && ! flags . json ) {
653680 await isOffline ( ) ;
@@ -667,6 +694,7 @@ async function main() {
667694
668695 if ( flags [ "list-regions" ] ) {
669696 await listRegions ( ) ;
697+ await flushAnalytics ( ) ;
670698 process . exit ( 0 ) ;
671699 }
672700
@@ -678,7 +706,7 @@ async function main() {
678706 region : region ,
679707 "selection-method" : "flag" ,
680708 "user-agent" : userAgent ,
681- } ) ;
709+ } , cliRunId ) ;
682710 }
683711
684712 if ( flags . interactive ) {
@@ -688,12 +716,13 @@ async function main() {
688716 if ( flags . json ) {
689717 try {
690718 if ( chooseRegionPrompt ) {
691- region = await promptForRegion ( region , userAgent ) ;
719+ region = await promptForRegion ( region , userAgent , cliRunId ) ;
692720 } else {
693721 await validateRegion ( region , true ) ;
694722 }
695- const result = await createDatabase ( name , region , userAgent , true ) ;
723+ const result = await createDatabase ( name , region , userAgent , cliRunId , true ) ;
696724 console . log ( JSON . stringify ( result , null , 2 ) ) ;
725+ await flushAnalytics ( ) ;
697726 process . exit ( 0 ) ;
698727 } catch ( e ) {
699728 console . log (
@@ -703,27 +732,31 @@ async function main() {
703732 2
704733 )
705734 ) ;
735+ await flushAnalytics ( ) ;
706736 process . exit ( 1 ) ;
707737 }
708738 }
709739
710740 if ( flags . env ) {
711741 try {
712742 if ( chooseRegionPrompt ) {
713- region = await promptForRegion ( region , userAgent ) ;
743+ region = await promptForRegion ( region , userAgent , cliRunId ) ;
714744 } else {
715745 await validateRegion ( region , true ) ;
716746 }
717- const result = await createDatabase ( name , region , userAgent , true ) ;
747+ const result = await createDatabase ( name , region , userAgent , cliRunId , true ) ;
718748 if ( result . error ) {
719749 console . error ( result . message || "Unknown error" ) ;
750+ await flushAnalytics ( ) ;
720751 process . exit ( 1 ) ;
721752 }
722753 console . log ( `DATABASE_URL="${ result . directConnectionString } "` ) ;
723754 console . error ( "\n# Claim your database at: " + result . claimUrl ) ;
755+ await flushAnalytics ( ) ;
724756 process . exit ( 0 ) ;
725757 } catch ( e ) {
726758 console . error ( e ?. message || String ( e ) ) ;
759+ await flushAnalytics ( ) ;
727760 process . exit ( 1 ) ;
728761 }
729762 }
@@ -738,18 +771,23 @@ async function main() {
738771 )
739772 ) ;
740773 if ( chooseRegionPrompt ) {
741- region = await promptForRegion ( region , userAgent ) ;
774+ region = await promptForRegion ( region , userAgent , cliRunId ) ;
742775 }
743776
744777 region = await validateRegion ( region ) ;
745778
746- await createDatabase ( name , region , userAgent ) ;
779+ await createDatabase ( name , region , userAgent , cliRunId ) ;
747780
748781 outro ( "" ) ;
782+ await flushAnalytics ( ) ;
749783 } catch ( error ) {
750784 console . error ( "Error:" , error . message ) ;
785+ await flushAnalytics ( ) ;
751786 process . exit ( 1 ) ;
752787 }
753788}
754789
755- main ( ) ;
790+ // Only run main() if this file is being executed directly, not when imported
791+ if ( import . meta. url === `file://${ process . argv [ 1 ] } ` ) {
792+ main ( ) ;
793+ }
0 commit comments