@@ -21,12 +21,16 @@ import * as PackageManager from '../../tools/packageManager';
2121import { installPods } from '@react-native-community/cli-doctor' ;
2222import banner from './banner' ;
2323import TemplateAndVersionError from './errors/TemplateAndVersionError' ;
24+ import { getBunVersionIfAvailable } from '../../tools/bun' ;
25+ import { getNpmVersionIfAvailable } from '../../tools/npm' ;
26+ import { getYarnVersionIfAvailable } from '../../tools/yarn' ;
2427
2528const DEFAULT_VERSION = 'latest' ;
2629
2730type Options = {
2831 template ?: string ;
2932 npm ?: boolean ;
33+ pm ?: PackageManager . PackageManager ;
3034 directory ?: string ;
3135 displayName ?: string ;
3236 title ?: string ;
@@ -39,6 +43,7 @@ interface TemplateOptions {
3943 projectName : string ;
4044 templateUri : string ;
4145 npm ?: boolean ;
46+ pm ?: PackageManager . PackageManager ;
4247 directory : string ;
4348 projectTitle ?: string ;
4449 skipInstall ?: boolean ;
@@ -82,6 +87,7 @@ async function createFromTemplate({
8287 projectName,
8388 templateUri,
8489 npm,
90+ pm,
8591 directory,
8692 projectTitle,
8793 skipInstall,
@@ -90,6 +96,24 @@ async function createFromTemplate({
9096 logger . debug ( 'Initializing new project' ) ;
9197 logger . log ( banner ) ;
9298
99+ let packageManager = pm ;
100+
101+ if ( pm ) {
102+ packageManager = pm ;
103+ } else {
104+ const userAgentPM = userAgentPackageManager ( ) ;
105+ // if possible, use the package manager from the user agent. Otherwise fallback to default (yarn)
106+ packageManager = userAgentPM || 'yarn' ;
107+ }
108+
109+ if ( npm ) {
110+ logger . warn (
111+ 'Flag --npm is deprecated and will be removed soon. In the future, please use --pm npm instead.' ,
112+ ) ;
113+
114+ packageManager = 'npm' ;
115+ }
116+
93117 const projectDirectory = await setProjectDirectory ( directory ) ;
94118
95119 const loader = getLoader ( { text : 'Downloading template' } ) ;
@@ -100,7 +124,11 @@ async function createFromTemplate({
100124 try {
101125 loader . start ( ) ;
102126
103- await installTemplatePackage ( templateUri , templateSourceDir , npm ) ;
127+ await installTemplatePackage (
128+ templateUri ,
129+ templateSourceDir ,
130+ packageManager ,
131+ ) ;
104132
105133 loader . succeed ( ) ;
106134 loader . start ( 'Copying template' ) ;
@@ -137,7 +165,7 @@ async function createFromTemplate({
137165
138166 if ( ! skipInstall ) {
139167 await installDependencies ( {
140- npm ,
168+ packageManager ,
141169 loader,
142170 root : projectDirectory ,
143171 } ) ;
@@ -153,18 +181,18 @@ async function createFromTemplate({
153181}
154182
155183async function installDependencies ( {
156- npm ,
184+ packageManager ,
157185 loader,
158186 root,
159187} : {
160- npm ?: boolean ;
188+ packageManager : PackageManager . PackageManager ;
161189 loader : Loader ;
162190 root : string ;
163191} ) {
164192 loader . start ( 'Installing dependencies' ) ;
165193
166194 await PackageManager . installAll ( {
167- preferYarn : ! npm ,
195+ packageManager ,
168196 silent : true ,
169197 root,
170198 } ) ;
@@ -176,6 +204,20 @@ async function installDependencies({
176204 loader . succeed ( ) ;
177205}
178206
207+ function checkPackageManagerAvailability (
208+ packageManager : PackageManager . PackageManager ,
209+ ) {
210+ if ( packageManager === 'bun' ) {
211+ return getBunVersionIfAvailable ( ) ;
212+ } else if ( packageManager === 'npm' ) {
213+ return getNpmVersionIfAvailable ( ) ;
214+ } else if ( packageManager === 'yarn' ) {
215+ return getYarnVersionIfAvailable ( ) ;
216+ }
217+
218+ return false ;
219+ }
220+
179221function createTemplateUri ( options : Options , version : string ) : string {
180222 const isTypescriptTemplate =
181223 options . template === 'react-native-template-typescript' ;
@@ -202,13 +244,32 @@ async function createProject(
202244 projectName,
203245 templateUri,
204246 npm : options . npm ,
247+ pm : options . pm ,
205248 directory,
206249 projectTitle : options . title ,
207250 skipInstall : options . skipInstall ,
208251 packageName : options . packageName ,
209252 } ) ;
210253}
211254
255+ function userAgentPackageManager ( ) {
256+ const userAgent = process . env . npm_config_user_agent ;
257+
258+ if ( userAgent ) {
259+ if ( userAgent . startsWith ( 'yarn' ) ) {
260+ return 'yarn' ;
261+ }
262+ if ( userAgent . startsWith ( 'npm' ) ) {
263+ return 'npm' ;
264+ }
265+ if ( userAgent . startsWith ( 'bun' ) ) {
266+ return 'bun' ;
267+ }
268+ }
269+
270+ return null ;
271+ }
272+
212273export default ( async function initialize (
213274 [ projectName ] : Array < string > ,
214275 options : Options ,
@@ -223,6 +284,13 @@ export default (async function initialize(
223284 const version = options . version || DEFAULT_VERSION ;
224285 const directoryName = path . relative ( root , options . directory || projectName ) ;
225286
287+ if ( options . pm && ! checkPackageManagerAvailability ( options . pm ) ) {
288+ logger . error (
289+ 'Seems like the package manager you want to use is not installed. Please install it or choose another package manager.' ,
290+ ) ;
291+ return ;
292+ }
293+
226294 await createProject ( projectName , directoryName , version , options ) ;
227295
228296 const projectFolder = path . join ( root , directoryName ) ;
0 commit comments