@@ -15,6 +15,7 @@ import { intro, log, multiselect, outro, spinner } from '@clack/prompts'
15
15
import { execa } from 'execa'
16
16
import { render } from 'ejs'
17
17
import { format } from 'prettier'
18
+ import chalk from 'chalk'
18
19
19
20
import {
20
21
SUPPORTED_PACKAGE_MANAGERS ,
@@ -64,6 +65,9 @@ type AddOn = {
64
65
args ?: Array < string >
65
66
}
66
67
readme ?: string
68
+ phase : 'setup' | 'add-on'
69
+ shadcnComponents ?: Array < string >
70
+ warning ?: string
67
71
}
68
72
69
73
interface Options {
@@ -306,11 +310,11 @@ async function copyFilesRecursively(
306
310
}
307
311
} else {
308
312
if ( source . endsWith ( '.ejs' ) ) {
309
- const target = source . replace ( '.ejs' , '' )
310
- await mkdir ( dirname ( target ) , {
313
+ const targetPath = target . replace ( '.ejs' , '' )
314
+ await mkdir ( dirname ( targetPath ) , {
311
315
recursive : true ,
312
316
} )
313
- await templateFile ( source , target )
317
+ await templateFile ( source , targetPath )
314
318
} else {
315
319
await mkdir ( dirname ( target ) , {
316
320
recursive : true ,
@@ -466,22 +470,57 @@ async function createApp(projectName: string, options: Required<Options>) {
466
470
)
467
471
468
472
// Copy all the asset files from the addons
469
- for ( const addOn of options . chosenAddOns ) {
470
- const addOnDir = resolve ( addOn . directory , 'assets' )
471
- if ( existsSync ( addOnDir ) ) {
472
- await copyFilesRecursively (
473
- addOnDir ,
474
- targetDir ,
475
- copyFile ,
476
- async ( file : string , targetFileName ?: string ) =>
477
- templateFile ( addOnDir , file , targetFileName ) ,
478
- )
473
+ const s = spinner ( )
474
+ for ( const phase of [ 'setup' , 'add-on' ] ) {
475
+ for ( const addOn of options . chosenAddOns . filter (
476
+ ( addOn ) => addOn . phase === phase ,
477
+ ) ) {
478
+ s . start ( `Setting up ${ addOn . name } ...` )
479
+ const addOnDir = resolve ( addOn . directory , 'assets' )
480
+ if ( existsSync ( addOnDir ) ) {
481
+ await copyFilesRecursively (
482
+ addOnDir ,
483
+ targetDir ,
484
+ copyFile ,
485
+ async ( file : string , targetFileName ?: string ) =>
486
+ templateFile ( addOnDir , file , targetFileName ) ,
487
+ )
488
+ }
489
+
490
+ if ( addOn . command ) {
491
+ await execa ( addOn . command . command , addOn . command . args || [ ] , {
492
+ cwd : targetDir ,
493
+ } )
494
+ }
495
+ s . stop ( `${ addOn . name } setup complete` )
479
496
}
497
+ }
480
498
481
- if ( addOn . command ) {
482
- await execa ( addOn . command . command , addOn . command . args || [ ] , {
499
+ if ( isAddOnEnabled ( 'shadcn' ) ) {
500
+ const shadcnComponents = new Set < string > ( )
501
+ for ( const addOn of options . chosenAddOns ) {
502
+ if ( addOn . shadcnComponents ) {
503
+ for ( const component of addOn . shadcnComponents ) {
504
+ shadcnComponents . add ( component )
505
+ }
506
+ }
507
+ }
508
+
509
+ if ( shadcnComponents . size > 0 ) {
510
+ s . start (
511
+ `Installing shadcn components (${ Array . from ( shadcnComponents ) . join ( ', ' ) } )...` ,
512
+ )
513
+ await execa ( 'npx' , [ 'shadcn@canary' , 'add' , ...shadcnComponents ] , {
483
514
cwd : targetDir ,
484
515
} )
516
+ s . stop ( `Installed shadcn components` )
517
+ }
518
+ }
519
+
520
+ const warnings : Array < string > = [ ]
521
+ for ( const addOn of options . chosenAddOns ) {
522
+ if ( addOn . warning ) {
523
+ warnings . push ( addOn . warning )
485
524
}
486
525
}
487
526
@@ -495,17 +534,20 @@ async function createApp(projectName: string, options: Required<Options>) {
495
534
await templateFile ( templateDirBase , 'README.md.ejs' )
496
535
497
536
// Install dependencies
498
- const s = spinner ( )
499
537
s . start ( `Installing dependencies via ${ options . packageManager } ...` )
500
538
await execa ( options . packageManager , [ 'install' ] , { cwd : targetDir } )
501
539
s . stop ( `Installed dependencies` )
502
540
541
+ if ( warnings . length > 0 ) {
542
+ log . warn ( chalk . red ( warnings . join ( '\n' ) ) )
543
+ }
544
+
503
545
outro ( `Created your new TanStack app in ${ targetDir } .
504
546
505
547
Use the following commands to start your app:
506
548
507
549
% cd ${ projectName }
508
- % ${ options . packageManager } start
550
+ % ${ options . packageManager } ${ isAddOnEnabled ( ' start' ) ? 'dev' : 'start' }
509
551
510
552
Please read README.md for more information on testing, styling, adding routes, react-query, etc.
511
553
` )
0 commit comments