chore(medusa): Improve database loader error handling (#4254)
* chore(medusa): Improve database loader error handling * Create sharp-melons-doubt.md * move the database error handling to the utils * fix unit tests * tackle feedback * fix unit tests
This commit is contained in:
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@medusajs/medusa": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
chore(medusa): Improve database loader error handling
|
||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
} from "typeorm"
|
} from "typeorm"
|
||||||
import { ConfigModule } from "../types/global"
|
import { ConfigModule } from "../types/global"
|
||||||
import "../utils/naming-strategy"
|
import "../utils/naming-strategy"
|
||||||
|
import { handlePostgresDatabaseError } from "@medusajs/utils"
|
||||||
|
|
||||||
type Options = {
|
type Options = {
|
||||||
configModule: ConfigModule
|
configModule: ConfigModule
|
||||||
@@ -52,33 +53,14 @@ export default async ({
|
|||||||
(configModule.projectConfig.database_logging || false),
|
(configModule.projectConfig.database_logging || false),
|
||||||
} as DataSourceOptions)
|
} as DataSourceOptions)
|
||||||
|
|
||||||
try {
|
await dataSource.initialize().catch(handlePostgresDatabaseError)
|
||||||
await dataSource.initialize()
|
|
||||||
} catch (err) {
|
|
||||||
// database name does not exist
|
|
||||||
if (err.code === "3D000") {
|
|
||||||
throw new Error(
|
|
||||||
`Specified database does not exist. Please create it and try again.\n${err.message}`
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
throw err
|
|
||||||
}
|
|
||||||
|
|
||||||
// If migrations are not included in the config, we assume you are attempting to start the server
|
// If migrations are not included in the config, we assume you are attempting to start the server
|
||||||
// Therefore, throw if the database is not migrated
|
// Therefore, throw if the database is not migrated
|
||||||
if (!dataSource.migrations?.length) {
|
if (!dataSource.migrations?.length) {
|
||||||
try {
|
await dataSource
|
||||||
await dataSource.query(`select * from migrations`)
|
.query(`select * from migrations`)
|
||||||
} catch (err) {
|
.catch(handlePostgresDatabaseError)
|
||||||
if (err.code === "42P01") {
|
|
||||||
throw new Error(
|
|
||||||
`Migrations missing. Please run 'medusa migrations run' and try again.`
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
throw err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return dataSource
|
return dataSource
|
||||||
|
|||||||
@@ -0,0 +1,107 @@
|
|||||||
|
import {
|
||||||
|
DatabaseErrorCode,
|
||||||
|
handlePostgresDatabaseError,
|
||||||
|
} from "../handle-postgres-database-error"
|
||||||
|
import { EOL } from "os"
|
||||||
|
|
||||||
|
describe("handlePostgresDataError", function () {
|
||||||
|
it("should throw a specific message on database does not exists", function () {
|
||||||
|
const error = new Error("database does not exist")
|
||||||
|
Object.assign(error, { code: DatabaseErrorCode.databaseDoesNotExist })
|
||||||
|
|
||||||
|
let outputError: any
|
||||||
|
try {
|
||||||
|
handlePostgresDatabaseError(error)
|
||||||
|
} catch (e) {
|
||||||
|
outputError = e
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(outputError.message).toEqual(
|
||||||
|
`The specified PostgreSQL database does not exist. Please create it and try again.${EOL}${error.message}`
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should throw a specific message on database connection failure", function () {
|
||||||
|
const error = new Error("database does not exist")
|
||||||
|
Object.assign(error, { code: DatabaseErrorCode.connectionFailure })
|
||||||
|
|
||||||
|
let outputError: any
|
||||||
|
try {
|
||||||
|
handlePostgresDatabaseError(error)
|
||||||
|
} catch (e) {
|
||||||
|
outputError = e
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(outputError.message).toEqual(
|
||||||
|
`Failed to establish a connection to PostgreSQL. Please ensure the following is true and try again:
|
||||||
|
- You have a PostgreSQL database running
|
||||||
|
- You have passed the correct credentials in medusa-config.js
|
||||||
|
- You have formatted the database connection string correctly. See below:
|
||||||
|
"postgres://[username]:[password]@[host]:[post]/[db_name]" - If there is no password, you can omit it from the connection string
|
||||||
|
${EOL}
|
||||||
|
${error.message}`
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should throw a specific message on database wrong credentials", function () {
|
||||||
|
const error = new Error("database does not exist")
|
||||||
|
Object.assign(error, { code: DatabaseErrorCode.wrongCredentials })
|
||||||
|
|
||||||
|
let outputError: any
|
||||||
|
try {
|
||||||
|
handlePostgresDatabaseError(error)
|
||||||
|
} catch (e) {
|
||||||
|
outputError = e
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(outputError.message).toEqual(
|
||||||
|
`The specified credentials does not exists for the specified PostgreSQL database.${EOL}${error.message}`
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should throw a specific message on database not found", function () {
|
||||||
|
const error = new Error("database does not exist")
|
||||||
|
Object.assign(error, { code: DatabaseErrorCode.notFound })
|
||||||
|
|
||||||
|
let outputError: any
|
||||||
|
try {
|
||||||
|
handlePostgresDatabaseError(error)
|
||||||
|
} catch (e) {
|
||||||
|
outputError = e
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(outputError.message).toEqual(
|
||||||
|
`The specified connection string for your PostgreSQL database might have illegal characters. Please check that it only contains allowed characters [a-zA-Z0-9]${EOL}${error.message}`
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should throw a specific message on database migration missing", function () {
|
||||||
|
const error = new Error("database does not exist")
|
||||||
|
Object.assign(error, { code: DatabaseErrorCode.migrationMissing })
|
||||||
|
|
||||||
|
let outputError: any
|
||||||
|
try {
|
||||||
|
handlePostgresDatabaseError(error)
|
||||||
|
} catch (e) {
|
||||||
|
outputError = e
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(outputError.message).toEqual(
|
||||||
|
`Migrations missing. Please run 'medusa migrations run' and try again.`
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should re throw unhandled error code", function () {
|
||||||
|
const error = new Error("database does not exist")
|
||||||
|
Object.assign(error, { code: "test" })
|
||||||
|
|
||||||
|
let outputError: any
|
||||||
|
try {
|
||||||
|
handlePostgresDatabaseError(error)
|
||||||
|
} catch (e) {
|
||||||
|
outputError = e
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(outputError.message).toEqual("database does not exist")
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
import { EOL } from "os"
|
||||||
|
|
||||||
|
export const DatabaseErrorCode = {
|
||||||
|
databaseDoesNotExist: "3D000",
|
||||||
|
connectionFailure: "ECONNREFUSED",
|
||||||
|
wrongCredentials: "28000",
|
||||||
|
notFound: "ENOTFOUND",
|
||||||
|
migrationMissing: "42P01",
|
||||||
|
}
|
||||||
|
|
||||||
|
export function handlePostgresDatabaseError(err: any): never {
|
||||||
|
if (DatabaseErrorCode.databaseDoesNotExist === err.code) {
|
||||||
|
throw new Error(
|
||||||
|
`The specified PostgreSQL database does not exist. Please create it and try again.${EOL}${err.message}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DatabaseErrorCode.connectionFailure === err.code) {
|
||||||
|
throw new Error(
|
||||||
|
`Failed to establish a connection to PostgreSQL. Please ensure the following is true and try again:
|
||||||
|
- You have a PostgreSQL database running
|
||||||
|
- You have passed the correct credentials in medusa-config.js
|
||||||
|
- You have formatted the database connection string correctly. See below:
|
||||||
|
"postgres://[username]:[password]@[host]:[post]/[db_name]" - If there is no password, you can omit it from the connection string
|
||||||
|
${EOL}
|
||||||
|
${err.message}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DatabaseErrorCode.wrongCredentials === err.code) {
|
||||||
|
throw new Error(
|
||||||
|
`The specified credentials does not exists for the specified PostgreSQL database.${EOL}${err.message}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DatabaseErrorCode.notFound === err.code) {
|
||||||
|
throw new Error(
|
||||||
|
`The specified connection string for your PostgreSQL database might have illegal characters. Please check that it only contains allowed characters [a-zA-Z0-9]${EOL}${err.message}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DatabaseErrorCode.migrationMissing === err.code) {
|
||||||
|
throw new Error(
|
||||||
|
`Migrations missing. Please run 'medusa migrations run' and try again.`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
throw err
|
||||||
|
}
|
||||||
@@ -11,3 +11,4 @@ export * from "./medusa-container"
|
|||||||
export * from "./set-metadata"
|
export * from "./set-metadata"
|
||||||
export * from "./wrap-handler"
|
export * from "./wrap-handler"
|
||||||
export * from "./build-query"
|
export * from "./build-query"
|
||||||
|
export * from "./handle-postgres-database-error"
|
||||||
|
|||||||
Reference in New Issue
Block a user