@@ -12,6 +12,7 @@ import chalk from 'chalk';
12
12
import prompts from 'prompts' ;
13
13
import glob from 'fast-glob' ;
14
14
import { createRequire } from 'module' ;
15
+ import { execSync } from 'child_process' ;
15
16
16
17
const filePath = fileURLToPath ( import . meta. url ) ;
17
18
const fileDir = path . dirname ( filePath ) ;
@@ -177,6 +178,64 @@ async function updateImportPaths(cwd: string, spinner: Ora) {
177
178
}
178
179
}
179
180
181
+ async function shouldPromptGitWarning ( cwd : string ) : Promise < boolean > {
182
+ try {
183
+ execSync ( 'git rev-parse --is-inside-work-tree' , { cwd } ) ;
184
+ const status = execSync ( 'git status --porcelain' , { cwd } ) . toString ( ) ;
185
+ return ! ! status ;
186
+ } catch ( error ) {
187
+ return false ;
188
+ }
189
+ }
190
+
191
+ async function validateProjectDirectory ( cwd : string ) {
192
+ if ( ! existsSync ( cwd ) ) {
193
+ logger . error ( `The path ${ cwd } does not exist. Please try again.` ) ;
194
+ process . exit ( 1 ) ;
195
+ }
196
+
197
+ if ( ! existsSync ( path . join ( cwd , 'package.json' ) ) ) {
198
+ logger . error ( 'No package.json found. Please run this command in a React Native project directory.' ) ;
199
+ process . exit ( 1 ) ;
200
+ }
201
+ }
202
+
203
+ async function checkGitStatus ( cwd : string ) {
204
+ if ( await shouldPromptGitWarning ( cwd ) ) {
205
+ const { proceed } = await prompts ( {
206
+ type : 'confirm' ,
207
+ name : 'proceed' ,
208
+ message : 'The Git repository is dirty (uncommitted changes). It is recommended to commit your changes before proceeding. Do you want to continue?' ,
209
+ initial : false ,
210
+ } ) ;
211
+
212
+ if ( ! proceed ) {
213
+ logger . info ( 'Installation cancelled.' ) ;
214
+ process . exit ( 0 ) ;
215
+ }
216
+ }
217
+ }
218
+
219
+ async function initializeProject ( cwd : string , overwrite : boolean ) {
220
+ const spinner = ora ( `Initializing project...` ) . start ( ) ;
221
+ const templatesDir = path . dirname (
222
+ createRequire ( import . meta. url ) . resolve ( '@rnr/starter-base' )
223
+ ) ;
224
+
225
+ await installDependencies ( cwd , spinner ) ;
226
+ await updateTsConfig ( cwd , spinner ) ;
227
+
228
+ spinner . text = 'Copying template files...' ;
229
+ for ( const file of TEMPLATE_FILES ) {
230
+ await copyTemplateFile ( file , templatesDir , cwd , spinner , overwrite ) ;
231
+ }
232
+
233
+ await updateImportPaths ( cwd , spinner ) ;
234
+ await updateLayoutFile ( cwd , spinner ) ;
235
+
236
+ spinner . succeed ( 'Initialization completed successfully!' ) ;
237
+ }
238
+
180
239
export const init = new Command ( )
181
240
. name ( 'init' )
182
241
. description ( 'Initialize the React Native project with required configuration' )
@@ -191,28 +250,9 @@ export const init = new Command()
191
250
const options = initOptionsSchema . parse ( opts ) ;
192
251
const cwd = path . resolve ( options . cwd ) ;
193
252
194
- if ( ! existsSync ( cwd ) ) {
195
- logger . error ( `The path ${ cwd } does not exist. Please try again.` ) ;
196
- process . exit ( 1 ) ;
197
- }
198
-
199
- const spinner = ora ( `Initializing project...` ) . start ( ) ;
200
- const templatesDir = path . dirname (
201
- createRequire ( import . meta. url ) . resolve ( '@rnr/starter-base' )
202
- ) ;
203
-
204
- await installDependencies ( cwd , spinner ) ;
205
- await updateTsConfig ( cwd , spinner ) ;
206
-
207
- spinner . text = 'Copying template files...' ;
208
- for ( const file of TEMPLATE_FILES ) {
209
- await copyTemplateFile ( file , templatesDir , cwd , spinner , options . overwrite ) ;
210
- }
211
-
212
- await updateImportPaths ( cwd , spinner ) ;
213
- await updateLayoutFile ( cwd , spinner ) ;
214
-
215
- spinner . succeed ( 'Initialization completed successfully!' ) ;
253
+ await validateProjectDirectory ( cwd ) ;
254
+ await checkGitStatus ( cwd ) ;
255
+ await initializeProject ( cwd , options . overwrite ) ;
216
256
} catch ( error ) {
217
257
handleError ( error ) ;
218
258
}
0 commit comments