feat(create-medusa-app): install v2 by default (#7381)
- Remove `v2` option and install V2 starter branch by default. - Use new `exec` command to seed data - Install v2 branch of next.js starter if the option is provided. - Change the opened browser to `localhost:9000/app`. - Added a bunch of todos for onboarding flows once we have that
This commit is contained in:
@@ -10,7 +10,6 @@ type CloneRepoOptions = {
|
||||
repoUrl?: string
|
||||
abortController?: AbortController
|
||||
verbose?: boolean
|
||||
v2?: boolean
|
||||
}
|
||||
|
||||
const DEFAULT_REPO = "https://github.com/medusajs/medusa-starter-default"
|
||||
@@ -21,13 +20,10 @@ export default async function cloneRepo({
|
||||
repoUrl,
|
||||
abortController,
|
||||
verbose = false,
|
||||
v2 = false,
|
||||
}: CloneRepoOptions) {
|
||||
await execute(
|
||||
[
|
||||
`git clone ${repoUrl || DEFAULT_REPO}${
|
||||
v2 ? ` -b ${V2_BRANCH}` : ""
|
||||
} ${directoryName}`,
|
||||
`git clone ${repoUrl || DEFAULT_REPO} -b ${V2_BRANCH} ${directoryName}`,
|
||||
{
|
||||
signal: abortController?.signal,
|
||||
},
|
||||
@@ -42,14 +38,12 @@ export async function runCloneRepo({
|
||||
abortController,
|
||||
spinner,
|
||||
verbose = false,
|
||||
v2 = false,
|
||||
}: {
|
||||
projectName: string
|
||||
repoUrl: string
|
||||
abortController: AbortController
|
||||
spinner: Ora
|
||||
verbose?: boolean
|
||||
v2?: boolean
|
||||
}) {
|
||||
try {
|
||||
await cloneRepo({
|
||||
@@ -57,7 +51,6 @@ export async function runCloneRepo({
|
||||
repoUrl,
|
||||
abortController,
|
||||
verbose,
|
||||
v2,
|
||||
})
|
||||
|
||||
deleteGitDirectory(projectName)
|
||||
|
||||
@@ -14,7 +14,6 @@ export type FactBoxOptions = {
|
||||
}
|
||||
|
||||
const facts = [
|
||||
"Plugins allow you to integrate third-party services for payment, fulfillment, notifications, and more.",
|
||||
"You can specify a product's availability in one or more sales channels.",
|
||||
"Payment and shipping options and providers can be configured per region.",
|
||||
"Tax-inclusive pricing allows you to set prices for products, shipping options, and more without having to worry about calculating taxes.",
|
||||
@@ -24,13 +23,16 @@ const facts = [
|
||||
"Publishable-API Keys allow you to send requests to the backend within a scoped resource.",
|
||||
"You can create custom endpoints by creating a TypeScript file under the src/api directory.",
|
||||
"You can listen to events to perform asynchronous actions using Subscribers.",
|
||||
"An entity represents a table in the database. You can create a table by creating a custom entity and migration.",
|
||||
"A data model represents a table in the database. You can create a table by creating a custom data model and migration in a module.",
|
||||
"Medusa's store endpoint paths are prefixed by /store. The admin endpoints are prefixed by /admin.",
|
||||
"Medusa provides a JavaScript client and a React library that you can use to build a storefront or a custom admin.",
|
||||
"Services are classes with methods related to an entity or functionality. You can create a custom service in a TypeScript file under src/services.",
|
||||
"Modules hold your custom features and data models. You create them under the src/modules directory. Each module must have a service.",
|
||||
"A service is a class with methods related to a functionality or a data model. You create a service in a module.",
|
||||
"Modules allow you to replace an entire functionality with your custom logic.",
|
||||
"The event bus module is responsible for triggering events and relaying them to subscribers.",
|
||||
"The cache module is responsible for caching data that requires heavy computation.",
|
||||
"A workflow is a series of steps that are defined once and executed anywhere. Workflows are created under the src/workflows directory.",
|
||||
"A workflow's steps can be retried or rolled back in case of an error."
|
||||
]
|
||||
|
||||
export const getFact = () => {
|
||||
|
||||
@@ -7,6 +7,7 @@ import path from "path"
|
||||
import { customAlphabet } from "nanoid"
|
||||
import { isAbortError } from "./create-abort-controller.js"
|
||||
import logMessage from "./log-message.js"
|
||||
import ProcessManager from "./process-manager.js"
|
||||
|
||||
const NEXTJS_REPO = "https://github.com/medusajs/nextjs-starter-medusa"
|
||||
|
||||
@@ -28,6 +29,7 @@ type InstallOptions = {
|
||||
abortController?: AbortController
|
||||
factBoxOptions: FactBoxOptions
|
||||
verbose?: boolean
|
||||
processManager: ProcessManager
|
||||
}
|
||||
|
||||
export async function installNextjsStarter({
|
||||
@@ -35,6 +37,7 @@ export async function installNextjsStarter({
|
||||
abortController,
|
||||
factBoxOptions,
|
||||
verbose = false,
|
||||
processManager
|
||||
}: InstallOptions): Promise<string> {
|
||||
factBoxOptions.interval = displayFactBox({
|
||||
...factBoxOptions,
|
||||
@@ -56,19 +59,35 @@ export async function installNextjsStarter({
|
||||
}
|
||||
|
||||
try {
|
||||
// TODO change back to use create-next-app once Next.js v2 changes land on the main branch
|
||||
await execute(
|
||||
[
|
||||
`npx create-next-app -e ${NEXTJS_REPO} ${nextjsDirectory}`,
|
||||
`git clone ${NEXTJS_REPO} -b v2 ${nextjsDirectory}`,
|
||||
{
|
||||
signal: abortController?.signal,
|
||||
env: {
|
||||
...process.env,
|
||||
npm_config_yes: "yes",
|
||||
},
|
||||
env: process.env,
|
||||
},
|
||||
],
|
||||
{ verbose }
|
||||
)
|
||||
const execOptions = {
|
||||
signal: abortController?.signal,
|
||||
cwd: nextjsDirectory
|
||||
}
|
||||
await processManager.runProcess({
|
||||
process: async () => {
|
||||
try {
|
||||
await execute([`yarn`, execOptions], { verbose })
|
||||
} catch (e) {
|
||||
// yarn isn't available
|
||||
// use npm
|
||||
await execute([`npm install`, execOptions], {
|
||||
verbose,
|
||||
})
|
||||
}
|
||||
},
|
||||
ignoreERESOLVE: true,
|
||||
})
|
||||
} catch (e) {
|
||||
if (isAbortError(e)) {
|
||||
process.exit()
|
||||
@@ -80,6 +99,11 @@ export async function installNextjsStarter({
|
||||
})
|
||||
}
|
||||
|
||||
fs.rmSync(path.join(nextjsDirectory, ".git"), {
|
||||
recursive: true,
|
||||
force: true,
|
||||
})
|
||||
|
||||
fs.renameSync(
|
||||
path.join(nextjsDirectory, ".env.template"),
|
||||
path.join(nextjsDirectory, ".env.local")
|
||||
|
||||
@@ -26,7 +26,6 @@ type PrepareOptions = {
|
||||
nextjsDirectory?: string
|
||||
client: Client | null
|
||||
verbose?: boolean
|
||||
v2?: boolean
|
||||
}
|
||||
|
||||
export default async ({
|
||||
@@ -44,7 +43,6 @@ export default async ({
|
||||
nextjsDirectory = "",
|
||||
client,
|
||||
verbose = false,
|
||||
v2 = false,
|
||||
}: PrepareOptions) => {
|
||||
// initialize execution options
|
||||
const execOptions = {
|
||||
@@ -73,10 +71,7 @@ export default async ({
|
||||
let inviteToken: string | undefined = undefined
|
||||
|
||||
if (!skipDb) {
|
||||
let env = `DATABASE_TYPE=postgres${EOL}DATABASE_URL=${dbConnectionString}${EOL}MEDUSA_ADMIN_ONBOARDING_TYPE=${onboardingType}${EOL}STORE_CORS=http://localhost:8000,http://localhost:7001`
|
||||
if (v2) {
|
||||
env += `${EOL}POSTGRES_URL=${dbConnectionString}`
|
||||
}
|
||||
let env = `DATABASE_TYPE=postgres${EOL}DATABASE_URL=${dbConnectionString}${EOL}MEDUSA_ADMIN_ONBOARDING_TYPE=${onboardingType}${EOL}STORE_CORS=http://localhost:8000,http://localhost:7001${EOL}POSTGRES_URL=${dbConnectionString}`
|
||||
if (nextjsDirectory) {
|
||||
env += `${EOL}MEDUSA_ADMIN_ONBOARDING_NEXTJS_DIRECTORY=${nextjsDirectory}`
|
||||
}
|
||||
@@ -154,7 +149,7 @@ export default async ({
|
||||
await processManager.runProcess({
|
||||
process: async () => {
|
||||
const proc = await execute(
|
||||
["npx @medusajs/medusa-cli@latest migrations run", npxOptions],
|
||||
["npx medusa migrations run", npxOptions],
|
||||
{ verbose, needOutput: true }
|
||||
)
|
||||
|
||||
@@ -164,7 +159,7 @@ export default async ({
|
||||
let errorOccurred = false
|
||||
try {
|
||||
const migrations = await client.query(
|
||||
`SELECT * FROM "${v2 ? "mikro_orm_migrations" : "migrations"}"`
|
||||
`SELECT * FROM "mikro_orm_migrations"`
|
||||
)
|
||||
errorOccurred = migrations.rowCount == 0
|
||||
} catch (e) {
|
||||
@@ -191,7 +186,7 @@ export default async ({
|
||||
})
|
||||
}
|
||||
|
||||
if (admin && !skipDb && migrations && !v2) {
|
||||
if (admin && !skipDb && migrations) {
|
||||
// create admin user
|
||||
factBoxOptions.interval = displayFactBox({
|
||||
...factBoxOptions,
|
||||
@@ -202,7 +197,7 @@ export default async ({
|
||||
process: async () => {
|
||||
const proc = await execute(
|
||||
[
|
||||
`npx @medusajs/medusa-cli@latest user -e ${admin.email} --invite`,
|
||||
`npx medusa user -e ${admin.email} --invite`,
|
||||
npxOptions,
|
||||
],
|
||||
{ verbose, needOutput: true }
|
||||
@@ -223,70 +218,47 @@ export default async ({
|
||||
}
|
||||
|
||||
if (!skipDb && migrations) {
|
||||
if (seed || !boilerplate) {
|
||||
factBoxOptions.interval = displayFactBox({
|
||||
...factBoxOptions,
|
||||
title: "Seeding database...",
|
||||
})
|
||||
// TODO for now we just seed the default data
|
||||
// we should add onboarding seeding again if it makes
|
||||
// since once we re-introduce the onboarding flow.
|
||||
factBoxOptions.interval = displayFactBox({
|
||||
...factBoxOptions,
|
||||
title: "Seeding database...",
|
||||
})
|
||||
|
||||
// check if a seed file exists in the project
|
||||
if (!fs.existsSync(path.join(directory, "data", "seed.json"))) {
|
||||
spinner
|
||||
?.warn(
|
||||
chalk.yellow(
|
||||
"Seed file was not found in the project. Skipping seeding..."
|
||||
)
|
||||
const seedScriptPath = path.join("dist", "helpers", "seed.js")
|
||||
|
||||
// check if a seed file exists in the project
|
||||
if (!fs.existsSync(path.join(directory, seedScriptPath))) {
|
||||
spinner
|
||||
?.warn(
|
||||
chalk.yellow(
|
||||
"Seed file was not found in the project. Skipping seeding..."
|
||||
)
|
||||
.start()
|
||||
return inviteToken
|
||||
}
|
||||
|
||||
await processManager.runProcess({
|
||||
process: async () => {
|
||||
await execute(
|
||||
[
|
||||
`npx @medusajs/medusa-cli@latest seed --seed-file=${path.join(
|
||||
"data",
|
||||
"seed.json"
|
||||
)}`,
|
||||
npxOptions,
|
||||
],
|
||||
{ verbose }
|
||||
)
|
||||
},
|
||||
})
|
||||
|
||||
displayFactBox({
|
||||
...factBoxOptions,
|
||||
message: "Seeded database with demo data",
|
||||
})
|
||||
} else if (
|
||||
fs.existsSync(path.join(directory, "data", "seed-onboarding.json"))
|
||||
) {
|
||||
// seed the database with onboarding seed
|
||||
factBoxOptions.interval = displayFactBox({
|
||||
...factBoxOptions,
|
||||
title: "Finish preparation...",
|
||||
})
|
||||
|
||||
await processManager.runProcess({
|
||||
process: async () => {
|
||||
await execute(
|
||||
[
|
||||
`npx @medusajs/medusa-cli@latest seed --seed-file=${path.join(
|
||||
"data",
|
||||
"seed-onboarding.json"
|
||||
)}`,
|
||||
npxOptions,
|
||||
],
|
||||
{ verbose }
|
||||
)
|
||||
},
|
||||
})
|
||||
)
|
||||
.start()
|
||||
return inviteToken
|
||||
}
|
||||
|
||||
displayFactBox({ ...factBoxOptions, message: "Finished Preparation" })
|
||||
await processManager.runProcess({
|
||||
process: async () => {
|
||||
await execute(
|
||||
[
|
||||
`npx medusa exec ${seedScriptPath}`,
|
||||
npxOptions,
|
||||
],
|
||||
{ verbose }
|
||||
)
|
||||
},
|
||||
})
|
||||
|
||||
displayFactBox({
|
||||
...factBoxOptions,
|
||||
message: "Seeded database with demo data",
|
||||
})
|
||||
}
|
||||
|
||||
displayFactBox({ ...factBoxOptions, message: "Finished Preparation" })
|
||||
|
||||
return inviteToken
|
||||
}
|
||||
|
||||
@@ -6,13 +6,11 @@ type StartOptions = {
|
||||
}
|
||||
|
||||
export default ({ directory, abortController }: StartOptions) => {
|
||||
const childProcess = exec(`npx @medusajs/medusa-cli@latest develop`, {
|
||||
const childProcess = exec(`npm run dev`, {
|
||||
cwd: directory,
|
||||
signal: abortController?.signal,
|
||||
env: {
|
||||
...process.env,
|
||||
OPEN_BROWSER: "false",
|
||||
npm_config_yes: "yes",
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user