@@ -27,6 +27,19 @@ function prompt(question, defaultAnswer) {
2727 } ) ;
2828}
2929
30+ async function installDependencies ( ) {
31+ console . log ( `Installing dependencies ...` ) ;
32+ await run ( `cd ${ dirName } && npm install` ) ;
33+ }
34+
35+ async function initGit ( ) {
36+ console . log ( `Setting up Git ...` ) ;
37+ await run ( `rm -rf ${ dirName } /.git` ) ;
38+ await run (
39+ `cd ${ dirName } && git init && git add . && git commit -m "New Stackbit project"`
40+ ) ;
41+ }
42+
3043/* --- Parse CLI Arguments */
3144
3245const args = yargs ( hideBin ( process . argv ) )
@@ -35,6 +48,11 @@ const args = yargs(hideBin(process.argv))
3548 describe : "Choose a starter" ,
3649 choices : config . starters . map ( ( s ) => s . name ) ,
3750 } )
51+ . option ( "example" , {
52+ alias : "e" ,
53+ describe : "Start from an example" ,
54+ choices : config . examples . directories ,
55+ } )
3856 . help ( )
3957 . parse ( ) ;
4058
@@ -43,27 +61,23 @@ const args = yargs(hideBin(process.argv))
4361const starter = config . starters . find (
4462 ( s ) => s . name === ( args . starter ?? config . defaults . starter . name )
4563) ;
64+
65+ const timestamp = new Date ( ) . getTime ( ) ;
66+
4667const dirName =
4768 args . _ [ 0 ] ?? `${ config . defaults . dirName } -${ nanoid ( 8 ) . toLowerCase ( ) } ` ;
4869
49- /* --- New Project --- */
70+ /* --- New Project from Starter --- */
5071
5172async function cloneStarter ( ) {
5273 // Clone repo
5374 const cloneCommand = `git clone --depth=1 ${ starter . repoUrl } ${ dirName } ` ;
5475 console . log ( `\nCreating new project in ${ dirName } ...` ) ;
5576 await run ( cloneCommand ) ;
5677
57- // Install dependencies
58- console . log ( `Installing dependencies ...` ) ;
59- await run ( `cd ${ dirName } && npm install` ) ;
60-
61- // Set up git
62- console . log ( `Setting up Git ...` ) ;
63- await run ( `rm -rf ${ dirName } /.git` ) ;
64- await run (
65- `cd ${ dirName } && git init && git add . && git commit -m "New Stackbit project"`
66- ) ;
78+ // Project Setup
79+ await installDependencies ( ) ;
80+ await initGit ( ) ;
6781
6882 // Output next steps:
6983 console . log ( `
@@ -75,6 +89,37 @@ Follow the instructions for getting Started here:
7589 ` ) ;
7690}
7791
92+ /* --- New Project from Example --- */
93+
94+ async function cloneExample ( ) {
95+ const tmpDir = `examples-sparse-${ timestamp } ` ;
96+ console . log ( `\nCreating new project in ${ dirName } ...` ) ;
97+
98+ // Sparse clone the monorepo.
99+ await run (
100+ `git clone --depth 1 --filter=blob:none --sparse ${ config . examples . repoUrl } ${ tmpDir } `
101+ ) ;
102+ // Checkout just the example dir.
103+ await run ( `cd ${ tmpDir } && git sparse-checkout set ${ args . example } ` ) ;
104+ // Copy out into a new directory within current working directory.
105+ await run ( `cp -R ${ tmpDir } /${ args . example } ${ dirName } ` ) ;
106+ // Delete the clone.
107+ await run ( `rm -rf ${ tmpDir } ` ) ;
108+
109+ // Project Setup
110+ await installDependencies ( ) ;
111+ await initGit ( ) ;
112+
113+ // Output next steps:
114+ console . log ( `
115+ 🎉 ${ chalk . bold ( "Your example project is ready!" ) } 🎉
116+
117+ Follow the instructions and learn more about the example here:
118+
119+ ${ config . examples . repoUrl } /tree/main/${ args . example } #readme
120+ ` ) ;
121+ }
122+
78123/* --- Existing Project --- */
79124
80125async function integrateStackbit ( ) {
@@ -96,9 +141,22 @@ Visit the following URL to learn more about the integration process:
96141
97142/* --- Run --- */
98143
99- const packageJsonFilePath = path . join ( process . cwd ( ) , "package.json" ) ;
100- const hasPackageJson = fs . existsSync ( packageJsonFilePath ) ;
101- const runFunc = hasPackageJson ? integrateStackbit : cloneStarter ;
102- await runFunc ( ) ;
144+ async function doCreate ( ) {
145+ // If the current directory has a package.json file, we assume we're in an
146+ // active project, and will not create a new project.
147+ const packageJsonFilePath = path . join ( process . cwd ( ) , "package.json" ) ;
148+ if ( fs . existsSync ( packageJsonFilePath ) ) return integrateStackbit ( ) ;
149+ // If both starter and example were specified, throw an error message.
150+ if ( args . starter && args . example ) {
151+ console . error ( "[ERROR] Cannot specify a starter and an example." ) ;
152+ process . exit ( 1 ) ;
153+ }
154+ // Start from an example if specified.
155+ if ( args . example ) return cloneExample ( ) ;
156+ // Otherwise, use a starter, which falls back to the default if not set.
157+ return cloneStarter ( ) ;
158+ }
159+
160+ await doCreate ( ) ;
103161
104162rl . close ( ) ;
0 commit comments