@@ -38,11 +38,27 @@ async function packageManagerInstall({
3838 } ) ;
3939
4040 // Simulate incremental progress
41- let progress = 0 ;
41+ // Start from 50% (where we left off) and go up to 88% max
42+ // This leaves room for the actual completion and final steps
43+ // On Windows, npm can be slow, so we continue updating to show activity
44+ let progress = 50 ;
45+ let lastProgressUpdate = Date . now ( ) ;
4246 const interval = setInterval ( ( ) => {
43- if ( progress < 90 ) {
44- progress += 5 ;
45- progressBar . update ( progress ) ;
47+ const now = Date . now ( ) ;
48+ // If we haven't received real progress updates in a while, continue incrementing
49+ // This prevents the progress bar from appearing stuck on slow Windows systems
50+ if ( progress < 88 ) {
51+ // Increment slower as we approach the limit to avoid hitting it too quickly
52+ const increment = progress < 70 ? 3 : 1 ;
53+ progress = Math . min ( progress + increment , 88 ) ;
54+ progressBar . update ( progress , {
55+ doing : "Installing dependencies..." ,
56+ } ) ;
57+ } else if ( now - lastProgressUpdate > 3000 ) {
58+ // Even at max, update the "doing" text to show it's still working
59+ progressBar . update ( progress , {
60+ doing : "Installing dependencies..." ,
61+ } ) ;
4662 }
4763 } , 1000 ) ;
4864
@@ -56,15 +72,35 @@ async function packageManagerInstall({
5672
5773 if ( npmProgressMatch ) {
5874 const [ , current , total , task ] = npmProgressMatch ;
59- progress = Math . round (
60- ( parseInt ( current ) / parseInt ( total ) ) * 100 ,
61- ) ;
75+ // Map npm progress (0-100%) to our range (50-90%)
76+ const npmProgress = ( parseInt ( current ) / parseInt ( total ) ) * 100 ;
77+ progress = Math . round ( 50 + npmProgress * 0.4 ) ; // 50% + (0-100% * 0.4) = 50-90%
78+ lastProgressUpdate = Date . now ( ) ;
6279 progressBar . update ( progress , { doing : task } ) ;
63- } else {
80+ } else if ( cleanedOutput ) {
81+ lastProgressUpdate = Date . now ( ) ;
6482 progressBar . update ( progress , { doing : cleanedOutput } ) ;
6583 }
6684 } ) ;
6785
86+ // On Windows, npm may output progress to stderr
87+ installProcess . stderr ?. on ( "data" , ( data : Buffer ) => {
88+ const output = data . toString ( ) . trim ( ) ;
89+ const cleanedOutput = output . replace ( / \| \| .* $ / g, "" ) ;
90+ const npmProgressMatch = cleanedOutput . match (
91+ / \[ ( \d + ) \/ ( \d + ) \] (?: n p m ) ? ( [ \w \s ] + ) \. { 3 } / ,
92+ ) ;
93+
94+ if ( npmProgressMatch ) {
95+ const [ , current , total , task ] = npmProgressMatch ;
96+ // Map npm progress (0-100%) to our range (50-90%)
97+ const npmProgress = ( parseInt ( current ) / parseInt ( total ) ) * 100 ;
98+ progress = Math . round ( 50 + npmProgress * 0.4 ) ; // 50% + (0-100% * 0.4) = 50-90%
99+ lastProgressUpdate = Date . now ( ) ;
100+ progressBar . update ( progress , { doing : task } ) ;
101+ }
102+ } ) ;
103+
68104 installProcess . on ( "error" , ( error ) => {
69105 clearInterval ( interval ) ;
70106 progressBar . stop ( ) ;
@@ -74,8 +110,8 @@ async function packageManagerInstall({
74110 installProcess . on ( "close" , ( code ) => {
75111 clearInterval ( interval ) ;
76112 if ( code === 0 ) {
77- progressBar . update ( 100 , { doing : "Complete!" } ) ;
78- progressBar . stop ( ) ;
113+ // Update to 90% to leave room for final steps (package name change)
114+ progressBar . update ( 90 , { doing : "Dependencies installed" } ) ;
79115 resolve ( "Installation Done!" ) ;
80116 } else {
81117 progressBar . stop ( ) ;
@@ -338,7 +374,11 @@ const projectForm = async (
338374 } ) ;
339375 }
340376
341- progressBar . update ( 90 ) ;
377+ // Progress should already be at 90% from packageManagerInstall
378+ // Only update if we skipped installation
379+ if ( ! SKIP_INSTALL_FOR_TESTING ) {
380+ progressBar . update ( 90 , { doing : "Finalizing project" } ) ;
381+ }
342382
343383 changePackageName ( {
344384 directory : answer . name ,
0 commit comments