@@ -426,32 +426,62 @@ function run(
426
426
getInstallPackage ( version , originalDirectory ) ,
427
427
getTemplateInstallPackage ( template , originalDirectory ) ,
428
428
] ) . then ( ( [ packageToInstall , templateToInstall ] ) => {
429
- const allDependencies = [
430
- 'react' ,
431
- 'react-dom' ,
432
- packageToInstall ,
433
- templateToInstall ,
434
- ] ;
429
+ const allDependencies = [ 'react' , 'react-dom' , packageToInstall ] ;
435
430
436
431
console . log ( 'Installing packages. This might take a couple of minutes.' ) ;
432
+
437
433
Promise . all ( [
438
- getPackageName ( packageToInstall ) ,
439
- getPackageName ( templateToInstall ) ,
434
+ getPackageInfo ( packageToInstall ) ,
435
+ getPackageInfo ( templateToInstall ) ,
440
436
] )
441
- . then ( ( [ packageName , templateName ] ) =>
437
+ . then ( ( [ packageInfo , templateInfo ] ) =>
442
438
checkIfOnline ( useYarn ) . then ( isOnline => ( {
443
439
isOnline,
444
- packageName ,
445
- templateName ,
440
+ packageInfo ,
441
+ templateInfo ,
446
442
} ) )
447
443
)
448
- . then ( ( { isOnline, packageName, templateName } ) => {
444
+ . then ( ( { isOnline, packageInfo, templateInfo } ) => {
445
+ let packageVersion = packageInfo . version ;
446
+
447
+ // Assume compatibility if we can't test the version.
448
+ if ( ! semver . valid ( packageVersion ) ) {
449
+ packageVersion = '3.2.0' ;
450
+ }
451
+
452
+ // Only support templates when used alongside new react-scripts versions.
453
+ const supportsTemplates = semver . gte ( packageVersion , '3.2.0' ) ;
454
+ if ( supportsTemplates ) {
455
+ allDependencies . push ( templateToInstall ) ;
456
+ } else if ( template ) {
457
+ console . log ( '' ) ;
458
+ console . log (
459
+ `The ${ chalk . cyan (
460
+ packageInfo . name
461
+ ) } version you're using is not compatible with the ${ chalk . cyan (
462
+ '--template'
463
+ ) } option.`
464
+ ) ;
465
+ console . log ( '' ) ;
466
+ }
467
+
468
+ // TODO: Remove with next major release.
469
+ if ( ! supportsTemplates && template . includes ( 'typescript' ) ) {
470
+ allDependencies . push (
471
+ '@types/node' ,
472
+ '@types/react' ,
473
+ '@types/react-dom' ,
474
+ '@types/jest' ,
475
+ 'typescript'
476
+ ) ;
477
+ }
478
+
449
479
console . log (
450
480
`Installing ${ chalk . cyan ( 'react' ) } , ${ chalk . cyan (
451
481
'react-dom'
452
- ) } , and ${ chalk . cyan ( packageName ) } with ${ chalk . cyan (
453
- templateName
454
- ) } ...`
482
+ ) } , and ${ chalk . cyan ( packageInfo . name ) } ${
483
+ supportsTemplates ? ` with ${ chalk . cyan ( templateInfo . name ) } ` : ''
484
+ } ...`
455
485
) ;
456
486
console . log ( ) ;
457
487
@@ -463,11 +493,14 @@ function run(
463
493
verbose ,
464
494
isOnline
465
495
) . then ( ( ) => ( {
466
- packageName,
467
- templateName,
496
+ packageInfo,
497
+ supportsTemplates,
498
+ templateInfo,
468
499
} ) ) ;
469
500
} )
470
- . then ( async ( { packageName, templateName } ) => {
501
+ . then ( async ( { packageInfo, supportsTemplates, templateInfo } ) => {
502
+ const packageName = packageInfo . name ;
503
+ const templateName = supportsTemplates ? templateInfo . name : undefined ;
471
504
checkNodeVersion ( packageName ) ;
472
505
setCaretRangeForRuntimeDeps ( packageName ) ;
473
506
@@ -656,7 +689,7 @@ function extractStream(stream, dest) {
656
689
}
657
690
658
691
// Extract package name from tarball url or path.
659
- function getPackageName ( installPackage ) {
692
+ function getPackageInfo ( installPackage ) {
660
693
if ( installPackage . match ( / ^ .+ \. ( t g z | t a r \. g z ) $ / ) ) {
661
694
return getTemporaryDirectory ( )
662
695
. then ( obj => {
@@ -669,9 +702,12 @@ function getPackageName(installPackage) {
669
702
return extractStream ( stream , obj . tmpdir ) . then ( ( ) => obj ) ;
670
703
} )
671
704
. then ( obj => {
672
- const packageName = require ( path . join ( obj . tmpdir , 'package.json' ) ) . name ;
705
+ const { name, version } = require ( path . join (
706
+ obj . tmpdir ,
707
+ 'package.json'
708
+ ) ) ;
673
709
obj . cleanup ( ) ;
674
- return packageName ;
710
+ return { name , version } ;
675
711
} )
676
712
. catch ( err => {
677
713
// The package name could be with or without semver version, e.g. react-scripts-0.2.0-alpha.1.tgz
@@ -687,27 +723,30 @@ function getPackageName(installPackage) {
687
723
assumedProjectName
688
724
) } "`
689
725
) ;
690
- return Promise . resolve ( assumedProjectName ) ;
726
+ return Promise . resolve ( { name : assumedProjectName } ) ;
691
727
} ) ;
692
728
} else if ( installPackage . indexOf ( 'git+' ) === 0 ) {
693
729
// Pull package name out of git urls e.g:
694
730
// git+https://github.com/mycompany/react-scripts.git
695
731
// git+ssh://github.com/mycompany/react-scripts.git#v1.2.3
696
- return Promise . resolve ( installPackage . match ( / ( [ ^ / ] + ) \. g i t ( # .* ) ? $ / ) [ 1 ] ) ;
732
+ return Promise . resolve ( {
733
+ name : installPackage . match ( / ( [ ^ / ] + ) \. g i t ( # .* ) ? $ / ) [ 1 ] ,
734
+ } ) ;
697
735
} else if ( installPackage . match ( / .+ @ / ) ) {
698
736
// Do not match @scope / when stripping off @version or @tag
699
- return Promise . resolve (
700
- installPackage . charAt ( 0 ) + installPackage . substr ( 1 ) . split ( '@' ) [ 0 ]
701
- ) ;
737
+ return Promise . resolve ( {
738
+ name : installPackage . charAt ( 0 ) + installPackage . substr ( 1 ) . split ( '@' ) [ 0 ] ,
739
+ version : installPackage . split ( '@' ) [ 1 ] ,
740
+ } ) ;
702
741
} else if ( installPackage . match ( / ^ f i l e : / ) ) {
703
742
const installPackagePath = installPackage . match ( / ^ f i l e : ( .* ) ? $ / ) [ 1 ] ;
704
- const installPackageJson = require ( path . join (
743
+ const { name , version } = require ( path . join (
705
744
installPackagePath ,
706
745
'package.json'
707
746
) ) ;
708
- return Promise . resolve ( installPackageJson . name ) ;
747
+ return Promise . resolve ( { name, version } ) ;
709
748
}
710
- return Promise . resolve ( installPackage ) ;
749
+ return Promise . resolve ( { name : installPackage } ) ;
711
750
}
712
751
713
752
function checkNpmVersion ( ) {
0 commit comments