1
1
#!/usr/bin/env node
2
2
3
- import chalk from " chalk" ;
4
- import { exec } from " child_process" ;
5
- import fs from "fs" ;
6
- import path from " path" ;
7
- import readline from " readline" ;
8
- import util from " util" ;
9
- import yargs from " yargs" ;
10
- import { hideBin } from " yargs/helpers" ;
3
+ import chalk from ' chalk'
4
+ import { exec } from ' child_process'
5
+ import fs from 'fs-extra'
6
+ import path from ' path'
7
+ import readline from ' readline'
8
+ import util from ' util'
9
+ import yargs from ' yargs'
10
+ import { hideBin } from ' yargs/helpers'
11
11
12
- import config from " ./config.js" ;
12
+ import config from ' ./config.js'
13
13
14
14
/* --- Helpers --- */
15
15
16
- const run = util . promisify ( exec ) ;
16
+ const run = util . promisify ( exec )
17
17
18
18
const rl = readline . createInterface ( {
19
19
input : process . stdin ,
20
20
output : process . stdout ,
21
- } ) ;
21
+ } )
22
22
23
23
function prompt ( question , defaultAnswer ) {
24
24
return new Promise ( ( resolve ) => {
25
- rl . question ( question , ( input ) => resolve ( input || defaultAnswer ) ) ;
26
- } ) ;
25
+ rl . question ( question , ( input ) => resolve ( input || defaultAnswer ) )
26
+ } )
27
27
}
28
28
29
29
function getDirName ( defaultDirName ) {
30
- let dirName = args . _ [ 0 ] ?? defaultDirName ;
31
- if ( fs . existsSync ( dirName ) ) dirName += `-${ timestamp } ` ;
32
- return dirName ;
30
+ let dirName = args . _ [ 0 ] ?? defaultDirName
31
+ if ( fs . existsSync ( dirName ) ) dirName += `-${ timestamp } `
32
+ return dirName
33
33
}
34
34
35
35
async function installDependencies ( dirName ) {
36
- console . log ( `Installing dependencies ...` ) ;
37
- await run ( `cd ${ dirName } && npm install` ) ;
36
+ console . log ( `Installing dependencies ...` )
37
+ await run ( `cd ${ dirName } && npm install` )
38
38
}
39
39
40
40
async function initGit ( dirName ) {
41
- console . log ( `Setting up Git ...` ) ;
42
- await run ( `rm -rf ${ dirName } /.git` ) ;
43
- await run (
44
- `cd ${ dirName } && git init && git add . && git commit -m "New Stackbit project"`
45
- ) ;
41
+ console . log ( `Setting up Git ...` )
42
+ await fs . remove ( `${ dirName } / .git` , { recursive : true } , async ( ) => {
43
+ await run (
44
+ `cd ${ dirName } && git init && git add . && git commit -m "New Stackbit project"`
45
+ )
46
+ } )
46
47
}
47
-
48
48
/**
49
49
* Given a version string, compare it to a control version. Returns:
50
50
*
@@ -57,131 +57,148 @@ async function initGit(dirName) {
57
57
*/
58
58
function compareVersion ( version , control ) {
59
59
// References
60
- let returnValue = 0 ;
60
+ let returnValue = 0
61
61
// Return 0 if the versions match.
62
- if ( version === control ) return returnValue ;
62
+ if ( version === control ) return returnValue
63
63
// Break the versions into arrays of integers.
64
- const getVersionParts = ( str ) => str . split ( "." ) . map ( ( v ) => parseInt ( v ) ) ;
65
- const versionParts = getVersionParts ( version ) ;
66
- const controlParts = getVersionParts ( control ) ;
64
+ const getVersionParts = ( str ) => str . split ( '.' ) . map ( ( v ) => parseInt ( v ) )
65
+ const versionParts = getVersionParts ( version )
66
+ const controlParts = getVersionParts ( control )
67
67
// Loop and compare each item.
68
68
controlParts . every ( ( controlPart , idx ) => {
69
69
// If the versions are equal at this part, we move on to the next part.
70
- if ( versionParts [ idx ] === controlPart ) return true ;
70
+ if ( versionParts [ idx ] === controlPart ) return true
71
71
// Otherwise, set the return value, then break out of the loop.
72
- returnValue = versionParts [ idx ] > controlPart ? 1 : - 1 ;
73
- return false ;
74
- } ) ;
75
- return returnValue ;
72
+ returnValue = versionParts [ idx ] > controlPart ? 1 : - 1
73
+ return false
74
+ } )
75
+ return returnValue
76
76
}
77
77
78
78
/* --- Parse CLI Arguments */
79
79
80
80
const args = yargs ( hideBin ( process . argv ) )
81
- . option ( " starter" , {
82
- alias : "s" ,
83
- describe : " Choose a starter" ,
81
+ . option ( ' starter' , {
82
+ alias : 's' ,
83
+ describe : ' Choose a starter' ,
84
84
choices : config . starters . map ( ( s ) => s . name ) ,
85
85
} )
86
- . option ( " example" , {
87
- alias : "e" ,
88
- describe : " Start from an example" ,
86
+ . option ( ' example' , {
87
+ alias : 'e' ,
88
+ describe : ' Start from an example' ,
89
89
choices : config . examples . directories ,
90
90
} )
91
91
. help ( )
92
- . parse ( ) ;
92
+ . parse ( )
93
93
94
94
/* --- References --- */
95
95
96
96
const starter = config . starters . find (
97
97
( s ) => s . name === ( args . starter ?? config . defaults . starter . name )
98
- ) ;
98
+ )
99
99
100
100
// Current time in seconds.
101
- const timestamp = Math . round ( new Date ( ) . getTime ( ) / 1000 ) ;
101
+ const timestamp = Math . round ( new Date ( ) . getTime ( ) / 1000 )
102
102
103
103
/* --- New Project from Starter --- */
104
104
105
105
async function cloneStarter ( ) {
106
106
// Set references
107
- const dirName = getDirName ( config . defaults . dirName ) ;
107
+ const dirName = getDirName ( config . defaults . dirName )
108
108
109
109
// Clone repo
110
- const cloneCommand = `git clone --depth=1 ${ starter . repoUrl } ${ dirName } ` ;
111
- console . log ( `\nCreating new project in ${ dirName } ...` ) ;
112
- await run ( cloneCommand ) ;
110
+ const cloneCommand = `git clone --depth=1 ${ starter . repoUrl } ${ dirName } `
111
+ console . log ( `\nCreating new project in ${ dirName } ...` )
112
+ await run ( cloneCommand )
113
113
114
114
// Project Setup
115
- await installDependencies ( dirName ) ;
116
- await initGit ( dirName ) ;
115
+ await installDependencies ( dirName )
116
+ await initGit ( dirName )
117
117
118
118
// Output next steps:
119
119
console . log ( `
120
- 🎉 ${ chalk . bold ( " Welcome to Stackbit!" ) } 🎉
120
+ 🎉 ${ chalk . bold ( ' Welcome to Stackbit!' ) } 🎉
121
121
122
122
Follow the instructions for getting Started here:
123
123
124
124
${ starter . repoUrl } #readme
125
- ` ) ;
125
+ ` )
126
126
}
127
127
128
128
/* --- New Project from Example --- */
129
129
130
130
async function cloneExample ( ) {
131
- const gitResult = await run ( " git --version" ) ;
132
- const gitVersionMatch = gitResult . stdout . match ( / \d + \. \d + \. \d + / ) ;
131
+ const gitResult = await run ( ' git --version' )
132
+ const gitVersionMatch = gitResult . stdout . match ( / \d + \. \d + \. \d + / )
133
133
if ( ! gitVersionMatch || ! gitVersionMatch [ 0 ] ) {
134
134
console . error (
135
135
`Cannot determine git version, which is required for starting from an example.` ,
136
136
`\nPlease report this:` ,
137
137
chalk . underline (
138
- " https://github.com/stackbit/create-stackbit-app/issues/new"
138
+ ' https://github.com/stackbit/create-stackbit-app/issues/new'
139
139
)
140
- ) ;
141
- process . exit ( 1 ) ;
140
+ )
141
+ process . exit ( 1 )
142
142
}
143
143
if ( compareVersion ( gitVersionMatch [ 0 ] , config . minGitVersion ) < 0 ) {
144
144
console . error (
145
145
`Starting from an example requires git version ${ config . minGitVersion } or later.` ,
146
- " Please upgrade"
147
- ) ;
148
- process . exit ( 1 ) ;
146
+ ' Please upgrade'
147
+ )
148
+ process . exit ( 1 )
149
149
}
150
150
151
- const dirName = getDirName ( args . example ) ;
152
- const tmpDir = `__tmp${ timestamp } __` ;
153
- console . log ( `\nCreating new project in ${ dirName } ...` ) ;
151
+ const dirName = getDirName ( args . example )
152
+ const tmpDir = `__tmp${ timestamp } __`
153
+ console . log ( `\nCreating new project in ${ dirName } ...` )
154
154
155
155
try {
156
156
// Sparse clone the monorepo.
157
157
await run (
158
158
`git clone --depth 1 --filter=blob:none --sparse ${ config . examples . repoUrl } ${ tmpDir } `
159
- ) ;
159
+ )
160
160
// Checkout just the example dir.
161
- await run ( `cd ${ tmpDir } && git sparse-checkout set ${ args . example } ` ) ;
161
+ await run ( `cd ${ tmpDir } && git sparse-checkout set ${ args . example } ` )
162
+
162
163
// Copy out into a new directory within current working directory.
163
- await run ( `cp -R ${ tmpDir } /${ args . example } ${ dirName } ` ) ;
164
- // Delete the clone.
165
- await run ( `rm -rf ${ tmpDir } ` ) ;
164
+ await fs . copy ( `${ tmpDir } /${ args . example } ` , dirName , async ( err ) => {
165
+ if ( err ) {
166
+ console . log ( err )
167
+ }
168
+ } )
166
169
170
+ // Delete the clone.
171
+ await fs . remove ( tmpDir , { recursive : true } , ( err ) => {
172
+ if ( err ) {
173
+ console . log ( err )
174
+ }
175
+ } )
176
+
177
+ if ( fs . existsSync ( path . join ( process . cwd ( ) , dirName ) ) )
178
+ await installDependencies ( path . join ( process . cwd ( ) , dirName ) )
167
179
// Project Setup
168
- await installDependencies ( dirName ) ;
169
- await initGit ( dirName ) ;
180
+ // await
181
+ // await initGit(prestineFolder)
170
182
} catch ( err ) {
171
- console . error ( err ) ;
172
- if ( fs . existsSync ( dirName ) ) await run ( `rm -rf ${ dirName } ` ) ;
173
- if ( fs . existsSync ( tmpDir ) ) await run ( `rm -rf ${ tmpDir } ` ) ;
174
- process . exit ( 1 ) ;
183
+
184
+ if ( fs . existsSync ( dirName ) ) await fs . remove ( dirName )
185
+ if ( fs . existsSync ( tmpDir ) )
186
+ await fs . remove ( tmpDir , ( err ) => {
187
+ if ( err ) {
188
+ console . log ( err )
189
+ }
190
+ } )
191
+ process . exit ( 1 )
175
192
}
176
193
177
194
// Output next steps:
178
195
console . log ( `
179
- 🎉 ${ chalk . bold ( " Your example project is ready!" ) } 🎉
196
+ 🎉 ${ chalk . bold ( ' Your example project is ready!' ) } 🎉
180
197
181
198
Follow the instructions and learn more about the example here:
182
199
183
200
${ config . examples . repoUrl } /tree/main/${ args . example } #readme
184
- ` ) ;
201
+ ` )
185
202
}
186
203
187
204
/* --- Existing Project --- */
@@ -190,37 +207,37 @@ async function integrateStackbit() {
190
207
return new Promise ( async ( resolve ) => {
191
208
const integrate = await prompt ( `
192
209
This looks like an existing project.
193
- ${ chalk . bold ( " Would you like to install Stackbit in this project?" ) } [Y/n] ` ) ;
210
+ ${ chalk . bold ( ' Would you like to install Stackbit in this project?' ) } [Y/n] ` )
194
211
195
- if ( ! [ " yes" , "y" ] . includes ( integrate ?. toLowerCase ( ) ) ) return resolve ( false ) ;
212
+ if ( ! [ ' yes' , 'y' ] . includes ( integrate ?. toLowerCase ( ) ) ) return resolve ( false )
196
213
197
214
console . log ( `
198
215
Visit the following URL to learn more about the integration process:
199
216
200
217
https://docs.stackbit.com/how-to-guides/site-management/integrate-stackbit/
201
- ` ) ;
202
- return resolve ( true ) ;
203
- } ) ;
218
+ ` )
219
+ return resolve ( true )
220
+ } )
204
221
}
205
222
206
223
/* --- Run --- */
207
224
208
225
async function doCreate ( ) {
209
226
// If the current directory has a package.json file, we assume we're in an
210
227
// active project, and will not create a new project.
211
- const packageJsonFilePath = path . join ( process . cwd ( ) , " package.json" ) ;
212
- if ( fs . existsSync ( packageJsonFilePath ) ) return integrateStackbit ( ) ;
228
+ const packageJsonFilePath = path . join ( process . cwd ( ) , ' package.json' )
229
+ if ( fs . existsSync ( packageJsonFilePath ) ) return integrateStackbit ( )
213
230
// If both starter and example were specified, throw an error message.
214
231
if ( args . starter && args . example ) {
215
- console . error ( " [ERROR] Cannot specify a starter and an example." ) ;
216
- process . exit ( 1 ) ;
232
+ console . error ( ' [ERROR] Cannot specify a starter and an example.' )
233
+ process . exit ( 1 )
217
234
}
218
235
// Start from an example if specified.
219
- if ( args . example ) return cloneExample ( ) ;
236
+ if ( args . example ) return cloneExample ( )
220
237
// Otherwise, use a starter, which falls back to the default if not set.
221
- return cloneStarter ( ) ;
238
+ return cloneStarter ( )
222
239
}
223
240
224
- await doCreate ( ) ;
241
+ await doCreate ( )
225
242
226
- rl . close ( ) ;
243
+ rl . close ( )
0 commit comments