fix(create-medusa-app): ensure the same package manager is used consistently (#12714)
* fix(create-medusa-app): ensure the same package manager is used consistently * fix verbose not working as expected * improvements * remove legacy peer deps * format
This commit is contained in:
5
.changeset/shy-nails-enjoy.md
Normal file
5
.changeset/shy-nails-enjoy.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"create-medusa-app": patch
|
||||
---
|
||||
|
||||
fix(create-medusa-app): ensure the same package manager is used consistently
|
||||
@@ -32,13 +32,15 @@ const execute = async (
|
||||
const childProcess = spawnSync(commandStr, {
|
||||
...options,
|
||||
shell: true,
|
||||
stdio: needOutput
|
||||
? "pipe"
|
||||
: [process.stdin, process.stdout, process.stderr],
|
||||
stdio: needOutput ?
|
||||
"pipe" :
|
||||
[process.stdin, process.stdout, process.stderr],
|
||||
})
|
||||
|
||||
if (childProcess.error) {
|
||||
throw childProcess.error
|
||||
if (childProcess.error || childProcess.status !== 0) {
|
||||
throw childProcess.error ||
|
||||
childProcess.stderr?.toString() ||
|
||||
`${commandStr} failed with status ${childProcess.status}`
|
||||
}
|
||||
|
||||
if (
|
||||
|
||||
87
packages/cli/create-medusa-app/src/utils/package-manager.ts
Normal file
87
packages/cli/create-medusa-app/src/utils/package-manager.ts
Normal file
@@ -0,0 +1,87 @@
|
||||
import execute from "./execute.js"
|
||||
import ProcessManager from "./process-manager.js"
|
||||
|
||||
export default class PackageManager {
|
||||
protected packageManager?: "npm" | "yarn"
|
||||
protected processManager: ProcessManager
|
||||
protected verbose
|
||||
|
||||
constructor(processManager: ProcessManager, verbose = false) {
|
||||
this.processManager = processManager
|
||||
this.verbose = verbose
|
||||
}
|
||||
|
||||
async setPackageManager(execOptions: Record<string, unknown>): Promise<void> {
|
||||
if (this.packageManager) {
|
||||
return
|
||||
}
|
||||
|
||||
// check whether yarn is available
|
||||
await this.processManager.runProcess({
|
||||
process: async () => {
|
||||
try {
|
||||
await execute([`yarn -v`, execOptions], { verbose: this.verbose })
|
||||
// yarn is available
|
||||
this.packageManager = "yarn"
|
||||
} catch (e) {
|
||||
// yarn isn't available
|
||||
// use npm
|
||||
this.packageManager = "npm"
|
||||
}
|
||||
},
|
||||
ignoreERESOLVE: true,
|
||||
})
|
||||
}
|
||||
|
||||
async installDependencies(
|
||||
execOptions: Record<string, unknown>,
|
||||
) {
|
||||
if (!this.packageManager) {
|
||||
await this.setPackageManager(execOptions)
|
||||
}
|
||||
|
||||
const command = this.packageManager === "yarn" ?
|
||||
`yarn` : `npm install`
|
||||
|
||||
await this.processManager.runProcess({
|
||||
process: async () => {
|
||||
await execute([command, execOptions], {
|
||||
verbose: this.verbose
|
||||
})
|
||||
},
|
||||
ignoreERESOLVE: true,
|
||||
})
|
||||
}
|
||||
|
||||
async runCommand(
|
||||
command: string,
|
||||
execOptions: Record<string, unknown>,
|
||||
) {
|
||||
if (!this.packageManager) {
|
||||
await this.setPackageManager(execOptions)
|
||||
}
|
||||
|
||||
const commandStr = this.getCommandStr(command)
|
||||
|
||||
await this.processManager.runProcess({
|
||||
process: async () => {
|
||||
await execute([commandStr, execOptions], {
|
||||
verbose: this.verbose
|
||||
})
|
||||
},
|
||||
ignoreERESOLVE: true,
|
||||
})
|
||||
}
|
||||
|
||||
getCommandStr(
|
||||
command: string,
|
||||
): string {
|
||||
if (!this.packageManager) {
|
||||
throw new Error("Package manager not set")
|
||||
}
|
||||
|
||||
return this.packageManager === "yarn"
|
||||
? `yarn ${command}`
|
||||
: `npm run ${command}`
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import { EOL } from "os"
|
||||
import { displayFactBox, FactBoxOptions } from "./facts.js"
|
||||
import ProcessManager from "./process-manager.js"
|
||||
import type { Client } from "pg"
|
||||
import PackageManager from "./package-manager.js"
|
||||
|
||||
const ADMIN_EMAIL = "admin@medusa-test.com"
|
||||
let STORE_CORS = "http://localhost:8000"
|
||||
@@ -24,6 +25,7 @@ type PreparePluginOptions = {
|
||||
processManager: ProcessManager
|
||||
abortController?: AbortController
|
||||
verbose?: boolean
|
||||
packageManager: PackageManager
|
||||
}
|
||||
|
||||
type PrepareProjectOptions = {
|
||||
@@ -42,6 +44,7 @@ type PrepareProjectOptions = {
|
||||
nextjsDirectory?: string
|
||||
client: Client | null
|
||||
verbose?: boolean
|
||||
packageManager: PackageManager
|
||||
}
|
||||
|
||||
type PrepareOptions = PreparePluginOptions | PrepareProjectOptions
|
||||
@@ -66,6 +69,7 @@ async function preparePlugin({
|
||||
processManager,
|
||||
abortController,
|
||||
verbose = false,
|
||||
packageManager,
|
||||
}: PreparePluginOptions) {
|
||||
// initialize execution options
|
||||
const execOptions = {
|
||||
@@ -98,20 +102,7 @@ async function preparePlugin({
|
||||
processManager,
|
||||
})
|
||||
|
||||
await processManager.runProcess({
|
||||
process: async () => {
|
||||
try {
|
||||
await execute([`yarn`, execOptions], { verbose })
|
||||
} catch (e) {
|
||||
// yarn isn't available
|
||||
// use npm
|
||||
await execute([`npm install --legacy-peer-deps`, execOptions], {
|
||||
verbose,
|
||||
})
|
||||
}
|
||||
},
|
||||
ignoreERESOLVE: true,
|
||||
})
|
||||
await packageManager.installDependencies(execOptions)
|
||||
|
||||
factBoxOptions.interval = displayFactBox({
|
||||
...factBoxOptions,
|
||||
@@ -136,6 +127,7 @@ async function prepareProject({
|
||||
nextjsDirectory = "",
|
||||
client,
|
||||
verbose = false,
|
||||
packageManager,
|
||||
}: PrepareProjectOptions) {
|
||||
// initialize execution options
|
||||
const execOptions = {
|
||||
@@ -196,20 +188,7 @@ async function prepareProject({
|
||||
processManager,
|
||||
})
|
||||
|
||||
await processManager.runProcess({
|
||||
process: async () => {
|
||||
try {
|
||||
await execute([`yarn`, execOptions], { verbose })
|
||||
} catch (e) {
|
||||
// yarn isn't available
|
||||
// use npm
|
||||
await execute([`npm install --legacy-peer-deps`, execOptions], {
|
||||
verbose,
|
||||
})
|
||||
}
|
||||
},
|
||||
ignoreERESOLVE: true,
|
||||
})
|
||||
await packageManager.installDependencies(execOptions)
|
||||
|
||||
factBoxOptions.interval = displayFactBox({
|
||||
...factBoxOptions,
|
||||
@@ -285,18 +264,7 @@ async function prepareProject({
|
||||
title: "Seeding database...",
|
||||
})
|
||||
|
||||
await processManager.runProcess({
|
||||
process: async () => {
|
||||
try {
|
||||
await execute([`yarn seed`, execOptions], { verbose })
|
||||
} catch (e) {
|
||||
// yarn isn't available
|
||||
// use npm
|
||||
await execute([`npm run seed`, execOptions], { verbose })
|
||||
}
|
||||
},
|
||||
ignoreERESOLVE: true,
|
||||
})
|
||||
await packageManager.runCommand("seed", execOptions)
|
||||
|
||||
displayFactBox({
|
||||
...factBoxOptions,
|
||||
|
||||
@@ -3,6 +3,7 @@ import path from "path"
|
||||
import createAbortController from "../create-abort-controller.js"
|
||||
import { FactBoxOptions } from "../facts.js"
|
||||
import ProcessManager from "../process-manager.js"
|
||||
import PackageManager from "../package-manager.js"
|
||||
|
||||
export interface ProjectOptions {
|
||||
repoUrl?: string
|
||||
@@ -25,6 +26,7 @@ export interface ProjectCreator {
|
||||
export abstract class BaseProjectCreator {
|
||||
protected spinner: Ora
|
||||
protected processManager: ProcessManager
|
||||
protected packageManager: PackageManager
|
||||
protected abortController: AbortController
|
||||
protected factBoxOptions: FactBoxOptions
|
||||
protected projectName: string
|
||||
@@ -39,6 +41,7 @@ export abstract class BaseProjectCreator {
|
||||
) {
|
||||
this.spinner = ora()
|
||||
this.processManager = new ProcessManager()
|
||||
this.packageManager = new PackageManager(this.processManager)
|
||||
this.abortController = createAbortController(this.processManager)
|
||||
this.projectName = projectName
|
||||
const basePath =
|
||||
|
||||
@@ -72,6 +72,7 @@ export class PluginProjectCreator
|
||||
processManager: this.processManager,
|
||||
abortController: this.abortController,
|
||||
verbose: this.options.verbose,
|
||||
packageManager: this.packageManager,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -153,6 +153,7 @@ export class MedusaProjectCreator
|
||||
nextjsDirectory: this.nextjsDirectory,
|
||||
client: this.client,
|
||||
verbose: this.options.verbose,
|
||||
packageManager: this.packageManager,
|
||||
})
|
||||
} finally {
|
||||
await this.client?.end()
|
||||
@@ -214,18 +215,19 @@ export class MedusaProjectCreator
|
||||
}
|
||||
|
||||
protected showSuccessMessage(): void {
|
||||
const commandStr = this.packageManager.getCommandStr(`dev`)
|
||||
logMessage({
|
||||
message: boxen(
|
||||
chalk.green(
|
||||
`Change to the \`${
|
||||
this.projectName
|
||||
}\` directory to explore your Medusa project.${EOL}${EOL}Start your Medusa application again with the following command:${EOL}${EOL}yarn dev${EOL}${EOL}${
|
||||
}\` directory to explore your Medusa project.${EOL}${EOL}Start your Medusa application again with the following command:${EOL}${EOL}${commandStr}${EOL}${EOL}${
|
||||
this.inviteToken
|
||||
? `After you start the Medusa application, you can create an admin user with the URL http://localhost:9000/app/invite?token=${this.inviteToken}&first_run=true${EOL}${EOL}`
|
||||
: ""
|
||||
}${
|
||||
this.nextjsDirectory?.length
|
||||
? `The Next.js Starter Storefront was installed in the \`${this.nextjsDirectory}\` directory. Change to that directory and start it with the following command:${EOL}${EOL}npm run dev${EOL}${EOL}`
|
||||
? `The Next.js Starter Storefront was installed in the \`${this.nextjsDirectory}\` directory. Change to that directory and start it with the following command:${EOL}${EOL}${commandStr}${EOL}${EOL}`
|
||||
: ""
|
||||
}Check out the Medusa documentation to start your development:${EOL}${EOL}https://docs.medusajs.com/${EOL}${EOL}Star us on GitHub if you like what we're building:${EOL}${EOL}https://github.com/medusajs/medusa/stargazers`
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user