@@ -18,6 +18,7 @@ import { addCodegenBuildScript } from './exampleApp/addCodegenBuildScript';
1818import { createInitialGitCommit } from './utils/initialCommit' ;
1919import { assertNpx } from './utils/assert' ;
2020import { resolveBobVersionWithFallback } from './utils/promiseWithFallback' ;
21+ import { generateTemplateConfiguration } from './template/config' ;
2122
2223const FALLBACK_BOB_VERSION = '0.32.0' ;
2324
@@ -98,7 +99,7 @@ type ProjectType =
9899 | 'view-legacy'
99100 | 'library' ;
100101
101- type Answers = {
102+ export type Answers = {
102103 name : string ;
103104 slug : string ;
104105 description : string ;
@@ -510,83 +511,17 @@ async function create(_argv: yargs.Arguments<any>) {
510511 local,
511512 ...singleChoiceAnswers ,
512513 ...promptAnswers ,
513- } as Answers ;
514+ } as Required < Answers > ;
514515
515516 assertOptions ( questions , answers ) ;
516517
517- const {
518- slug,
519- description,
520- authorName,
521- authorEmail,
522- authorUrl,
523- repoUrl,
524- type = 'module-mixed' ,
525- languages = type === 'library' ? 'js' : 'kotlin-objc' ,
526- example = local ? 'none' : type === 'library' ? 'expo' : 'vanilla' ,
527- reactNativeVersion,
528- } = answers ;
529-
530- const moduleType = type . startsWith ( 'view-' ) ? 'view' : 'module' ;
531- const arch =
532- type === 'module-new' || type === 'view-new'
533- ? 'new'
534- : type === 'module-mixed' || type === 'view-mixed'
535- ? 'mixed'
536- : 'legacy' ;
537-
538- const project = slug . replace ( / ^ ( r e a c t - n a t i v e - | @ [ ^ / ] + \/ ) / , '' ) ;
539-
540- let namespace : string | undefined ;
541-
542- if ( slug . startsWith ( '@' ) && slug . includes ( '/' ) ) {
543- namespace = slug
544- . split ( '/' ) [ 0 ]
545- ?. replace ( / [ ^ a - z 0 - 9 ] / g, '' )
546- . toLowerCase ( ) ;
547- }
548-
549- // Create a package identifier with specified namespace when possible
550- const pack = `${ namespace ? `${ namespace } .` : '' } ${ project
551- . replace ( / [ ^ a - z 0 - 9 ] / g, '' )
552- . toLowerCase ( ) } `;
553-
554518 const bobVersion = await resolveBobVersion ( ) ;
555- const options = {
556- bob : {
557- version : bobVersion ,
558- } ,
559- project : {
560- slug,
561- description,
562- name :
563- / ^ [ A - Z ] / . test ( basename ) && / ^ [ a - z 0 - 9 ] + $ / i. test ( basename )
564- ? // If the project name is already in PascalCase, use it as-is
565- basename
566- : // Otherwise, convert it to PascalCase and remove any non-alphanumeric characters
567- `${ project . charAt ( 0 ) . toUpperCase ( ) } ${ project
568- . replace ( / [ ^ a - z 0 - 9 ] ( \w ) / g, ( _ , $1 ) => $1 . toUpperCase ( ) )
569- . slice ( 1 ) } `,
570- package : pack ,
571- package_dir : pack . replace ( / \. / g, '/' ) ,
572- package_cpp : pack . replace ( / \. / g, '_' ) ,
573- identifier : slug . replace ( / [ ^ a - z 0 - 9 ] + / g, '-' ) . replace ( / ^ - / , '' ) ,
574- native : languages !== 'js' ,
575- arch,
576- cpp : languages === 'cpp' ,
577- swift : languages === 'kotlin-swift' ,
578- view : moduleType === 'view' ,
579- module : moduleType === 'module' ,
580- } ,
581- author : {
582- name : authorName ,
583- email : authorEmail ,
584- url : authorUrl ,
585- } ,
586- repo : repoUrl ,
587- example,
588- year : new Date ( ) . getFullYear ( ) ,
589- } ;
519+
520+ const config = generateTemplateConfiguration ( {
521+ bobVersion,
522+ basename,
523+ answers,
524+ } ) ;
590525
591526 async function applyTemplate ( source : string , destination : string ) {
592527 await fs . mkdirp ( destination ) ;
@@ -596,7 +531,7 @@ async function create(_argv: yargs.Arguments<any>) {
596531 for ( const f of files ) {
597532 const target = path . join (
598533 destination ,
599- ejs . render ( f . replace ( / ^ \$ / , '' ) , options , {
534+ ejs . render ( f . replace ( / ^ \$ / , '' ) , config , {
600535 openDelimiter : '{' ,
601536 closeDelimiter : '}' ,
602537 } )
@@ -610,7 +545,7 @@ async function create(_argv: yargs.Arguments<any>) {
610545 } else if ( ! BINARIES . some ( ( r ) => r . test ( file ) ) ) {
611546 const content = await fs . readFile ( file , 'utf8' ) ;
612547
613- await fs . writeFile ( target , ejs . render ( content , options ) ) ;
548+ await fs . writeFile ( target , ejs . render ( content , config ) ) ;
614549 } else {
615550 await fs . copyFile ( file , target ) ;
616551 }
@@ -619,36 +554,36 @@ async function create(_argv: yargs.Arguments<any>) {
619554
620555 await fs . mkdirp ( folder ) ;
621556
622- if ( reactNativeVersion != null ) {
623- if ( example === 'vanilla' ) {
557+ if ( answers . reactNativeVersion != null ) {
558+ if ( config . example === 'vanilla' ) {
624559 console . log (
625560 `${ kleur . blue ( 'ℹ' ) } Using ${ kleur . cyan (
626- `react-native@${ reactNativeVersion } `
561+ `react-native@${ answers . reactNativeVersion } `
627562 ) } for the example`
628563 ) ;
629564 } else {
630565 console . warn (
631566 `${ kleur . yellow (
632567 '⚠'
633568 ) } Ignoring --react-native-version for unsupported example type: ${ kleur . cyan (
634- example
569+ config . example
635570 ) } `
636571 ) ;
637572 }
638573 }
639574
640575 const spinner = ora ( ) . start ( ) ;
641576
642- if ( example !== 'none' ) {
577+ if ( config . example !== 'none' ) {
643578 spinner . text = 'Generating example app' ;
644579
645580 await generateExampleApp ( {
646- type : example ,
581+ type : config . example ,
647582 dest : folder ,
648- arch,
649- project : options . project ,
583+ arch : config . project . arch ,
584+ project : config . project ,
650585 bobVersion,
651- reactNativeVersion,
586+ reactNativeVersion : answers . reactNativeVersion ,
652587 } ) ;
653588 }
654589
@@ -659,50 +594,55 @@ async function create(_argv: yargs.Arguments<any>) {
659594 } else {
660595 await applyTemplate ( COMMON_FILES , folder ) ;
661596
662- if ( example !== 'none' ) {
597+ if ( config . example !== 'none' ) {
663598 await applyTemplate ( COMMON_EXAMPLE_FILES , folder ) ;
664599 }
665600 }
666601
667- if ( languages === 'js' ) {
602+ if ( answers . languages === 'js' ) {
668603 await applyTemplate ( JS_FILES , folder ) ;
669604 await applyTemplate ( EXPO_FILES , folder ) ;
670605 } else {
671606 await applyTemplate ( NATIVE_COMMON_FILES , folder ) ;
672607
673- if ( example !== 'none' ) {
608+ if ( config . example !== 'none' ) {
674609 await applyTemplate ( NATIVE_COMMON_EXAMPLE_FILES , folder ) ;
675610 }
676611
677- if ( moduleType === 'module' ) {
678- await applyTemplate ( NATIVE_FILES [ `${ moduleType } _${ arch } ` ] , folder ) ;
612+ if ( config . project . module ) {
613+ await applyTemplate (
614+ NATIVE_FILES [ `module_${ config . project . arch } ` ] ,
615+ folder
616+ ) ;
679617 } else {
680- await applyTemplate ( NATIVE_FILES [ `${ moduleType } _ ${ arch } ` ] , folder ) ;
618+ await applyTemplate ( NATIVE_FILES [ `view_ ${ config . project . arch } ` ] , folder ) ;
681619 }
682620
683- if ( options . project . swift ) {
684- await applyTemplate ( SWIFT_FILES [ `${ moduleType } _legacy ` ] , folder ) ;
621+ if ( config . project . swift ) {
622+ await applyTemplate ( SWIFT_FILES [ `module_legacy ` ] , folder ) ;
685623 } else {
686- if ( moduleType === ' module' ) {
687- await applyTemplate ( OBJC_FILES [ `${ moduleType } _common ` ] , folder ) ;
624+ if ( config . project . module ) {
625+ await applyTemplate ( OBJC_FILES [ `module_common ` ] , folder ) ;
688626 } else {
689- await applyTemplate ( OBJC_FILES [ `view_${ arch } ` ] , folder ) ;
627+ await applyTemplate ( OBJC_FILES [ `view_${ config . project . arch } ` ] , folder ) ;
690628 }
691629 }
692630
693- const templateType = `${ moduleType } _${ arch } ` as const ;
631+ const templateType = `${ config . project . module ? 'module' : 'view' } _${
632+ config . project . arch
633+ } ` as const ;
694634
695635 await applyTemplate ( KOTLIN_FILES [ templateType ] , folder ) ;
696636
697- if ( options . project . cpp ) {
637+ if ( config . project . cpp ) {
698638 await applyTemplate ( CPP_FILES , folder ) ;
699- await fs . remove ( path . join ( folder , 'ios' , `${ options . project . name } .m` ) ) ;
639+ await fs . remove ( path . join ( folder , 'ios' , `${ config . project . name } .m` ) ) ;
700640 }
701641 }
702642
703643 const rootPackageJson = await fs . readJson ( path . join ( folder , 'package.json' ) ) ;
704644
705- if ( example !== 'none' ) {
645+ if ( config . example !== 'none' ) {
706646 // Set `react` and `react-native` versions of root `package.json` from example `package.json`
707647 const examplePackageJson = await fs . readJSON (
708648 path . join ( folder , 'example' , 'package.json' )
@@ -719,7 +659,7 @@ async function create(_argv: yargs.Arguments<any>) {
719659 examplePackageJson . dependencies [ 'react-native' ] ;
720660 }
721661
722- if ( example === 'vanilla' ) {
662+ if ( config . example === 'vanilla' ) {
723663 // React Native doesn't provide the community CLI as a dependency.
724664 // We have to get read the version from the example app and put to the root package json
725665 const exampleCommunityCLIVersion =
@@ -733,7 +673,7 @@ async function create(_argv: yargs.Arguments<any>) {
733673 rootPackageJson . devDependencies [ '@react-native-community/cli' ] =
734674 exampleCommunityCLIVersion ;
735675
736- if ( arch !== 'legacy' ) {
676+ if ( config . project . arch !== 'legacy' ) {
737677 addCodegenBuildScript ( folder ) ;
738678 }
739679 }
@@ -800,7 +740,7 @@ async function create(_argv: yargs.Arguments<any>) {
800740
801741 if ( isReactNativeProject ) {
802742 packageJson . dependencies = packageJson . dependencies || { } ;
803- packageJson . dependencies [ slug ] =
743+ packageJson . dependencies [ config . project . slug ] =
804744 packageManager === 'yarn'
805745 ? `link:./${ path . relative ( process . cwd ( ) , folder ) } `
806746 : `file:./${ path . relative ( process . cwd ( ) , folder ) } ` ;
@@ -833,7 +773,9 @@ async function create(_argv: yargs.Arguments<any>) {
833773 `- Run ${ kleur . blue ( 'npx react-native run-android' ) } or ${ kleur . blue (
834774 'npx react-native run-ios'
835775 ) } to build and run the app\n` +
836- `- Import from ${ kleur . blue ( slug ) } and use it in your app.`
776+ `- Import from ${ kleur . blue (
777+ config . project . slug
778+ ) } and use it in your app.`
837779 }
838780
839781 ${ kleur . yellow ( `Good luck!` ) }
@@ -843,7 +785,7 @@ async function create(_argv: yargs.Arguments<any>) {
843785 const platforms = {
844786 ios : { name : 'iOS' , color : 'cyan' } ,
845787 android : { name : 'Android' , color : 'green' } ,
846- ...( example === 'expo'
788+ ...( config . example === 'expo'
847789 ? ( { web : { name : 'Web' , color : 'blue' } } as const )
848790 : null ) ,
849791 } as const ;
0 commit comments