Feat(medusa): config error handling in loaders (#2514)
**What** - add error handling when loading project config **How** - Add error parameter to get-medusa-config result if an error was thrown (previously we returned an empty config) - Discussion: A different, but equally valid approach could be just throwing the error rather than creating an error parameter. This causes a more ugly output without warnings and changes the api a bit but it would force error handling. wdyt? **Why** - cli would fail with database error `databaseMissingDriverError` if config was invalid, ex. missing a comma ### example (missing `,` in config) **old output** ``` Successfully compiled 2 files with Babel (143ms). [medusa-config] ⚠️ redis_url not found. A fake redis instance will be used. [medusa-config] ⚠️ database_type not found. fallback to default sqlite. info: Using flag MEDUSA_FF_ORDER_EDITING from environment with value true info: Using flag MEDUSA_FF_SALES_CHANNELS from environment with value true info: Using flag MEDUSA_FF_TAX_INCLUSIVE_PRICING from environment with value true info: Using fake Redis ✔ Models initialized – 13ms ✔ Plugin models initialized – 0ms ✔ Repositories initialized – 17ms ⠋ Initializing databaseMissingDriverError: Wrong driver: "undefined" given. Supported drivers are: "aurora-data-api", "aurora-data-api-pg", "better-sqlite3", "capacitor", "cockroachdb", "cordova", "expo", "mariadb", "mongodb", "mssql", "mysql", "nativescript", "oracle", "postgres", "react-native", "sap", "sqlite", "sqljs". ``` **new output** ``` Successfully compiled 2 files with Babel (185ms). error: Error in loading config: Unexpected identifier error: /Users/phko/projects/community/my-medusa-store/medusa-config.js:129 plugins, ^^^^^^^ SyntaxError: Unexpected identifier at compileFunction (<anonymous>) at Object.compileFunction (node:vm:352:18) at wrapSafe (node:internal/modules/cjs/loader:1033:15) at Module._compile (node:internal/modules/cjs/loader:1069:27) at Object.Module._extensions..js (node:internal/modules/cjs/loader:1159:10) at Module.load (node:internal/modules/cjs/loader:981:32) at Function.Module._load (node:internal/modules/cjs/loader:822:12) at Module.require (node:internal/modules/cjs/loader:1005:19) at require (node:internal/modules/cjs/helpers:102:18) at getConfigFile (/Users/phko/projects/community/my-medusa-store/node_modules/medusa-core-utils/dist/get-config-file.js:26:20) ```
This commit is contained in:
1 parent
0b0d50b476
commit
ea3d738823
10 files changed
+71
-39
No files matched your search
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
"medusa-core-utils": patch
|
||||||
|
"@medusajs/medusa": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Feat(medusa): invalid medusa-config handling in loaders
|
||||||
@@ -306,7 +306,6 @@ describe("/admin/batch-jobs", () => {
|
|||||||
await api
|
await api
|
||||||
.post(`/admin/batch-jobs/${jobId}/cancel`, {}, adminReqConfig)
|
.post(`/admin/batch-jobs/${jobId}/cancel`, {}, adminReqConfig)
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.log(err)
|
|
||||||
expect(err.response.status).toEqual(400)
|
expect(err.response.status).toEqual(400)
|
||||||
expect(err.response.data.type).toEqual("not_allowed")
|
expect(err.response.data.type).toEqual("not_allowed")
|
||||||
expect(err.response.data.message).toEqual(
|
expect(err.response.data.message).toEqual(
|
||||||
|
|||||||
@@ -4,17 +4,20 @@ import path from "path"
|
|||||||
* Attempts to resolve the config file in a given root directory.
|
* Attempts to resolve the config file in a given root directory.
|
||||||
* @param {string} rootDir - the directory to find the config file in.
|
* @param {string} rootDir - the directory to find the config file in.
|
||||||
* @param {string} configName - the name of the config file.
|
* @param {string} configName - the name of the config file.
|
||||||
* @return {object} an object containing the config module and its path.
|
* @return {object} an object containing the config module and its path as well as an error property if the config couldn't be loaded.
|
||||||
*/
|
*/
|
||||||
function getConfigFile(rootDir, configName) {
|
function getConfigFile(rootDir, configName) {
|
||||||
const configPath = path.join(rootDir, configName)
|
const configPath = path.join(rootDir, configName)
|
||||||
let configFilePath = ``
|
let configFilePath = ``
|
||||||
let configModule
|
let configModule
|
||||||
|
|
||||||
try {
|
try {
|
||||||
configFilePath = require.resolve(configPath)
|
configFilePath = require.resolve(configPath)
|
||||||
configModule = require(configFilePath)
|
configModule = require(configFilePath)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return {}
|
return {
|
||||||
|
error: err,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return { configModule, configFilePath }
|
return { configModule, configFilePath }
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { createConnection } from "typeorm"
|
import { createConnection } from "typeorm"
|
||||||
import { getConfigFile } from "medusa-core-utils"
|
import { getConfigFile } from "medusa-core-utils"
|
||||||
import featureFlagLoader from "../loaders/feature-flags"
|
import featureFlagLoader from "../loaders/feature-flags"
|
||||||
|
import { handleConfigError } from "../loaders/config"
|
||||||
import Logger from "../loaders/logger"
|
import Logger from "../loaders/logger"
|
||||||
|
|
||||||
import getMigrations from "./utils/get-migrations"
|
import getMigrations from "./utils/get-migrations"
|
||||||
@@ -11,7 +12,11 @@ const t = async function ({ directory }) {
|
|||||||
args.shift()
|
args.shift()
|
||||||
args.shift()
|
args.shift()
|
||||||
|
|
||||||
const { configModule } = getConfigFile(directory, `medusa-config`)
|
const { configModule, error } = getConfigFile(directory, `medusa-config`)
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
handleConfigError(error)
|
||||||
|
}
|
||||||
|
|
||||||
const featureFlagRouter = featureFlagLoader(configModule)
|
const featureFlagRouter = featureFlagLoader(configModule)
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { sync as existsSync } from "fs-exists-cached"
|
|||||||
import { getConfigFile } from "medusa-core-utils"
|
import { getConfigFile } from "medusa-core-utils"
|
||||||
import { track } from "medusa-telemetry"
|
import { track } from "medusa-telemetry"
|
||||||
|
|
||||||
|
import { handleConfigError } from "../loaders/config"
|
||||||
import Logger from "../loaders/logger"
|
import Logger from "../loaders/logger"
|
||||||
import loaders from "../loaders"
|
import loaders from "../loaders"
|
||||||
|
|
||||||
@@ -29,7 +30,11 @@ const t = async function ({ directory, migrate, seedFile }) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const { configModule } = getConfigFile(directory, `medusa-config`)
|
const { configModule, error } = getConfigFile(directory, `medusa-config`)
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
handleConfigError(error)
|
||||||
|
}
|
||||||
|
|
||||||
const featureFlagRouter = featureFlagLoader(configModule)
|
const featureFlagRouter = featureFlagLoader(configModule)
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import fs from "fs"
|
|||||||
import { isString } from "lodash"
|
import { isString } from "lodash"
|
||||||
import { sync as existsSync } from "fs-exists-cached"
|
import { sync as existsSync } from "fs-exists-cached"
|
||||||
import { getConfigFile, createRequireFromPath } from "medusa-core-utils"
|
import { getConfigFile, createRequireFromPath } from "medusa-core-utils"
|
||||||
|
import { handleConfigError } from "../../loaders/config"
|
||||||
|
import logger from "../../loaders/logger"
|
||||||
|
|
||||||
function createFileContentHash(path, files) {
|
function createFileContentHash(path, files) {
|
||||||
return path + files
|
return path + files
|
||||||
@@ -88,7 +90,12 @@ function resolvePlugin(pluginName) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default async (directory, featureFlagRouter) => {
|
export default async (directory, featureFlagRouter) => {
|
||||||
const { configModule } = getConfigFile(directory, `medusa-config`)
|
const { configModule, error } = getConfigFile(directory, `medusa-config`)
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
handleConfigError(error)
|
||||||
|
}
|
||||||
|
|
||||||
const { plugins } = configModule
|
const { plugins } = configModule
|
||||||
|
|
||||||
const resolved = plugins.map((plugin) => {
|
const resolved = plugins.map((plugin) => {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { ConfigModule } from "../types/global"
|
import { ConfigModule } from "../types/global"
|
||||||
import { getConfigFile } from "medusa-core-utils/dist"
|
import { getConfigFile } from "medusa-core-utils/dist"
|
||||||
|
import logger from "./logger"
|
||||||
|
|
||||||
const isProduction = ["production", "prod"].includes(process.env.NODE_ENV || "")
|
const isProduction = ["production", "prod"].includes(process.env.NODE_ENV || "")
|
||||||
|
|
||||||
@@ -9,9 +10,25 @@ const errorHandler = isProduction
|
|||||||
}
|
}
|
||||||
: console.log
|
: console.log
|
||||||
|
|
||||||
|
export const handleConfigError = (error: Error): void => {
|
||||||
|
logger.error(`Error in loading config: ${error.message}`)
|
||||||
|
if (error.stack) {
|
||||||
|
logger.error(error.stack)
|
||||||
|
}
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
export default (rootDirectory: string): ConfigModule => {
|
export default (rootDirectory: string): ConfigModule => {
|
||||||
const { configModule } = getConfigFile(rootDirectory, `medusa-config`) as {
|
const { configModule, error } = getConfigFile(
|
||||||
|
rootDirectory,
|
||||||
|
`medusa-config`
|
||||||
|
) as {
|
||||||
configModule: ConfigModule
|
configModule: ConfigModule
|
||||||
|
error: Error | null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
handleConfigError(error)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!configModule?.projectConfig?.redis_url) {
|
if (!configModule?.projectConfig?.redis_url) {
|
||||||
|
|||||||
@@ -115,7 +115,10 @@ export default async ({
|
|||||||
|
|
||||||
const dbActivity = Logger.activity("Initializing database")
|
const dbActivity = Logger.activity("Initializing database")
|
||||||
track("DATABASE_INIT_STARTED")
|
track("DATABASE_INIT_STARTED")
|
||||||
const dbConnection = await databaseLoader({ container, configModule })
|
const dbConnection = await databaseLoader({
|
||||||
|
container,
|
||||||
|
configModule,
|
||||||
|
})
|
||||||
const dbAct = Logger.success(dbActivity, "Database initialized") || {}
|
const dbAct = Logger.success(dbActivity, "Database initialized") || {}
|
||||||
track("DATABASE_INIT_COMPLETED", { duration: dbAct.duration })
|
track("DATABASE_INIT_COMPLETED", { duration: dbAct.duration })
|
||||||
|
|
||||||
|
|||||||
@@ -18,16 +18,12 @@ const pgSqliteGenerationMapping: {
|
|||||||
let dbType: string
|
let dbType: string
|
||||||
export function resolveDbType(pgSqlType: ColumnType): ColumnType {
|
export function resolveDbType(pgSqlType: ColumnType): ColumnType {
|
||||||
if (!dbType) {
|
if (!dbType) {
|
||||||
try {
|
const { configModule } = getConfigFile(
|
||||||
const { configModule } = getConfigFile(
|
path.resolve("."),
|
||||||
path.resolve("."),
|
`medusa-config`
|
||||||
`medusa-config`
|
) as any
|
||||||
) as any
|
|
||||||
dbType = configModule.projectConfig.database_type
|
dbType = configModule?.projectConfig?.database_type || "postgres"
|
||||||
} catch (error) {
|
|
||||||
// Default to Postgres to allow for e.g. migrations to run
|
|
||||||
dbType = "postgres"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dbType === "sqlite" && (pgSqlType as string) in pgSqliteTypeMapping) {
|
if (dbType === "sqlite" && (pgSqlType as string) in pgSqliteTypeMapping) {
|
||||||
@@ -40,16 +36,12 @@ export function resolveDbGenerationStrategy(
|
|||||||
pgSqlType: "increment" | "uuid" | "rowid"
|
pgSqlType: "increment" | "uuid" | "rowid"
|
||||||
): "increment" | "uuid" | "rowid" {
|
): "increment" | "uuid" | "rowid" {
|
||||||
if (!dbType) {
|
if (!dbType) {
|
||||||
try {
|
const { configModule } = getConfigFile(
|
||||||
const { configModule } = getConfigFile(
|
path.resolve("."),
|
||||||
path.resolve("."),
|
`medusa-config`
|
||||||
`medusa-config`
|
) as any
|
||||||
) as any
|
|
||||||
dbType = configModule.projectConfig.database_type
|
dbType = configModule?.projectConfig?.database_type || "postgres"
|
||||||
} catch (error) {
|
|
||||||
// Default to Postgres to allow for e.g. migrations to run
|
|
||||||
dbType = "postgres"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dbType === "sqlite" && pgSqlType in pgSqliteTypeMapping) {
|
if (dbType === "sqlite" && pgSqlType in pgSqliteTypeMapping) {
|
||||||
|
|||||||
@@ -5,17 +5,12 @@ import { getConnection } from "typeorm"
|
|||||||
export async function manualAutoIncrement(
|
export async function manualAutoIncrement(
|
||||||
tableName: string
|
tableName: string
|
||||||
): Promise<number | null> {
|
): Promise<number | null> {
|
||||||
let dbType
|
const { configModule } = getConfigFile(
|
||||||
try {
|
path.resolve("."),
|
||||||
const { configModule } = getConfigFile(
|
`medusa-config`
|
||||||
path.resolve("."),
|
) as any
|
||||||
`medusa-config`
|
|
||||||
) as any
|
const dbType = configModule?.projectConfig?.database_type || "postgres"
|
||||||
dbType = configModule.projectConfig.database_type
|
|
||||||
} catch (error) {
|
|
||||||
// Default to Postgres to allow for e.g. migrations to run
|
|
||||||
dbType = "postgres"
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dbType === "sqlite") {
|
if (dbType === "sqlite") {
|
||||||
const connection = getConnection()
|
const connection = getConnection()
|
||||||
|
|||||||
Reference in new issue
Block a user