230 lines
5.5 KiB
TypeScript
230 lines
5.5 KiB
TypeScript
import { EOL } from "os"
|
|
import pg from "pg"
|
|
import postgresClient, { DEFAULT_HOST, DEFAULT_PORT } from "./postgres-client.js"
|
|
import inquirer from "inquirer"
|
|
import logMessage from "./log-message.js"
|
|
import formatConnectionString from "./format-connection-string.js"
|
|
import { Ora } from "ora"
|
|
import { getCurrentOs } from "./get-current-os.js"
|
|
|
|
type CreateDbOptions = {
|
|
client: pg.Client
|
|
db: string
|
|
}
|
|
|
|
export default async function createDb({ client, db }: CreateDbOptions) {
|
|
await client.query(`CREATE DATABASE "${db}"`)
|
|
}
|
|
|
|
async function doesDbExist (client: pg.Client, dbName: string): Promise<boolean> {
|
|
const result = await client.query(`SELECT datname FROM pg_catalog.pg_database WHERE datname='${dbName}';`)
|
|
|
|
return !!result.rowCount
|
|
}
|
|
|
|
export async function runCreateDb({
|
|
client,
|
|
dbName,
|
|
spinner,
|
|
}: {
|
|
client: pg.Client
|
|
dbName: string
|
|
spinner: Ora
|
|
}): Promise<pg.Client> {
|
|
let newClient = client
|
|
|
|
try {
|
|
// create postgres database
|
|
await createDb({
|
|
client,
|
|
db: dbName,
|
|
})
|
|
|
|
// create a new connection with database selected
|
|
await client.end()
|
|
newClient = await postgresClient({
|
|
user: client.user,
|
|
password: client.password,
|
|
database: dbName,
|
|
})
|
|
} catch (e) {
|
|
spinner.stop()
|
|
logMessage({
|
|
message: `An error occurred while trying to create your database: ${e}`,
|
|
type: "error",
|
|
})
|
|
}
|
|
|
|
return newClient
|
|
}
|
|
|
|
async function getForDbName({
|
|
dbName,
|
|
verbose = false,
|
|
}: {
|
|
dbName: string
|
|
verbose?: boolean
|
|
}): Promise<{
|
|
client: pg.Client
|
|
dbConnectionString: string
|
|
dbName: string
|
|
}> {
|
|
let client!: pg.Client
|
|
let postgresUsername = "postgres"
|
|
let postgresPassword = ""
|
|
|
|
const defaultConnectionOptions = {
|
|
host: DEFAULT_HOST,
|
|
port: DEFAULT_PORT
|
|
}
|
|
|
|
try {
|
|
client = await postgresClient({
|
|
user: postgresUsername,
|
|
password: postgresPassword,
|
|
...defaultConnectionOptions
|
|
})
|
|
} catch (e) {
|
|
if (verbose) {
|
|
logMessage({
|
|
message: `The following error occured when connecting to the database: ${e}`,
|
|
type: "verbose",
|
|
})
|
|
}
|
|
// ask for the user's postgres credentials
|
|
const answers = await inquirer.prompt([
|
|
{
|
|
type: "input",
|
|
name: "postgresUsername",
|
|
message: "Enter your Postgres username",
|
|
default: "postgres",
|
|
validate: (input) => {
|
|
return typeof input === "string" && input.length > 0
|
|
},
|
|
},
|
|
{
|
|
type: "password",
|
|
name: "postgresPassword",
|
|
message: "Enter your Postgres password",
|
|
},
|
|
])
|
|
|
|
postgresUsername = answers.postgresUsername
|
|
postgresPassword = answers.postgresPassword
|
|
|
|
const { userDbName } = await inquirer.prompt([
|
|
{
|
|
type: "database",
|
|
name: "userDbName",
|
|
message: "Enter your Postgres user's database name",
|
|
default: answers.postgresUsername,
|
|
validate: (input) => {
|
|
return typeof input === "string" && input.length > 0
|
|
},
|
|
},
|
|
])
|
|
|
|
try {
|
|
client = await postgresClient({
|
|
user: postgresUsername,
|
|
password: postgresPassword,
|
|
database: userDbName,
|
|
...defaultConnectionOptions
|
|
})
|
|
} catch (e) {
|
|
logMessage({
|
|
message: `Couldn't connect to PostgreSQL because of the following error: ${e}.${EOL}${EOL}Make sure you have PostgreSQL installed and the credentials you provided are correct.${EOL}${EOL}You can learn how to install PostgreSQL here: https://docs.medusajs.com/development/backend/prepare-environment?os=${getCurrentOs()}#postgresql${EOL}${EOL}If you keep running into this issue despite having PostgreSQL installed, please check out our troubleshooting guidelines: https://docs.medusajs.com/troubleshooting/database-error`,
|
|
type: "error",
|
|
})
|
|
}
|
|
}
|
|
|
|
// check if database exists
|
|
if (await doesDbExist(client, dbName)) {
|
|
const { newDbName } = await inquirer.prompt([
|
|
{
|
|
type: "input",
|
|
name: "newDbName",
|
|
message: `A database already exists with the name ${dbName}, please enter a name for the database:`,
|
|
default: dbName,
|
|
validate: (input) => {
|
|
return typeof input === "string" && input.length > 0 && input !== dbName
|
|
},
|
|
},
|
|
])
|
|
|
|
dbName = newDbName
|
|
}
|
|
|
|
// format connection string
|
|
const dbConnectionString = formatConnectionString({
|
|
user: postgresUsername,
|
|
password: postgresPassword,
|
|
host: client!.host,
|
|
db: dbName,
|
|
})
|
|
|
|
return {
|
|
client,
|
|
dbConnectionString,
|
|
dbName
|
|
}
|
|
}
|
|
|
|
async function getForDbUrl({
|
|
dbUrl,
|
|
verbose = false,
|
|
}: {
|
|
dbUrl: string
|
|
verbose?: boolean
|
|
}): Promise<{
|
|
client: pg.Client
|
|
dbConnectionString: string
|
|
}> {
|
|
let client!: pg.Client
|
|
|
|
try {
|
|
client = await postgresClient({
|
|
connectionString: dbUrl,
|
|
})
|
|
} catch (e) {
|
|
if (verbose) {
|
|
logMessage({
|
|
message: `The following error occured when connecting to the database: ${e}`,
|
|
type: "verbose",
|
|
})
|
|
}
|
|
logMessage({
|
|
message: `Couldn't connect to PostgreSQL using the database URL you passed. Make sure it's correct and try again.`,
|
|
type: "error",
|
|
})
|
|
}
|
|
|
|
return {
|
|
client,
|
|
dbConnectionString: dbUrl,
|
|
}
|
|
}
|
|
|
|
export async function getDbClientAndCredentials({
|
|
dbName = "",
|
|
dbUrl = "",
|
|
verbose = false,
|
|
}): Promise<{
|
|
client: pg.Client
|
|
dbConnectionString: string
|
|
verbose?: boolean
|
|
}> {
|
|
if (dbName) {
|
|
return await getForDbName({
|
|
dbName,
|
|
verbose,
|
|
})
|
|
} else {
|
|
return await getForDbUrl({
|
|
dbUrl,
|
|
verbose,
|
|
})
|
|
}
|
|
}
|