@@ -36,11 +36,16 @@ import {
3636 checkNodeVersion ,
3737 checkThatNpmCanReadCwd ,
3838 cleanUpDockerResources ,
39+ detectPackageManager ,
3940 downloadAndExtractStorefront ,
4041 findAvailablePort ,
4142 getDependencies ,
43+ getMonorepoRootPackageJson ,
44+ getPackageManagerInfo ,
45+ getServerPackageScripts ,
4246 installPackages ,
4347 isSafeToCreateProjectIn ,
48+ registerTemplateHelpers ,
4449 resolvePackageRootDir ,
4550 scaffoldAlreadyExists ,
4651 startPostgresDatabase ,
@@ -76,7 +81,7 @@ program
7681 . option ( '--verbose' , 'Alias for --log-level verbose' , false )
7782 . option (
7883 '--use-npm' ,
79- 'Uses npm rather than as the default package manager. DEPRECATED: Npm is now the default ' ,
84+ 'Force npm, overriding auto-detection of the package manager that invoked the CLI ' ,
8085 )
8186 . option ( '--ci' , 'Runs without prompts for use in CI scenarios' , false )
8287 . option ( '--with-storefront' , 'Include Next.js storefront (only used with --ci)' , false )
@@ -96,7 +101,7 @@ void createVendureApp(
96101
97102export async function createVendureApp (
98103 name : string | undefined ,
99- _useNpm : boolean , // Deprecated: npm is now the default package manager
104+ _useNpm : boolean , // Legacy flag: forces npm, overriding package- manager auto-detection
100105 logLevel : CliLogLevel ,
101106 isCi : boolean = false ,
102107 withStorefront : boolean = false ,
@@ -144,7 +149,12 @@ export async function createVendureApp(
144149 const appName = path . basename ( root ) ;
145150 const scaffoldExists = scaffoldAlreadyExists ( root , name ) ;
146151
147- const packageManager : PackageManager = 'npm' ;
152+ // `--use-npm` is honoured as an explicit override of auto-detection; otherwise we
153+ // detect the manager that invoked the CLI (bunx/pnpm dlx/yarn dlx) so the generated
154+ // project, install step and instructions all match what the user is actually using.
155+ const packageManager : PackageManager = _useNpm ? 'npm' : detectPackageManager ( ) ;
156+ const pmInfo = getPackageManagerInfo ( packageManager ) ;
157+ registerTemplateHelpers ( pmInfo ) ;
148158
149159 if ( scaffoldExists ) {
150160 log (
@@ -196,7 +206,8 @@ export async function createVendureApp(
196206 }
197207
198208 process . chdir ( root ) ;
199- if ( packageManager !== 'npm' && ! checkThatNpmCanReadCwd ( ) ) {
209+ // This check spawns `npm` itself, so it only makes sense (and only works) for npm.
210+ if ( packageManager === 'npm' && ! checkThatNpmCanReadCwd ( ) ) {
200211 process . exit ( 1 ) ;
201212 }
202213
@@ -215,15 +226,23 @@ export async function createVendureApp(
215226 await fs . ensureDir ( serverRoot ) ;
216227 await fs . ensureDir ( path . join ( serverRoot , 'src' ) ) ;
217228
218- // Generate root package.json from template
219- const rootPackageTemplate = await fs . readFile ( templatePath ( 'root-package.json.hbs' ) , 'utf-8' ) ;
220- const rootPackageContent = Handlebars . compile ( rootPackageTemplate ) ( { name : appName } ) ;
221- fs . writeFileSync ( path . join ( root , 'package.json' ) , rootPackageContent + os . EOL ) ;
229+ // Generate root package.json with package-manager-aware workspace scripts
230+ fs . writeFileSync (
231+ path . join ( root , 'package.json' ) ,
232+ JSON . stringify ( getMonorepoRootPackageJson ( appName , pmInfo ) , null , 2 ) + os . EOL ,
233+ ) ;
234+
235+ // pnpm does not read the package.json `workspaces` field; it requires a
236+ // pnpm-workspace.yaml instead.
237+ if ( ! pmInfo . usesPackageJsonWorkspaces ) {
238+ fs . writeFileSync ( path . join ( root , 'pnpm-workspace.yaml' ) , `packages:\n - 'apps/*'\n` ) ;
239+ }
222240
223241 // Generate root README from template
224242 const rootReadmeTemplate = await fs . readFile ( templatePath ( 'root-readme.hbs' ) , 'utf-8' ) ;
225243 const rootReadmeContent = Handlebars . compile ( rootReadmeTemplate ) ( {
226244 name : appName ,
245+ packageManager,
227246 serverPort : port ,
228247 storefrontPort,
229248 superadminIdentifier : SUPER_ADMIN_USER_IDENTIFIER ,
@@ -239,7 +258,7 @@ export async function createVendureApp(
239258 name : 'server' ,
240259 version : DEFAULT_PROJECT_VERSION ,
241260 private : true ,
242- scripts : getServerPackageScripts ( ) ,
261+ scripts : getServerPackageScripts ( pmInfo ) ,
243262 } ;
244263 fs . writeFileSync (
245264 path . join ( serverRoot , 'package.json' ) ,
@@ -251,7 +270,7 @@ export async function createVendureApp(
251270 name : appName ,
252271 version : DEFAULT_PROJECT_VERSION ,
253272 private : true ,
254- scripts : getServerPackageScripts ( ) ,
273+ scripts : getServerPackageScripts ( pmInfo ) ,
255274 } ;
256275 fs . writeFileSync (
257276 path . join ( root , 'package.json' ) ,
@@ -302,6 +321,7 @@ export async function createVendureApp(
302321 // Install server dependencies
303322 await installDependenciesWithSpinner ( {
304323 dependencies,
324+ packageManager,
305325 logLevel,
306326 cwd : serverRoot ,
307327 spinnerMessage : `Installing ${ dependencies [ 0 ] } + ${ dependencies . length - 1 } more dependencies` ,
@@ -313,6 +333,7 @@ export async function createVendureApp(
313333 await installDependenciesWithSpinner ( {
314334 dependencies : devDependencies ,
315335 isDevDependencies : true ,
336+ packageManager,
316337 logLevel,
317338 cwd : serverRoot ,
318339 spinnerMessage : `Installing ${ devDependencies [ 0 ] } + ${ devDependencies . length - 1 } more dev dependencies` ,
@@ -325,6 +346,7 @@ export async function createVendureApp(
325346 // Install storefront dependencies
326347 const storefrontInstalled = await installDependenciesWithSpinner ( {
327348 dependencies : [ ] ,
349+ packageManager,
328350 logLevel,
329351 cwd : storefrontRoot ,
330352 spinnerMessage : 'Installing storefront dependencies...' ,
@@ -333,7 +355,9 @@ export async function createVendureApp(
333355 warnOnFailure : true ,
334356 } ) ;
335357 if ( ! storefrontInstalled ) {
336- log ( 'You may need to run npm install in the storefront directory manually.' , { level : 'info' } ) ;
358+ log ( `You may need to run ${ pmInfo . install } in the storefront directory manually.` , {
359+ level : 'info' ,
360+ } ) ;
337361 }
338362 }
339363
@@ -511,10 +535,13 @@ export async function createVendureApp(
511535 ] ;
512536 note ( quickStartInstructions . join ( '\n' ) ) ;
513537
514- const npmCommand = os . platform ( ) === 'win32' ? 'npm.cmd' : 'npm' ;
538+ // Run `dev` via the detected package manager. On Windows the npm/yarn/pnpm
539+ // binaries are `.cmd` shims (bun ships a real `bun.exe`).
540+ const pmCommand =
541+ os . platform ( ) === 'win32' && pmInfo . name !== 'bun' ? `${ pmInfo . name } .cmd` : pmInfo . name ;
515542 let quickStartProcess : ChildProcess | undefined ;
516543 try {
517- quickStartProcess = spawn ( npmCommand , [ 'run' , 'dev' ] , {
544+ quickStartProcess = spawn ( pmCommand , [ 'run' , 'dev' ] , {
518545 cwd : root ,
519546 stdio : 'inherit' ,
520547 } ) ;
@@ -527,6 +554,7 @@ export async function createVendureApp(
527554 displayOutro ( {
528555 root,
529556 name,
557+ packageManager,
530558 superAdminCredentials,
531559 includeStorefront,
532560 serverPort : port ,
@@ -557,6 +585,7 @@ export async function createVendureApp(
557585 displayOutro ( {
558586 root,
559587 name,
588+ packageManager,
560589 superAdminCredentials,
561590 includeStorefront,
562591 serverPort : port ,
@@ -571,26 +600,10 @@ export async function createVendureApp(
571600 }
572601}
573602
574- /**
575- * Returns the standard npm scripts for the server package.json.
576- */
577- function getServerPackageScripts ( ) : Record < string , string > {
578- return {
579- 'dev:server' : 'ts-node ./src/index.ts' ,
580- 'dev:worker' : 'ts-node ./src/index-worker.ts' ,
581- 'dev:dashboard' : 'vite --clearScreen false' ,
582- dev : 'concurrently --kill-others npm:dev:*' ,
583- build : 'tsc' ,
584- 'build:dashboard' : 'vite build' ,
585- 'start:server' : 'node ./dist/index.js' ,
586- 'start:worker' : 'node ./dist/index-worker.js' ,
587- start : 'concurrently npm:start:*' ,
588- } ;
589- }
590-
591603interface InstallDependenciesOptions {
592604 dependencies : string [ ] ;
593605 isDevDependencies ?: boolean ;
606+ packageManager : PackageManager ;
594607 logLevel : CliLogLevel ;
595608 cwd : string ;
596609 spinnerMessage : string ;
@@ -607,6 +620,7 @@ async function installDependenciesWithSpinner(installOptions: InstallDependencie
607620 const {
608621 dependencies,
609622 isDevDependencies = false ,
623+ packageManager,
610624 logLevel,
611625 cwd,
612626 spinnerMessage,
@@ -619,7 +633,7 @@ async function installDependenciesWithSpinner(installOptions: InstallDependencie
619633 installSpinner . start ( spinnerMessage ) ;
620634
621635 try {
622- await installPackages ( { dependencies, isDevDependencies, logLevel, cwd } ) ;
636+ await installPackages ( { dependencies, isDevDependencies, packageManager , logLevel, cwd } ) ;
623637 installSpinner . stop ( successMessage ) ;
624638 return true ;
625639 } catch ( e ) {
@@ -636,6 +650,7 @@ async function installDependenciesWithSpinner(installOptions: InstallDependencie
636650interface OutroOptions {
637651 root : string ;
638652 name : string ;
653+ packageManager : PackageManager ;
639654 superAdminCredentials ?: { identifier : string ; password : string } ;
640655 includeStorefront ?: boolean ;
641656 serverPort ?: number ;
@@ -647,12 +662,13 @@ function displayOutro(outroOptions: OutroOptions) {
647662 const {
648663 root,
649664 name,
665+ packageManager,
650666 superAdminCredentials,
651667 includeStorefront,
652668 serverPort = SERVER_PORT ,
653669 storefrontPort = STOREFRONT_PORT ,
654670 } = outroOptions ;
655- const startCommand = 'npm run dev' ;
671+ const startCommand = ` ${ getPackageManagerInfo ( packageManager ) . runScript } dev` ;
656672 const identifier = superAdminCredentials ?. identifier ?? SUPER_ADMIN_USER_IDENTIFIER ;
657673 const password = superAdminCredentials ?. password ?? SUPER_ADMIN_USER_PASSWORD ;
658674
0 commit comments