feature: add db:setup command (#8830)

This commit is contained in:
Harminder Virk
2024-08-28 13:08:48 +05:30
committed by GitHub
parent 841cb69ba9
commit 69c5d122b1
5 changed files with 171 additions and 58 deletions

View File

@@ -120,6 +120,42 @@ function buildLocalCommands(cli, isLocalProject) {
desc: `Create a new Medusa project.`,
handler: handlerP(newStarter),
})
.command({
command: "db:setup",
desc: "Create the database, run migrations and sync links",
builder: (builder) => {
builder.option("db", {
type: "string",
describe: "Specify the name of the database you want to create",
})
builder.option("interactive", {
type: "boolean",
default: true,
describe:
"Display prompts. Use --no-interactive flag to run the command without prompts",
})
builder.option("skip-links", {
type: "boolean",
describe: "Do not sync links",
})
builder.option("execute-all-links", {
type: "boolean",
describe:
"Skip prompts and execute all (including unsafe) actions from sync links",
})
builder.option("execute-safe-links", {
type: "boolean",
describe:
"Skip prompts and execute only safe actions from sync links",
})
},
handler: handlerP(
getCommandHandler("db/setup", (args, cmd) => {
process.env.NODE_ENV = process.env.NODE_ENV || `development`
return cmd(args)
})
),
})
.command({
command: "db:create",
desc: "Create the database used by your application",

View File

@@ -10,7 +10,19 @@ import {
parseConnectionString,
} from "@medusajs/utils"
const main = async function ({ directory, interactive, db }) {
/**
* A low-level utility to create the database. This util should
* never exit the process implicitly.
*/
export async function dbCreate({
db,
directory,
interactive,
}: {
db: string | undefined
directory: string
interactive: boolean
}): Promise<boolean> {
let dbName = db
/**
@@ -33,8 +45,7 @@ const main = async function ({ directory, interactive, db }) {
logger.error(
`Missing "DATABASE_URL" inside the .env file. The value is required to connect to the PostgreSQL server`
)
process.exitCode = 1
return
return false
}
/**
@@ -45,18 +56,11 @@ const main = async function ({ directory, interactive, db }) {
const defaultValue =
envEditor.get("DB_NAME") ?? `medusa-${slugify(basename(directory))}`
if (interactive) {
try {
dbName = await input({
message: "Enter the database name",
default: defaultValue,
required: true,
})
} catch (error) {
if (error.name === "ExitPromptError") {
process.exit()
}
throw error
}
dbName = await input({
message: "Enter the database name",
default: defaultValue,
required: true,
})
} else {
dbName = defaultValue
}
@@ -82,12 +86,11 @@ const main = async function ({ directory, interactive, db }) {
await client.connect()
logger.info(`Connection established with the database "${dbName}"`)
} catch (error) {
process.exitCode = 1
logger.error(
"Unable to establish database connection because of the following error"
)
logger.error(error)
return
return false
}
if (await dbExists(client, dbName)) {
@@ -97,7 +100,7 @@ const main = async function ({ directory, interactive, db }) {
await envEditor.save()
logger.info(`Updated .env file with "DB_NAME=${dbName}"`)
return
return true
}
await createDb(client, dbName)
@@ -106,6 +109,20 @@ const main = async function ({ directory, interactive, db }) {
envEditor.set("DB_NAME", dbName)
await envEditor.save()
logger.info(`Updated .env file with "DB_NAME=${dbName}"`)
return true
}
const main = async function ({ directory, interactive, db }) {
try {
const created = await dbCreate({ directory, interactive, db })
process.exit(created ? 0 : 1)
} catch (error) {
if (error.name === "ExitPromptError") {
process.exit()
}
logger.error(error)
process.exit(1)
}
}
export default main

View File

@@ -9,6 +9,62 @@ import { getResolvedPlugins } from "../../loaders/helpers/resolve-plugins"
const TERMINAL_SIZE = process.stdout.columns
/**
* A low-level utility to migrate the database. This util should
* never exit the process implicitly.
*/
export async function migrate({
directory,
skipLinks,
executeAllLinks,
executeSafeLinks,
}: {
directory: string
skipLinks: boolean
executeAllLinks: boolean
executeSafeLinks: boolean
}): Promise<boolean> {
/**
* Setup
*/
const container = await initializeContainer(directory)
await ensureDbExists(container)
const medusaAppLoader = new MedusaAppLoader()
const configModule = container.resolve(
ContainerRegistrationKeys.CONFIG_MODULE
)
const plugins = getResolvedPlugins(directory, configModule, true) || []
const linksSourcePaths = plugins.map((plugin) =>
join(plugin.resolve, "links")
)
await new LinkLoader(linksSourcePaths).load()
/**
* Run migrations
*/
logger.info("Running migrations...")
await medusaAppLoader.runModulesMigrations({
action: "run",
})
console.log(new Array(TERMINAL_SIZE).join("-"))
logger.info("Migrations completed")
/**
* Sync links
*/
if (!skipLinks) {
console.log(new Array(TERMINAL_SIZE).join("-"))
await syncLinks(medusaAppLoader, {
executeAll: executeAllLinks,
executeSafe: executeSafeLinks,
})
}
return true
}
const main = async function ({
directory,
skipLinks,
@@ -16,45 +72,13 @@ const main = async function ({
executeSafeLinks,
}) {
try {
/**
* Setup
*/
const container = await initializeContainer(directory)
await ensureDbExists(container)
const medusaAppLoader = new MedusaAppLoader()
const configModule = container.resolve(
ContainerRegistrationKeys.CONFIG_MODULE
)
const plugins = getResolvedPlugins(directory, configModule, true) || []
const linksSourcePaths = plugins.map((plugin) =>
join(plugin.resolve, "links")
)
await new LinkLoader(linksSourcePaths).load()
/**
* Run migrations
*/
logger.info("Running migrations...")
await medusaAppLoader.runModulesMigrations({
action: "run",
const migrated = await migrate({
directory,
skipLinks,
executeAllLinks,
executeSafeLinks,
})
console.log(new Array(TERMINAL_SIZE).join("-"))
logger.info("Migrations completed")
/**
* Sync links
*/
if (!skipLinks) {
console.log(new Array(TERMINAL_SIZE).join("-"))
await syncLinks(medusaAppLoader, {
executeAll: executeAllLinks,
executeSafe: executeSafeLinks,
})
}
process.exit()
process.exit(migrated ? 0 : 1)
} catch (error) {
logger.error(error)
process.exit(1)

View File

@@ -0,0 +1,36 @@
import { logger } from "@medusajs/framework"
import { dbCreate } from "./create"
import { migrate } from "./migrate"
const main = async function ({
directory,
interactive,
db,
skipLinks,
executeAllLinks,
executeSafeLinks,
}) {
try {
const created = await dbCreate({ directory, interactive, db })
if (!created) {
process.exit(1)
}
const migrated = await migrate({
directory,
skipLinks,
executeAllLinks,
executeSafeLinks,
})
process.exit(migrated ? 0 : 1)
} catch (error) {
if (error.name === "ExitPromptError") {
process.exit()
}
logger.error(error)
process.exit(1)
}
}
export default main

View File

@@ -193,8 +193,8 @@ const main = async function ({ directory, executeSafe, executeAll }) {
await syncLinks(medusaAppLoader, { executeAll, executeSafe })
process.exit()
} catch (e) {
logger.error(e)
} catch (error) {
logger.error(error)
process.exit(1)
}
}