feat: custom logger (#13156)

* feat: custom logger

* mock log

* unit test

* FF and jobs loader

* unit test

* add to ResourceLoader

* get from container

* mock

* rm log

* default logger mock

* link loaders, express

* comments

* initialize container as first step

* db conn

* test

* initialize start

* plugin build using default logger

* ignore .medusa

* revert ignroe

---------

Co-authored-by: Oli Juhl <59018053+olivermrbl@users.noreply.github.com>
This commit is contained in:
Carlos R. L. RodriguesandOli Juhl authored and GitHub committed 2025-08-28 15:31:19 +02:00
1 parent 9412669e65
commit e2213448ac
42 files changed
+471 -210

No files matched your search

+9
View File
@@ -0,0 +1,9 @@
---
"@medusajs/test-utils": patch
"@medusajs/framework": patch
"@medusajs/types": patch
"@medusajs/utils": patch
"@medusajs/medusa": patch
---
feat: custom logger on medusa-config
+12 -11
View File
@@ -1,6 +1,6 @@
import { ConfigModule } from "./types"
import { deepCopy, isDefined } from "@medusajs/utils" import { deepCopy, isDefined } from "@medusajs/utils"
import { logger } from "../logger" import { logger } from "../logger"
import { ConfigModule } from "./types"
export class ConfigManager { export class ConfigManager {
/** /**
@@ -124,21 +124,23 @@ export class ConfigManager {
/** /**
* Normalizes the project config object and assign the defaults if needed * Normalizes the project config object and assign the defaults if needed
* @param projectConfig * @param config
* @protected * @protected
*/ */
protected normalizeProjectConfig( protected normalizeProjectConfig(
projectConfig: Partial<ConfigModule["projectConfig"]> config: Partial<ConfigModule>
): ConfigModule["projectConfig"] { ): ConfigModule["projectConfig"] {
const outputConfig = deepCopy( const projConfig = config?.projectConfig ?? {}
projectConfig const outputConfig = deepCopy(projConfig) as ConfigModule["projectConfig"]
) as ConfigModule["projectConfig"]
if (!outputConfig?.redisUrl) { if (!outputConfig?.redisUrl) {
console.log(`redisUrl not found. A fake redis instance will be used.`) const customLogger = config?.logger ?? logger
customLogger.log(
`redisUrl not found. A fake redis instance will be used.`
)
} }
outputConfig.http = this.buildHttpConfig(projectConfig) outputConfig.http = this.buildHttpConfig(projConfig)
let workerMode = outputConfig?.workerMode! let workerMode = outputConfig?.workerMode!
@@ -172,9 +174,7 @@ export class ConfigManager {
}): ConfigModule { }): ConfigModule {
this.#baseDir = baseDir this.#baseDir = baseDir
const normalizedProjectConfig = this.normalizeProjectConfig( const normalizedProjectConfig = this.normalizeProjectConfig(projectConfig)
projectConfig.projectConfig ?? {}
)
this.#config = { this.#config = {
projectConfig: normalizedProjectConfig, projectConfig: normalizedProjectConfig,
@@ -184,6 +184,7 @@ export class ConfigManager {
modules: projectConfig.modules ?? {}, modules: projectConfig.modules ?? {},
featureFlags: projectConfig.featureFlags ?? {}, featureFlags: projectConfig.featureFlags ?? {},
plugins: projectConfig.plugins ?? [], plugins: projectConfig.plugins ?? [],
logger: projectConfig.logger ?? logger,
} }
return this.#config return this.#config
+7 -7
View File
@@ -1,14 +1,14 @@
import { ConfigModule } from "./types"
import { ContainerRegistrationKeys, getConfigFile } from "@medusajs/utils" import { ContainerRegistrationKeys, getConfigFile } from "@medusajs/utils"
import { logger } from "../logger"
import { ConfigManager } from "./config"
import { container } from "../container"
import { asFunction } from "awilix" import { asFunction } from "awilix"
import { container } from "../container"
import { logger as defaultLogger } from "../logger"
import { ConfigManager } from "./config"
import { ConfigModule } from "./types"
const handleConfigError = (error: Error): void => { const handleConfigError = (error: Error): void => {
logger.error(`Error in loading config: ${error.message}`) defaultLogger.error(`Error in loading config: ${error.message}`)
if (error.stack) { if (error.stack) {
logger.error(error.stack) defaultLogger.error(error.stack)
} }
process.exit(1) process.exit(1)
} }
@@ -28,7 +28,7 @@ container.register(
*/ */
export async function configLoader( export async function configLoader(
entryDirectory: string, entryDirectory: string,
configFileName: string configFileName: string = "medusa-config"
): Promise<ConfigModule> { ): Promise<ConfigModule> {
const config = await getConfigFile<ConfigModule>( const config = await getConfigFile<ConfigModule>(
entryDirectory, entryDirectory,
@@ -10,7 +10,6 @@ import { asFunction } from "awilix"
import { normalize } from "path" import { normalize } from "path"
import { configManager } from "../config" import { configManager } from "../config"
import { container } from "../container" import { container } from "../container"
import { logger } from "../logger"
import { FlagSettings } from "./types" import { FlagSettings } from "./types"
container.register( container.register(
@@ -25,7 +24,7 @@ container.register(
export async function featureFlagsLoader( export async function featureFlagsLoader(
sourcePath?: string sourcePath?: string
): Promise<FlagRouter> { ): Promise<FlagRouter> {
const { featureFlags: projectConfigFlags = {} } = configManager.config const { featureFlags: projectConfigFlags = {}, logger } = configManager.config
if (!sourcePath) { if (!sourcePath) {
return FeatureFlag return FeatureFlag
@@ -3,17 +3,16 @@ import {
ModulesDefinition, ModulesDefinition,
registerMedusaModule, registerMedusaModule,
} from "@medusajs/modules-sdk" } from "@medusajs/modules-sdk"
import { MedusaContainer } from "@medusajs/types"
import { ContainerRegistrationKeys, generateJwtToken } from "@medusajs/utils" import { ContainerRegistrationKeys, generateJwtToken } from "@medusajs/utils"
import { asValue } from "awilix" import { asValue } from "awilix"
import express from "express" import express from "express"
import querystring from "querystring" import querystring from "querystring"
import supertest from "supertest" import supertest from "supertest"
import { MedusaContainer } from "@medusajs/types"
import { configManager } from "../../../config" import { configManager } from "../../../config"
import { container } from "../../../container" import { container } from "../../../container"
import { featureFlagsLoader } from "../../../feature-flags" import { featureFlagsLoader } from "../../../feature-flags"
import { logger } from "../../../logger" import { logger as defaultLogger } from "../../../logger"
import { ApiLoader } from "../../router" import { ApiLoader } from "../../router"
import { MedusaRequest } from "../../types" import { MedusaRequest } from "../../types"
import { config } from "../mocks" import { config } from "../mocks"
@@ -66,11 +65,8 @@ export const createServer = async (rootDir) => {
container.register(ContainerRegistrationKeys.PG_CONNECTION, asValue({})) container.register(ContainerRegistrationKeys.PG_CONNECTION, asValue({}))
container.register("configModule", asValue(config)) container.register("configModule", asValue(config))
container.register(ContainerRegistrationKeys.LOGGER, asValue(defaultLogger))
container.register({ container.register({
logger: asValue({
error: () => {},
info: () => {},
}),
manager: asValue({}), manager: asValue({}),
}) })
@@ -88,7 +84,7 @@ export const createServer = async (rootDir) => {
}) })
await featureFlagsLoader() await featureFlagsLoader()
await moduleLoader({ container, moduleResolutions, logger }) await moduleLoader({ container, moduleResolutions, logger: defaultLogger })
app.use((req, res, next) => { app.use((req, res, next) => {
;(req as MedusaRequest).scope = container.createScope() as MedusaContainer ;(req as MedusaRequest).scope = container.createScope() as MedusaContainer
@@ -98,6 +94,7 @@ export const createServer = async (rootDir) => {
await new ApiLoader({ await new ApiLoader({
app, app,
sourceDir: rootDir, sourceDir: rootDir,
container,
}).load() }).load()
const superRequest = supertest(app) const superRequest = supertest(app)
@@ -1,5 +1,11 @@
import {
ContainerRegistrationKeys,
createMedusaContainer,
} from "@medusajs/utils"
import { asValue } from "awilix"
import express from "express" import express from "express"
import { resolve } from "path" import { resolve } from "path"
import { logger as defaultLogger } from "../../logger"
import { import {
customersCreateMiddlewareMock, customersCreateMiddlewareMock,
customersCreateMiddlewareValidatorMock, customersCreateMiddlewareValidatorMock,
@@ -7,7 +13,7 @@ import {
storeGlobalMiddlewareMock, storeGlobalMiddlewareMock,
} from "../__fixtures__/mocks" } from "../__fixtures__/mocks"
import { createServer } from "../__fixtures__/server" import { createServer } from "../__fixtures__/server"
import { MedusaNextFunction, ApiLoader } from "../index" import { ApiLoader, MedusaNextFunction } from "../index"
jest.setTimeout(30000) jest.setTimeout(30000)
@@ -335,9 +341,16 @@ describe("RoutesLoader", function () {
__dirname, __dirname,
"../__fixtures__/routers-duplicate-parameter" "../__fixtures__/routers-duplicate-parameter"
) )
const container = createMedusaContainer()
container.register(
ContainerRegistrationKeys.LOGGER,
asValue(defaultLogger)
)
const err = await new ApiLoader({ const err = await new ApiLoader({
app, app,
sourceDir: rootDir, sourceDir: rootDir,
container,
}) })
.load() .load()
.catch((e) => e) .catch((e) => e)
@@ -1,3 +1,5 @@
import { MedusaContainer } from "@medusajs/framework/types"
import { ContainerRegistrationKeys } from "@medusajs/framework/utils"
import { dynamicImport } from "@medusajs/utils" import { dynamicImport } from "@medusajs/utils"
import createStore from "connect-redis" import createStore from "connect-redis"
import cookieParser from "cookie-parser" import cookieParser from "cookie-parser"
@@ -7,14 +9,19 @@ import Redis from "ioredis"
import morgan from "morgan" import morgan from "morgan"
import path from "path" import path from "path"
import { configManager } from "../config" import { configManager } from "../config"
import { logger } from "../logger"
import { MedusaRequest, MedusaResponse } from "./types" import { MedusaRequest, MedusaResponse } from "./types"
const NOISY_ENDPOINTS_CHUNKS = ["@fs", "@id", "@vite", "@react", "node_modules"] const NOISY_ENDPOINTS_CHUNKS = ["@fs", "@id", "@vite", "@react", "node_modules"]
const isHealthCheck = (req: MedusaRequest) => req.path === "/health" const isHealthCheck = (req: MedusaRequest) => req.path === "/health"
export async function expressLoader({ app }: { app: Express }): Promise<{ export async function expressLoader({
app,
container,
}: {
app: Express
container: MedusaContainer
}): Promise<{
app: Express app: Express
shutdown: () => Promise<void> shutdown: () => Promise<void>
}> { }> {
@@ -25,6 +32,7 @@ export async function expressLoader({ app }: { app: Express }): Promise<{
const IS_DEV = NODE_ENV.startsWith("dev") const IS_DEV = NODE_ENV.startsWith("dev")
const isStaging = NODE_ENV === "staging" const isStaging = NODE_ENV === "staging"
const isTest = NODE_ENV === "test" const isTest = NODE_ENV === "test"
const logger = container.resolve(ContainerRegistrationKeys.LOGGER)
let sameSite: string | boolean = false let sameSite: string | boolean = false
let secure = false let secure = false
+33 -21
View File
@@ -1,31 +1,31 @@
import logger from "@medusajs/cli/dist/reporter" import { ContainerRegistrationKeys, parseCorsOrigins } from "@medusajs/utils"
import cors, { CorsOptions } from "cors" import cors, { CorsOptions } from "cors"
import { parseCorsOrigins } from "@medusajs/utils" import type { ErrorRequestHandler, Express, RequestHandler } from "express"
import type { Express, RequestHandler, ErrorRequestHandler } from "express"
import type { import type {
AdditionalDataValidatorRoute,
BodyParserConfigRoute,
MedusaNextFunction,
MedusaRequest, MedusaRequest,
MedusaResponse, MedusaResponse,
MiddlewareDescriptor,
MiddlewareFunction,
MiddlewareVerb, MiddlewareVerb,
RouteDescriptor, RouteDescriptor,
MiddlewareFunction,
MedusaNextFunction,
MiddlewareDescriptor,
BodyParserConfigRoute,
RouteHandler, RouteHandler,
AdditionalDataValidatorRoute,
} from "./types" } from "./types"
import { RoutesLoader } from "./routes-loader" import { Logger, MedusaContainer } from "@medusajs/types"
import { RoutesFinder } from "./routes-finder" import { configManager } from "../config"
import { RoutesSorter } from "./routes-sorter"
import { wrapHandler } from "./utils/wrap-handler"
import { authenticate, AuthType } from "./middlewares"
import { errorHandler } from "./middlewares/error-handler"
import { RestrictedFields } from "./utils/restricted-fields"
import { MiddlewareFileLoader } from "./middleware-file-loader" import { MiddlewareFileLoader } from "./middleware-file-loader"
import { authenticate, AuthType } from "./middlewares"
import { createBodyParserMiddlewaresStack } from "./middlewares/bodyparser" import { createBodyParserMiddlewaresStack } from "./middlewares/bodyparser"
import { ensurePublishableApiKeyMiddleware } from "./middlewares/ensure-publishable-api-key" import { ensurePublishableApiKeyMiddleware } from "./middlewares/ensure-publishable-api-key"
import { configManager } from "../config" import { errorHandler } from "./middlewares/error-handler"
import { RoutesFinder } from "./routes-finder"
import { RoutesLoader } from "./routes-loader"
import { RoutesSorter } from "./routes-sorter"
import { RestrictedFields } from "./utils/restricted-fields"
import { wrapHandler } from "./utils/wrap-handler"
export class ApiLoader { export class ApiLoader {
/** /**
@@ -58,18 +58,23 @@ export class ApiLoader {
*/ */
readonly #sourceDirs: string[] readonly #sourceDirs: string[]
readonly #logger: Logger
constructor({ constructor({
app, app,
sourceDir, sourceDir,
baseRestrictedFields = [], baseRestrictedFields = [],
container,
}: { }: {
app: Express app: Express
sourceDir: string | string[] sourceDir: string | string[]
baseRestrictedFields?: string[] baseRestrictedFields?: string[]
container: MedusaContainer
}) { }) {
this.#app = app this.#app = app
this.#sourceDirs = Array.isArray(sourceDir) ? sourceDir : [sourceDir] this.#sourceDirs = Array.isArray(sourceDir) ? sourceDir : [sourceDir]
this.#assignRestrictedFields(baseRestrictedFields ?? []) this.#assignRestrictedFields(baseRestrictedFields ?? [])
this.#logger = container.resolve(ContainerRegistrationKeys.LOGGER)
} }
/** /**
@@ -105,7 +110,7 @@ export class ApiLoader {
route: MiddlewareDescriptor | RouteDescriptor | RouteDescriptor route: MiddlewareDescriptor | RouteDescriptor | RouteDescriptor
) { ) {
if ("isRoute" in route) { if ("isRoute" in route) {
logger.debug(`registering route ${route.method} ${route.matcher}`) this.#logger.debug(`registering route ${route.method} ${route.matcher}`)
const handler = ApiLoader.traceRoute const handler = ApiLoader.traceRoute
? ApiLoader.traceRoute(route.handler, { ? ApiLoader.traceRoute(route.handler, {
route: route.matcher, route: route.matcher,
@@ -118,7 +123,7 @@ export class ApiLoader {
} }
if (!route.methods) { if (!route.methods) {
logger.debug(`registering global middleware for ${route.matcher}`) this.#logger.debug(`registering global middleware for ${route.matcher}`)
const handler = ApiLoader.traceMiddleware const handler = ApiLoader.traceMiddleware
? (ApiLoader.traceMiddleware(route.handler, { ? (ApiLoader.traceMiddleware(route.handler, {
route: route.matcher, route: route.matcher,
@@ -133,7 +138,9 @@ export class ApiLoader {
? route.methods ? route.methods
: [route.methods] : [route.methods]
methods.forEach((method) => { methods.forEach((method) => {
logger.debug(`registering route middleware ${method} ${route.matcher}`) this.#logger.debug(
`registering route middleware ${method} ${route.matcher}`
)
const handler = ApiLoader.traceMiddleware const handler = ApiLoader.traceMiddleware
? (ApiLoader.traceMiddleware(wrapHandler(route.handler), { ? (ApiLoader.traceMiddleware(wrapHandler(route.handler), {
route: route.matcher, route: route.matcher,
@@ -192,6 +199,7 @@ export class ApiLoader {
| "shouldAppendStoreCors", | "shouldAppendStoreCors",
corsOptions: CorsOptions corsOptions: CorsOptions
) { ) {
const logger = this.#logger
const corsFn = cors(corsOptions) const corsFn = cors(corsOptions)
const corsMiddleware: RequestHandler = function corsMiddleware( const corsMiddleware: RequestHandler = function corsMiddleware(
req, req,
@@ -234,6 +242,7 @@ export class ApiLoader {
authType: AuthType | AuthType[], authType: AuthType | AuthType[],
options?: { allowUnauthenticated?: boolean; allowUnregistered?: boolean } options?: { allowUnauthenticated?: boolean; allowUnregistered?: boolean }
) { ) {
const logger = this.#logger
logger.debug(`Registering auth middleware for prefix ${namespace}`) logger.debug(`Registering auth middleware for prefix ${namespace}`)
const originalFn = authenticate(actorType, authType, options) const originalFn = authenticate(actorType, authType, options)
@@ -273,7 +282,9 @@ export class ApiLoader {
namespace: string, namespace: string,
routesFinder: RoutesFinder<BodyParserConfigRoute> routesFinder: RoutesFinder<BodyParserConfigRoute>
): void { ): void {
logger.debug(`Registering bodyparser middleware for prefix ${namespace}`) this.#logger.debug(
`Registering bodyparser middleware for prefix ${namespace}`
)
this.#app.use( this.#app.use(
namespace, namespace,
createBodyParserMiddlewaresStack( createBodyParserMiddlewaresStack(
@@ -292,6 +303,7 @@ export class ApiLoader {
namespace: string, namespace: string,
routesFinder: RoutesFinder<AdditionalDataValidatorRoute> routesFinder: RoutesFinder<AdditionalDataValidatorRoute>
) { ) {
const logger = this.#logger
logger.debug( logger.debug(
`Registering assignAdditionalDataValidator middleware for prefix ${namespace}` `Registering assignAdditionalDataValidator middleware for prefix ${namespace}`
) )
@@ -329,7 +341,7 @@ export class ApiLoader {
* a `x-publishable-key` header * a `x-publishable-key` header
*/ */
#applyStorePublishableKeyMiddleware(namespace: string) { #applyStorePublishableKeyMiddleware(namespace: string) {
logger.debug( this.#logger.debug(
`Registering publishable key middleware for namespace ${namespace}` `Registering publishable key middleware for namespace ${namespace}`
) )
let middleware = ApiLoader.traceMiddleware let middleware = ApiLoader.traceMiddleware
@@ -1,5 +1,11 @@
import { join } from "path"
import { WorkflowManager, WorkflowScheduler } from "@medusajs/orchestration" import { WorkflowManager, WorkflowScheduler } from "@medusajs/orchestration"
import {
ContainerRegistrationKeys,
createMedusaContainer,
} from "@medusajs/utils"
import { asValue } from "awilix"
import { join } from "path"
import { logger } from "../../logger"
import { MockSchedulerStorage } from "../__fixtures__/mock-scheduler-storage" import { MockSchedulerStorage } from "../__fixtures__/mock-scheduler-storage"
import { JobLoader } from "../job-loader" import { JobLoader } from "../job-loader"
@@ -11,8 +17,12 @@ describe("register jobs", () => {
}) })
it("should registers jobs from plugins", async () => { it("should registers jobs from plugins", async () => {
const container = createMedusaContainer()
container.register(ContainerRegistrationKeys.LOGGER, asValue(logger))
const jobLoader: JobLoader = new JobLoader( const jobLoader: JobLoader = new JobLoader(
join(__dirname, "../__fixtures__/plugin/jobs") join(__dirname, "../__fixtures__/plugin/jobs"),
container
) )
await jobLoader.load() await jobLoader.load()
const workflow = WorkflowManager.getWorkflow("job-summarize-orders") const workflow = WorkflowManager.getWorkflow("job-summarize-orders")
@@ -24,8 +34,12 @@ describe("register jobs", () => {
}) })
it("should not load non js/ts files", async () => { it("should not load non js/ts files", async () => {
const container = createMedusaContainer()
container.register(ContainerRegistrationKeys.LOGGER, asValue(logger))
const jobLoader: JobLoader = new JobLoader( const jobLoader: JobLoader = new JobLoader(
join(__dirname, "../__fixtures__/plugin/jobs-with-other-files") join(__dirname, "../__fixtures__/plugin/jobs-with-other-files"),
container
) )
await jobLoader.load() await jobLoader.load()
const workflow = WorkflowManager.getWorkflow("job-summarize-orders") const workflow = WorkflowManager.getWorkflow("job-summarize-orders")
@@ -6,7 +6,6 @@ import {
createWorkflow, createWorkflow,
StepResponse, StepResponse,
} from "@medusajs/workflows-sdk" } from "@medusajs/workflows-sdk"
import { logger } from "../logger"
import { ResourceLoader } from "../utils/resource-loader" import { ResourceLoader } from "../utils/resource-loader"
type CronJobConfig = { type CronJobConfig = {
@@ -20,8 +19,8 @@ type CronJobHandler = (container: MedusaContainer) => Promise<any>
export class JobLoader extends ResourceLoader { export class JobLoader extends ResourceLoader {
protected resourceName = "job" protected resourceName = "job"
constructor(sourceDir: string | string[]) { constructor(sourceDir: string | string[], container: MedusaContainer) {
super(sourceDir) super(sourceDir, container)
} }
protected async onFileLoaded( protected async onFileLoaded(
@@ -36,7 +35,7 @@ export class JobLoader extends ResourceLoader {
} }
this.validateConfig(fileExports.config) this.validateConfig(fileExports.config)
logger.debug(`Registering job from ${path}.`) this.logger.debug(`Registering job from ${path}.`)
this.register({ this.register({
config: fileExports.config, config: fileExports.config,
handler: fileExports.default, handler: fileExports.default,
@@ -96,7 +95,7 @@ export class JobLoader extends ResourceLoader {
const res = await handler(container) const res = await handler(container)
return new StepResponse(res, res) return new StepResponse(res, res)
} catch (error) { } catch (error) {
logger.error( this.logger.error(
`Scheduled job ${config.name} failed with error: ${error.message}` `Scheduled job ${config.name} failed with error: ${error.message}`
) )
throw error throw error
@@ -125,6 +124,6 @@ export class JobLoader extends ResourceLoader {
async load() { async load() {
await super.discoverResources() await super.discoverResources()
logger.debug(`Jobs registered.`) this.logger.debug(`Jobs registered.`)
} }
} }
@@ -1,8 +1,9 @@
import { Logger } from "@medusajs/types"
import { dynamicImport, promiseAll, readDirRecursive } from "@medusajs/utils" import { dynamicImport, promiseAll, readDirRecursive } from "@medusajs/utils"
import { Dirent } from "fs" import { Dirent } from "fs"
import { access } from "fs/promises" import { access } from "fs/promises"
import { join } from "path" import { join } from "path"
import { logger } from "../logger" import { logger as defaultLogger } from "../logger"
export class LinkLoader { export class LinkLoader {
/** /**
@@ -23,8 +24,11 @@ export class LinkLoader {
/^_[^/\\]*(\.[^/\\]+)?$/, /^_[^/\\]*(\.[^/\\]+)?$/,
] ]
constructor(sourceDir: string | string[]) { #logger: Logger
constructor(sourceDir: string | string[], logger?: Logger) {
this.#sourceDir = sourceDir this.#sourceDir = sourceDir
this.#logger = logger ?? defaultLogger
} }
/** /**
@@ -40,7 +44,7 @@ export class LinkLoader {
try { try {
await access(sourcePath) await access(sourcePath)
} catch { } catch {
logger.info(`No link to load from ${sourcePath}. skipped.`) this.#logger.info(`No link to load from ${sourcePath}. skipped.`)
return return
} }
@@ -52,7 +56,7 @@ export class LinkLoader {
) )
}) })
logger.debug(`Registering links from ${sourcePath}.`) this.#logger.debug(`Registering links from ${sourcePath}.`)
return await promiseAll( return await promiseAll(
fileEntries.map(async (entry: Dirent) => { fileEntries.map(async (entry: Dirent) => {
@@ -65,6 +69,6 @@ export class LinkLoader {
await promiseAll(promises) await promiseAll(promises)
logger.debug(`Links registered.`) this.#logger.debug(`Links registered.`)
} }
} }
@@ -1,7 +1,8 @@
import { Modules } from "@medusajs/utils" import { ContainerRegistrationKeys, Modules } from "@medusajs/utils"
import { asValue } from "awilix" import { asValue } from "awilix"
import { join } from "path" import { join } from "path"
import { container } from "../../container" import { container } from "../../container"
import { logger } from "../../logger"
import { eventBusServiceMock } from "../__mocks__" import { eventBusServiceMock } from "../__mocks__"
import { SubscriberLoader } from "../subscriber-loader" import { SubscriberLoader } from "../subscriber-loader"
@@ -18,8 +19,13 @@ describe("SubscriberLoader", () => {
beforeAll(async () => { beforeAll(async () => {
container.register(Modules.EVENT_BUS, asValue(eventBusServiceMock)) container.register(Modules.EVENT_BUS, asValue(eventBusServiceMock))
container.register(ContainerRegistrationKeys.LOGGER, asValue(logger))
const paths = await new SubscriberLoader(rootDir, pluginOptions).load() const paths = await new SubscriberLoader(
rootDir,
pluginOptions,
container
).load()
if (paths) { if (paths) {
registeredPaths = [...registeredPaths, ...paths] registeredPaths = [...registeredPaths, ...paths]
@@ -1,10 +1,13 @@
import { Event, IEventBusModuleService, Subscriber } from "@medusajs/types" import {
Event,
IEventBusModuleService,
MedusaContainer,
Subscriber,
} from "@medusajs/types"
import { isFileSkipped, kebabCase, Modules } from "@medusajs/utils" import { isFileSkipped, kebabCase, Modules } from "@medusajs/utils"
import { parse } from "path" import { parse } from "path"
import { configManager } from "../config" import { configManager } from "../config"
import { container } from "../container" import { container } from "../container"
import { logger } from "../logger"
import { ResourceLoader } from "../utils/resource-loader" import { ResourceLoader } from "../utils/resource-loader"
import { SubscriberArgs, SubscriberConfig } from "./types" import { SubscriberArgs, SubscriberConfig } from "./types"
@@ -32,9 +35,10 @@ export class SubscriberLoader extends ResourceLoader {
constructor( constructor(
sourceDir: string | string[], sourceDir: string | string[],
options: Record<string, unknown> = {} options: Record<string, unknown> = {},
container: MedusaContainer
) { ) {
super(sourceDir) super(sourceDir, container)
this.#pluginOptions = options this.#pluginOptions = options
} }
@@ -48,7 +52,7 @@ export class SubscriberLoader extends ResourceLoader {
const isValid = this.validateSubscriber(fileExports, path) const isValid = this.validateSubscriber(fileExports, path)
logger.debug(`Registering subscribers from ${path}.`) this.logger.debug(`Registering subscribers from ${path}.`)
if (!isValid) { if (!isValid) {
return return
@@ -73,7 +77,7 @@ export class SubscriberLoader extends ResourceLoader {
/** /**
* If the handler is not a function, we can't use it * If the handler is not a function, we can't use it
*/ */
logger.warn(`The subscriber in ${path} is not a function. skipped.`) this.logger.warn(`The subscriber in ${path} is not a function. skipped.`)
return false return false
} }
@@ -83,7 +87,9 @@ export class SubscriberLoader extends ResourceLoader {
/** /**
* If the subscriber is missing a config, we can't use it * If the subscriber is missing a config, we can't use it
*/ */
logger.warn(`The subscriber in ${path} is missing a config. skipped.`) this.logger.warn(
`The subscriber in ${path} is missing a config. skipped.`
)
return false return false
} }
@@ -97,7 +103,7 @@ export class SubscriberLoader extends ResourceLoader {
`The subscriber in ${path} is missing an event in the config.` `The subscriber in ${path} is missing an event in the config.`
) )
} else { } else {
logger.warn( this.logger.warn(
`The subscriber in ${path} is missing an event in the config. skipped.` `The subscriber in ${path} is missing an event in the config. skipped.`
) )
} }
@@ -111,7 +117,7 @@ export class SubscriberLoader extends ResourceLoader {
/** /**
* If the subscribers event is not a string or an array of strings, we can't use it * If the subscribers event is not a string or an array of strings, we can't use it
*/ */
logger.warn( this.logger.warn(
`The subscriber in ${path} has an invalid event config. The event must be a string or an array of strings. skipped.` `The subscriber in ${path} has an invalid event config. The event must be a string or an array of strings. skipped.`
) )
return false return false
@@ -197,7 +203,7 @@ export class SubscriberLoader extends ResourceLoader {
}) })
} }
logger.debug(`Subscribers registered.`) this.logger.debug(`Subscribers registered.`)
/** /**
* Return the file paths of the registered subscribers, to prevent the * Return the file paths of the registered subscribers, to prevent the
@@ -1,8 +1,13 @@
import { dynamicImport, promiseAll, readDirRecursive } from "@medusajs/utils" import { Logger, MedusaContainer } from "@medusajs/types"
import {
ContainerRegistrationKeys,
dynamicImport,
promiseAll,
readDirRecursive,
} from "@medusajs/utils"
import { Dirent } from "fs" import { Dirent } from "fs"
import { access } from "fs/promises" import { access } from "fs/promises"
import { join, parse } from "path" import { join, parse } from "path"
import { logger } from "../logger"
export abstract class ResourceLoader { export abstract class ResourceLoader {
/** /**
@@ -22,8 +27,11 @@ export abstract class ResourceLoader {
*/ */
#excludes: RegExp[] = [/^_[^/\\]*(\.[^/\\]+)?$/] #excludes: RegExp[] = [/^_[^/\\]*(\.[^/\\]+)?$/]
constructor(sourceDir: string | string[]) { protected logger: Logger
constructor(sourceDir: string | string[], container: MedusaContainer) {
this.#sourceDir = sourceDir this.#sourceDir = sourceDir
this.logger = container.resolve(ContainerRegistrationKeys.LOGGER)
} }
/** /**
@@ -61,7 +69,7 @@ export abstract class ResourceLoader {
try { try {
await access(sourcePath) await access(sourcePath)
} catch { } catch {
logger.info( this.logger.info(
`No ${this.resourceName} to load from ${sourcePath}. skipped.` `No ${this.resourceName} to load from ${sourcePath}. skipped.`
) )
return return
@@ -1,14 +1,23 @@
import { join } from "path"
import { WorkflowLoader } from "../workflow-loader"
import { WorkflowManager } from "@medusajs/orchestration" import { WorkflowManager } from "@medusajs/orchestration"
import { orderWorkflowId } from "../__fixtures__/workflows/order-notifier" import {
ContainerRegistrationKeys,
createMedusaContainer,
} from "@medusajs/utils"
import { asValue } from "awilix"
import { join } from "path"
import { logger } from "../../logger"
import { productWorkflowId } from "../__fixtures__/workflows/deep-workflows/product-updater" import { productWorkflowId } from "../__fixtures__/workflows/deep-workflows/product-updater"
import { orderWorkflowId } from "../__fixtures__/workflows/order-notifier"
import { WorkflowLoader } from "../workflow-loader"
describe("WorkflowLoader", () => { describe("WorkflowLoader", () => {
const rootDir = join(__dirname, "../__fixtures__", "workflows") const rootDir = join(__dirname, "../__fixtures__", "workflows")
beforeAll(async () => { beforeAll(async () => {
await new WorkflowLoader(rootDir).load() const container = createMedusaContainer()
container.register(ContainerRegistrationKeys.LOGGER, asValue(logger))
await new WorkflowLoader(rootDir, container).load()
}) })
it("should register each workflow in the '/workflows' folder and sub folder", async () => { it("should register each workflow in the '/workflows' folder and sub folder", async () => {
@@ -1,3 +1,4 @@
import { MedusaContainer } from "@medusajs/types"
import { isFileSkipped } from "@medusajs/utils" import { isFileSkipped } from "@medusajs/utils"
import { MedusaWorkflow } from "@medusajs/workflows-sdk" import { MedusaWorkflow } from "@medusajs/workflows-sdk"
import { logger } from "../logger" import { logger } from "../logger"
@@ -6,8 +7,8 @@ import { ResourceLoader } from "../utils/resource-loader"
export class WorkflowLoader extends ResourceLoader { export class WorkflowLoader extends ResourceLoader {
protected resourceName = "workflow" protected resourceName = "workflow"
constructor(sourceDir: string | string[]) { constructor(sourceDir: string | string[], container: MedusaContainer) {
super(sourceDir) super(sourceDir, container)
} }
protected async onFileLoaded( protected async onFileLoaded(
@@ -35,6 +36,6 @@ export class WorkflowLoader extends ResourceLoader {
async load() { async load() {
await super.discoverResources() await super.discoverResources()
logger.debug(`Workflows registered.`) this.logger.debug(`Workflows registered.`)
} }
} }
@@ -8,6 +8,7 @@ import type { RedisOptions } from "ioredis"
import { ConnectionOptions } from "node:tls" import { ConnectionOptions } from "node:tls"
// @ts-ignore // @ts-ignore
import type { InlineConfig } from "vite" import type { InlineConfig } from "vite"
import type { Logger } from "../logger"
/** /**
* @interface * @interface
@@ -919,7 +920,7 @@ export type ProjectConfigOptions = {
*/ */
export type ConfigModule = { export type ConfigModule = {
/** /**
* This property holds essential configurations related to the Medusa application, such as database and CORS configurations. * This property holds essential configurations related to the Medusa application, such as database, CORS configurations and Logger.
*/ */
projectConfig: ProjectConfigOptions projectConfig: ProjectConfigOptions
@@ -1047,6 +1048,11 @@ export type ConfigModule = {
* ::: * :::
*/ */
featureFlags: Record<string, boolean | string | Record<string, boolean>> featureFlags: Record<string, boolean | string | Record<string, boolean>>
/**
* The Logger instance to be used by the application.
*/
logger?: Logger
} }
type InternalModuleDeclarationOverride = InternalModuleDeclaration & { type InternalModuleDeclarationOverride = InternalModuleDeclaration & {
+16 -13
View File
@@ -1,15 +1,18 @@
export interface Logger { export interface Logger {
panic: (data: any) => void panic(data: unknown): void
shouldLog: (level: string) => boolean shouldLog(level: string): boolean
setLogLevel: (level: string) => void setLogLevel(level: string): void
unsetLogLevel: () => void unsetLogLevel(): void
activity: (message: string, config?: Record<string, any>) => string activity(message: string, config?: unknown): string
progress: (activityId: string, message: string) => void progress(activityId: string, message: string): void
error: (messageOrError: string | Error, error?: Error) => void error(messageOrError: string | Error, error?: Error): void
failure: (activityId: string, message: string) => Record<string, any> | null failure(activityId: string, message: string): unknown
success: (activityId: string, message: string) => Record<string, any> | null success(activityId: string, message: string): Record<string, unknown>
debug: (message: string) => void silly(message: string): void
info: (message: string) => void debug(message: string): void
warn: (message: string) => void verbose(message: string): void
log: (...args: any[]) => void http(message: string): void
info(message: string): void
warn(message: string): void
log(...args: unknown[]): void
} }
@@ -10,6 +10,7 @@ describe("defineConfig", function () {
"path": "/app", "path": "/app",
}, },
"featureFlags": {}, "featureFlags": {},
"logger": undefined,
"modules": { "modules": {
"api_key": { "api_key": {
"resolve": "@medusajs/medusa/api-key", "resolve": "@medusajs/medusa/api-key",
@@ -179,6 +180,7 @@ describe("defineConfig", function () {
"path": "/app", "path": "/app",
}, },
"featureFlags": {}, "featureFlags": {},
"logger": undefined,
"modules": { "modules": {
"GithubModuleService": { "GithubModuleService": {
"resolve": "./modules/github", "resolve": "./modules/github",
@@ -354,6 +356,7 @@ describe("defineConfig", function () {
"path": "/app", "path": "/app",
}, },
"featureFlags": {}, "featureFlags": {},
"logger": undefined,
"modules": { "modules": {
"GithubModuleService": { "GithubModuleService": {
"options": { "options": {
@@ -535,6 +538,7 @@ describe("defineConfig", function () {
"path": "/app", "path": "/app",
}, },
"featureFlags": {}, "featureFlags": {},
"logger": undefined,
"modules": { "modules": {
"GithubModuleServiceOverride": { "GithubModuleServiceOverride": {
"options": { "options": {
@@ -712,6 +716,7 @@ describe("defineConfig", function () {
"path": "/app", "path": "/app",
}, },
"featureFlags": {}, "featureFlags": {},
"logger": undefined,
"modules": { "modules": {
"api_key": { "api_key": {
"resolve": "@medusajs/medusa/api-key", "resolve": "@medusajs/medusa/api-key",
@@ -884,6 +889,7 @@ describe("defineConfig", function () {
"path": "/app", "path": "/app",
}, },
"featureFlags": {}, "featureFlags": {},
"logger": undefined,
"modules": { "modules": {
"api_key": { "api_key": {
"resolve": "@medusajs/medusa/api-key", "resolve": "@medusajs/medusa/api-key",
@@ -1058,6 +1064,7 @@ describe("defineConfig", function () {
"path": "/app", "path": "/app",
}, },
"featureFlags": {}, "featureFlags": {},
"logger": undefined,
"modules": { "modules": {
"api_key": { "api_key": {
"resolve": "@medusajs/medusa/api-key", "resolve": "@medusajs/medusa/api-key",
@@ -1265,6 +1272,7 @@ describe("defineConfig", function () {
"path": "/app", "path": "/app",
}, },
"featureFlags": {}, "featureFlags": {},
"logger": undefined,
"modules": { "modules": {
"api_key": { "api_key": {
"resolve": "@medusajs/medusa/api-key", "resolve": "@medusajs/medusa/api-key",
@@ -1488,6 +1496,7 @@ describe("defineConfig", function () {
"path": "/app", "path": "/app",
}, },
"featureFlags": {}, "featureFlags": {},
"logger": undefined,
"modules": { "modules": {
"api_key": { "api_key": {
"resolve": "@medusajs/medusa/api-key", "resolve": "@medusajs/medusa/api-key",
@@ -1791,6 +1800,7 @@ describe("defineConfig", function () {
"path": "/app", "path": "/app",
}, },
"featureFlags": {}, "featureFlags": {},
"logger": undefined,
"modules": { "modules": {
"api_key": { "api_key": {
"resolve": "@medusajs/medusa/api-key", "resolve": "@medusajs/medusa/api-key",
@@ -56,6 +56,7 @@ export function defineConfig(config: InputConfig = {}): ConfigModule {
featureFlags: (config.featureFlags ?? {}) as ConfigModule["featureFlags"], featureFlags: (config.featureFlags ?? {}) as ConfigModule["featureFlags"],
admin: adminConfig, admin: adminConfig,
modules: modules, modules: modules,
logger: config.logger,
plugins, plugins,
} }
} }
@@ -62,7 +62,8 @@ async function loadCustomLinks(directory: string, container: MedusaContainer) {
const linksSourcePaths = plugins.map((plugin) => const linksSourcePaths = plugins.map((plugin) =>
join(plugin.resolve, "links") join(plugin.resolve, "links")
) )
const logger = container.resolve(ContainerRegistrationKeys.LOGGER)
const { LinkLoader } = await import("@medusajs/framework") const { LinkLoader } = await import("@medusajs/framework")
await new LinkLoader(linksSourcePaths).load() await new LinkLoader(linksSourcePaths, logger).load()
} }
@@ -1,13 +1,36 @@
import { registerInstrumentation } from "../start"
import * as utils from "@medusajs/framework/utils" import * as utils from "@medusajs/framework/utils"
import * as logger from "@medusajs/framework/logger" import path from "path"
import * as instrumentationFixture from "../__fixtures__/instrumentation" import * as instrumentationFixture from "../__fixtures__/instrumentation"
import * as instrumentationFailureFixture from "../__fixtures__/instrumentation-failure/instrumentation" import * as instrumentationFailureFixture from "../__fixtures__/instrumentation-failure/instrumentation"
import path from "path" import { registerInstrumentation } from "../start"
const logger = {
info: jest.fn(),
error: jest.fn(),
}
jest.mock("@medusajs/framework/config", () => {
return {
configManager: {
config: {},
},
configLoader: jest.fn().mockImplementation(() => {
return {
logger,
}
}),
}
})
describe("start", () => { describe("start", () => {
beforeEach(() => { beforeEach(() => {
jest.clearAllMocks() jest.clearAllMocks()
jest.doMock("@medusajs/framework/utils", () => ({
...jest.requireActual("@medusajs/framework/utils"),
createMedusaContainer: jest.fn(() => ({
resolve: jest.fn(() => logger),
})),
}))
}) })
describe("registerInstrumentation", () => { describe("registerInstrumentation", () => {
@@ -32,7 +55,7 @@ describe("start", () => {
"exists", "exists",
"" as never "" as never
) )
const loggerSpy = jest.spyOn(logger.logger, "info", "" as never) const loggerSpy = jest.spyOn(logger, "info", "" as never)
await registerInstrumentation( await registerInstrumentation(
path.join(__dirname, "../__fixtures__/instrumentation-no-register") path.join(__dirname, "../__fixtures__/instrumentation-no-register")
+7 -1
View File
@@ -1,5 +1,6 @@
import { logger } from "@medusajs/framework/logger"
import { Compiler } from "@medusajs/framework/build-tools" import { Compiler } from "@medusajs/framework/build-tools"
import { ContainerRegistrationKeys } from "@medusajs/framework/utils"
import { initializeContainer } from "../loaders"
export default async function build({ export default async function build({
directory, directory,
@@ -8,6 +9,11 @@ export default async function build({
directory: string directory: string
adminOnly: boolean adminOnly: boolean
}) { }) {
const container = await initializeContainer(directory, {
skipDbConnection: true,
})
const logger = container.resolve(ContainerRegistrationKeys.LOGGER)
logger.info("Starting build...") logger.info("Starting build...")
const compiler = new Compiler(directory, logger) const compiler = new Compiler(directory, logger)
+13 -4
View File
@@ -1,14 +1,16 @@
import slugify from "slugify"
import { basename } from "path"
import input from "@inquirer/input" import input from "@inquirer/input"
import { logger } from "@medusajs/framework/logger" import type { Logger } from "@medusajs/framework/types"
import { import {
ContainerRegistrationKeys,
createClient, createClient,
createDb, createDb,
dbExists, dbExists,
EnvEditor, EnvEditor,
parseConnectionString, parseConnectionString,
} from "@medusajs/framework/utils" } from "@medusajs/framework/utils"
import { basename } from "path"
import slugify from "slugify"
import { initializeContainer } from "../../loaders"
async function connectClient(client: ReturnType<typeof createClient>) { async function connectClient(client: ReturnType<typeof createClient>) {
try { try {
@@ -27,10 +29,12 @@ export async function dbCreate({
db, db,
directory, directory,
interactive, interactive,
logger,
}: { }: {
db: string | undefined db: string | undefined
directory: string directory: string
interactive: boolean interactive: boolean
logger: Logger
}): Promise<boolean> { }): Promise<boolean> {
let dbName = db let dbName = db
@@ -155,8 +159,13 @@ export async function dbCreate({
} }
const main = async function ({ directory, interactive, db }) { const main = async function ({ directory, interactive, db }) {
const container = await initializeContainer(directory, {
skipDbConnection: true,
})
const logger = container.resolve(ContainerRegistrationKeys.LOGGER)
try { try {
const created = await dbCreate({ directory, interactive, db }) const created = await dbCreate({ directory, interactive, db, logger })
process.exit(created ? 0 : 1) process.exit(created ? 0 : 1)
} catch (error) { } catch (error) {
if (error.name === "ExitPromptError") { if (error.name === "ExitPromptError") {
+7 -6
View File
@@ -1,6 +1,5 @@
import { MedusaAppLoader } from "@medusajs/framework" import { MedusaAppLoader } from "@medusajs/framework"
import { LinkLoader } from "@medusajs/framework/links" import { LinkLoader } from "@medusajs/framework/links"
import { logger } from "@medusajs/framework/logger"
import { import {
ContainerRegistrationKeys, ContainerRegistrationKeys,
getResolvedPlugins, getResolvedPlugins,
@@ -8,18 +7,20 @@ import {
mergePluginModules, mergePluginModules,
} from "@medusajs/framework/utils" } from "@medusajs/framework/utils"
import { join } from "path" import { join } from "path"
import { initializeContainer } from "../../loaders" import { initializeContainer } from "../../loaders"
import { ensureDbExists } from "../utils" import { ensureDbExists } from "../utils"
const TERMINAL_SIZE = process.stdout.columns const TERMINAL_SIZE = process.stdout.columns
const main = async function ({ directory, modules }) { const main = async function ({ directory, modules }) {
const container = await initializeContainer(directory)
const logger = container.resolve(ContainerRegistrationKeys.LOGGER)
try { try {
/** /**
* Setup * Setup
*/ */
const container = await initializeContainer(directory)
await ensureDbExists(container) await ensureDbExists(container)
const medusaAppLoader = new MedusaAppLoader() const medusaAppLoader = new MedusaAppLoader()
@@ -33,7 +34,7 @@ const main = async function ({ directory, modules }) {
const linksSourcePaths = plugins.map((plugin) => const linksSourcePaths = plugins.map((plugin) =>
join(plugin.resolve, "links") join(plugin.resolve, "links")
) )
await new LinkLoader(linksSourcePaths).load() await new LinkLoader(linksSourcePaths, logger).load()
/** /**
* Generating migrations * Generating migrations
@@ -45,12 +46,12 @@ const main = async function ({ directory, modules }) {
action: "generate", action: "generate",
}) })
console.log(new Array(TERMINAL_SIZE).join("-")) logger.log(new Array(TERMINAL_SIZE).join("-"))
logger.info("Migrations generated") logger.info("Migrations generated")
process.exit() process.exit()
} catch (error) { } catch (error) {
console.log(new Array(TERMINAL_SIZE).join("-")) logger.log(new Array(TERMINAL_SIZE).join("-"))
if (error.code && error.code === MedusaError.Codes.UNKNOWN_MODULES) { if (error.code && error.code === MedusaError.Codes.UNKNOWN_MODULES) {
logger.error(error.message) logger.error(error.message)
const modulesList = error.allModules.map( const modulesList = error.allModules.map(
+19 -9
View File
@@ -1,18 +1,17 @@
import { MEDUSA_CLI_PATH, MedusaAppLoader } from "@medusajs/framework" import { MEDUSA_CLI_PATH, MedusaAppLoader } from "@medusajs/framework"
import { LinkLoader } from "@medusajs/framework/links" import { LinkLoader } from "@medusajs/framework/links"
import { logger } from "@medusajs/framework/logger"
import { import {
ContainerRegistrationKeys, ContainerRegistrationKeys,
getResolvedPlugins, getResolvedPlugins,
mergePluginModules, mergePluginModules,
} from "@medusajs/framework/utils" } from "@medusajs/framework/utils"
import { join } from "path" import { Logger, MedusaContainer } from "@medusajs/types"
import { fork } from "child_process" import { fork } from "child_process"
import path from "path" import path, { join } from "path"
import { initializeContainer } from "../../loaders" import { initializeContainer } from "../../loaders"
import { ensureDbExists } from "../utils" import { ensureDbExists } from "../utils"
import { syncLinks } from "./sync-links" import { syncLinks } from "./sync-links"
const TERMINAL_SIZE = process.stdout.columns const TERMINAL_SIZE = process.stdout.columns
const cliPath = path.resolve(MEDUSA_CLI_PATH, "..", "..", "cli.js") const cliPath = path.resolve(MEDUSA_CLI_PATH, "..", "..", "cli.js")
@@ -27,17 +26,21 @@ export async function migrate({
skipScripts, skipScripts,
executeAllLinks, executeAllLinks,
executeSafeLinks, executeSafeLinks,
logger,
container,
}: { }: {
directory: string directory: string
skipLinks: boolean skipLinks: boolean
skipScripts: boolean skipScripts: boolean
executeAllLinks: boolean executeAllLinks: boolean
executeSafeLinks: boolean executeSafeLinks: boolean
logger: Logger
container: MedusaContainer
}): Promise<boolean> { }): Promise<boolean> {
/** /**
* Setup * Setup
*/ */
const container = await initializeContainer(directory)
await ensureDbExists(container) await ensureDbExists(container)
const medusaAppLoader = new MedusaAppLoader() const medusaAppLoader = new MedusaAppLoader()
@@ -51,7 +54,7 @@ export async function migrate({
const linksSourcePaths = plugins.map((plugin) => const linksSourcePaths = plugins.map((plugin) =>
join(plugin.resolve, "links") join(plugin.resolve, "links")
) )
await new LinkLoader(linksSourcePaths).load() await new LinkLoader(linksSourcePaths, logger).load()
/** /**
* Run migrations * Run migrations
@@ -60,17 +63,19 @@ export async function migrate({
await medusaAppLoader.runModulesMigrations({ await medusaAppLoader.runModulesMigrations({
action: "run", action: "run",
}) })
console.log(new Array(TERMINAL_SIZE).join("-")) logger.log(new Array(TERMINAL_SIZE).join("-"))
logger.info("Migrations completed") logger.info("Migrations completed")
/** /**
* Sync links * Sync links
*/ */
if (!skipLinks) { if (!skipLinks) {
console.log(new Array(TERMINAL_SIZE).join("-")) logger.log(new Array(TERMINAL_SIZE).join("-"))
await syncLinks(medusaAppLoader, { await syncLinks(medusaAppLoader, {
executeAll: executeAllLinks, executeAll: executeAllLinks,
executeSafe: executeSafeLinks, executeSafe: executeSafeLinks,
directory,
container,
}) })
} }
@@ -78,7 +83,7 @@ export async function migrate({
/** /**
* Run migration scripts * Run migration scripts
*/ */
console.log(new Array(TERMINAL_SIZE).join("-")) logger.log(new Array(TERMINAL_SIZE).join("-"))
const childProcess = fork(cliPath, ["db:migrate:scripts"], { const childProcess = fork(cliPath, ["db:migrate:scripts"], {
cwd: directory, cwd: directory,
env: process.env, env: process.env,
@@ -104,6 +109,9 @@ const main = async function ({
executeAllLinks, executeAllLinks,
executeSafeLinks, executeSafeLinks,
}) { }) {
const container = await initializeContainer(directory)
const logger = container.resolve(ContainerRegistrationKeys.LOGGER)
try { try {
const migrated = await migrate({ const migrated = await migrate({
directory, directory,
@@ -111,6 +119,8 @@ const main = async function ({
skipScripts, skipScripts,
executeAllLinks, executeAllLinks,
executeSafeLinks, executeSafeLinks,
logger,
container,
}) })
process.exit(migrated ? 0 : 1) process.exit(migrated ? 0 : 1)
} catch (error) { } catch (error) {
+7 -6
View File
@@ -1,6 +1,5 @@
import { MedusaAppLoader } from "@medusajs/framework" import { MedusaAppLoader } from "@medusajs/framework"
import { LinkLoader } from "@medusajs/framework/links" import { LinkLoader } from "@medusajs/framework/links"
import { logger } from "@medusajs/framework/logger"
import { import {
ContainerRegistrationKeys, ContainerRegistrationKeys,
getResolvedPlugins, getResolvedPlugins,
@@ -8,18 +7,20 @@ import {
mergePluginModules, mergePluginModules,
} from "@medusajs/framework/utils" } from "@medusajs/framework/utils"
import { join } from "path" import { join } from "path"
import { initializeContainer } from "../../loaders" import { initializeContainer } from "../../loaders"
import { ensureDbExists } from "../utils" import { ensureDbExists } from "../utils"
const TERMINAL_SIZE = process.stdout.columns const TERMINAL_SIZE = process.stdout.columns
const main = async function ({ directory, modules }) { const main = async function ({ directory, modules }) {
const container = await initializeContainer(directory)
const logger = container.resolve(ContainerRegistrationKeys.LOGGER)
try { try {
/** /**
* Setup * Setup
*/ */
const container = await initializeContainer(directory)
await ensureDbExists(container) await ensureDbExists(container)
const medusaAppLoader = new MedusaAppLoader() const medusaAppLoader = new MedusaAppLoader()
@@ -33,7 +34,7 @@ const main = async function ({ directory, modules }) {
const linksSourcePaths = plugins.map((plugin) => const linksSourcePaths = plugins.map((plugin) =>
join(plugin.resolve, "links") join(plugin.resolve, "links")
) )
await new LinkLoader(linksSourcePaths).load() await new LinkLoader(linksSourcePaths, logger).load()
/** /**
* Reverting migrations * Reverting migrations
@@ -43,12 +44,12 @@ const main = async function ({ directory, modules }) {
moduleNames: modules, moduleNames: modules,
action: "revert", action: "revert",
}) })
console.log(new Array(TERMINAL_SIZE).join("-")) logger.log(new Array(TERMINAL_SIZE).join("-"))
logger.info("Migrations reverted") logger.info("Migrations reverted")
process.exit() process.exit()
} catch (error) { } catch (error) {
console.log(new Array(TERMINAL_SIZE).join("-")) logger.log(new Array(TERMINAL_SIZE).join("-"))
if (error.code && error.code === MedusaError.Codes.UNKNOWN_MODULES) { if (error.code && error.code === MedusaError.Codes.UNKNOWN_MODULES) {
logger.error(error.message) logger.error(error.message)
const modulesList = error.allModules.map( const modulesList = error.allModules.map(
+23 -13
View File
@@ -1,6 +1,5 @@
import { MedusaAppLoader } from "@medusajs/framework" import { MedusaAppLoader } from "@medusajs/framework"
import { LinkLoader } from "@medusajs/framework/links" import { LinkLoader } from "@medusajs/framework/links"
import { logger } from "@medusajs/framework/logger"
import { MigrationScriptsMigrator } from "@medusajs/framework/migrations" import { MigrationScriptsMigrator } from "@medusajs/framework/migrations"
import { import {
ContainerRegistrationKeys, ContainerRegistrationKeys,
@@ -10,7 +9,7 @@ import {
import { dirname, join } from "path" import { dirname, join } from "path"
import { MedusaModule } from "@medusajs/framework/modules-sdk" import { MedusaModule } from "@medusajs/framework/modules-sdk"
import { MedusaContainer, PluginDetails } from "@medusajs/types" import { Logger, MedusaContainer, PluginDetails } from "@medusajs/types"
import { initializeContainer } from "../../loaders" import { initializeContainer } from "../../loaders"
import { ensureDbExists } from "../utils" import { ensureDbExists } from "../utils"
@@ -22,20 +21,23 @@ const TERMINAL_SIZE = process.stdout.columns
*/ */
export async function runMigrationScripts({ export async function runMigrationScripts({
directory, directory,
container,
logger,
}: { }: {
directory: string directory: string
container: MedusaContainer
logger: Logger
}): Promise<boolean> { }): Promise<boolean> {
let onApplicationPrepareShutdown: () => Promise<void> = async () => let onApplicationPrepareShutdown: () => Promise<void> = async () =>
Promise.resolve() Promise.resolve()
let onApplicationShutdown: () => Promise<void> = async () => Promise.resolve() let onApplicationShutdown: () => Promise<void> = async () => Promise.resolve()
let container_: MedusaContainer
let plugins: PluginDetails[] let plugins: PluginDetails[]
try { try {
container_ = await initializeContainer(directory) await ensureDbExists(container)
await ensureDbExists(container_)
const configModule = container_.resolve( const configModule = container.resolve(
ContainerRegistrationKeys.CONFIG_MODULE ContainerRegistrationKeys.CONFIG_MODULE
) )
@@ -43,7 +45,7 @@ export async function runMigrationScripts({
mergePluginModules(configModule, plugins) mergePluginModules(configModule, plugins)
const resources = await loadResources(plugins) const resources = await loadResources(plugins, logger)
onApplicationPrepareShutdown = resources.onApplicationPrepareShutdown onApplicationPrepareShutdown = resources.onApplicationPrepareShutdown
onApplicationShutdown = resources.onApplicationShutdown onApplicationShutdown = resources.onApplicationShutdown
@@ -52,7 +54,7 @@ export async function runMigrationScripts({
...plugins.map((plugin) => join(plugin.resolve, "migration-scripts")), ...plugins.map((plugin) => join(plugin.resolve, "migration-scripts")),
] ]
const migrator = new MigrationScriptsMigrator({ container: container_ }) const migrator = new MigrationScriptsMigrator({ container: container })
await migrator.ensureMigrationsTable() await migrator.ensureMigrationsTable()
const pendingScripts = await migrator.getPendingMigrations( const pendingScripts = await migrator.getPendingMigrations(
scriptsSourcePaths scriptsSourcePaths
@@ -63,15 +65,15 @@ export async function runMigrationScripts({
return true return true
} }
console.log(new Array(TERMINAL_SIZE).join("-")) logger.log(new Array(TERMINAL_SIZE).join("-"))
logger.info("Pending migration scripts to execute") logger.info("Pending migration scripts to execute")
logger.info(`${pendingScripts.join("\n")}`) logger.info(`${pendingScripts.join("\n")}`)
console.log(new Array(TERMINAL_SIZE).join("-")) logger.log(new Array(TERMINAL_SIZE).join("-"))
logger.info("Running migration scripts...") logger.info("Running migration scripts...")
await migrator.run(scriptsSourcePaths) await migrator.run(scriptsSourcePaths)
console.log(new Array(TERMINAL_SIZE).join("-")) logger.log(new Array(TERMINAL_SIZE).join("-"))
logger.info("Migration scripts completed") logger.info("Migration scripts completed")
return true return true
@@ -81,7 +83,10 @@ export async function runMigrationScripts({
} }
} }
async function loadResources(plugins: any): Promise<{ async function loadResources(
plugins: any,
logger: Logger
): Promise<{
onApplicationPrepareShutdown: () => Promise<void> onApplicationPrepareShutdown: () => Promise<void>
onApplicationShutdown: () => Promise<void> onApplicationShutdown: () => Promise<void>
}> { }> {
@@ -97,7 +102,7 @@ async function loadResources(plugins: any): Promise<{
const linksSourcePaths = plugins.map((plugin) => const linksSourcePaths = plugins.map((plugin) =>
join(plugin.resolve, "links") join(plugin.resolve, "links")
) )
await new LinkLoader(linksSourcePaths).load() await new LinkLoader(linksSourcePaths, logger).load()
const medusaAppResources = await new MedusaAppLoader().load() const medusaAppResources = await new MedusaAppLoader().load()
const onApplicationPrepareShutdown = const onApplicationPrepareShutdown =
@@ -117,9 +122,14 @@ const main = async function ({
directory: string directory: string
container?: MedusaContainer container?: MedusaContainer
}) { }) {
const container = await initializeContainer(directory)
const logger = container.resolve(ContainerRegistrationKeys.LOGGER)
try { try {
const migrated = await runMigrationScripts({ const migrated = await runMigrationScripts({
directory, directory,
container: container,
logger,
}) })
process.exit(migrated ? 0 : 1) process.exit(migrated ? 0 : 1)
} catch (error) { } catch (error) {
+8 -2
View File
@@ -1,4 +1,5 @@
import { logger } from "@medusajs/framework/logger" import { ContainerRegistrationKeys } from "@medusajs/framework/utils"
import { initializeContainer } from "../../loaders"
import { dbCreate } from "./create" import { dbCreate } from "./create"
import { migrate } from "./migrate" import { migrate } from "./migrate"
@@ -11,8 +12,11 @@ const main = async function ({
executeAllLinks, executeAllLinks,
executeSafeLinks, executeSafeLinks,
}) { }) {
const container = await initializeContainer(directory)
const logger = container.resolve(ContainerRegistrationKeys.LOGGER)
try { try {
const created = await dbCreate({ directory, interactive, db }) const created = await dbCreate({ directory, interactive, db, logger })
if (!created) { if (!created) {
process.exit(1) process.exit(1)
} }
@@ -23,6 +27,8 @@ const main = async function ({
skipScripts, skipScripts,
executeAllLinks, executeAllLinks,
executeSafeLinks, executeSafeLinks,
logger,
container,
}) })
process.exit(migrated ? 0 : 1) process.exit(migrated ? 0 : 1)
+34 -14
View File
@@ -1,8 +1,11 @@
import checkbox from "@inquirer/checkbox" import checkbox from "@inquirer/checkbox"
import { MedusaAppLoader } from "@medusajs/framework" import { MedusaAppLoader } from "@medusajs/framework"
import { LinkLoader } from "@medusajs/framework/links" import { LinkLoader } from "@medusajs/framework/links"
import { logger } from "@medusajs/framework/logger" import {
import { LinkMigrationsPlannerAction } from "@medusajs/framework/types" LinkMigrationsPlannerAction,
Logger,
MedusaContainer,
} from "@medusajs/framework/types"
import { import {
ContainerRegistrationKeys, ContainerRegistrationKeys,
getResolvedPlugins, getResolvedPlugins,
@@ -52,13 +55,14 @@ function buildLinkDescription(action: LinkMigrationsPlannerAction) {
*/ */
function logActions( function logActions(
title: string, title: string,
actionsOrContext: LinkMigrationsPlannerAction[] actionsOrContext: LinkMigrationsPlannerAction[],
logger: Logger
) { ) {
const actionsList = actionsOrContext const actionsList = actionsOrContext
.map((action) => ` - ${buildLinkDescription(action)}`) .map((action) => ` - ${buildLinkDescription(action)}`)
.join("\n") .join("\n")
console.log(boxen(`${title}\n${actionsList}`, { padding: 1 })) logger.info(boxen(`${title}\n${actionsList}`, { padding: 1 }))
} }
/** /**
@@ -67,9 +71,10 @@ function logActions(
*/ */
async function askForLinkActionsToPerform( async function askForLinkActionsToPerform(
message: string, message: string,
actions: LinkMigrationsPlannerAction[] actions: LinkMigrationsPlannerAction[],
logger: Logger
) { ) {
console.log(boxen(message, { borderColor: "red", padding: 1 })) logger.info(boxen(message, { borderColor: "red", padding: 1 }))
return await checkbox({ return await checkbox({
message: "Select tables to act upon", message: "Select tables to act upon",
@@ -95,11 +100,17 @@ export async function syncLinks(
{ {
executeAll, executeAll,
executeSafe, executeSafe,
directory,
container,
}: { }: {
executeSafe: boolean executeSafe: boolean
executeAll: boolean executeAll: boolean
directory: string
container: MedusaContainer
} }
) { ) {
const logger = container.resolve(ContainerRegistrationKeys.LOGGER)
const planner = await medusaAppLoader.getLinksExecutionPlanner() const planner = await medusaAppLoader.getLinksExecutionPlanner()
logger.info("Syncing links...") logger.info("Syncing links...")
@@ -120,7 +131,8 @@ export async function syncLinks(
`Select the tables to ${chalk.red( `Select the tables to ${chalk.red(
"DELETE" "DELETE"
)}. The following links have been removed`, )}. The following links have been removed`,
groupActionPlan.delete groupActionPlan.delete,
logger
) )
} }
} }
@@ -140,7 +152,8 @@ export async function syncLinks(
`Select the tables to ${chalk.red( `Select the tables to ${chalk.red(
"UPDATE" "UPDATE"
)}. The following links have been updated`, )}. The following links have been updated`,
groupActionPlan.notify groupActionPlan.notify,
logger
) )
} }
@@ -163,13 +176,13 @@ export async function syncLinks(
await planner.executePlan(actionsToExecute) await planner.executePlan(actionsToExecute)
if (toCreate.length) { if (toCreate.length) {
logActions("Created following links tables", toCreate) logActions("Created following links tables", toCreate, logger)
} }
if (toUpdate.length) { if (toUpdate.length) {
logActions("Updated following links tables", toUpdate) logActions("Updated following links tables", toUpdate, logger)
} }
if (toDelete.length) { if (toDelete.length) {
logActions("Deleted following links tables", toDelete) logActions("Deleted following links tables", toDelete, logger)
} }
if (actionsToExecute.length) { if (actionsToExecute.length) {
@@ -180,8 +193,10 @@ export async function syncLinks(
} }
const main = async function ({ directory, executeSafe, executeAll }) { const main = async function ({ directory, executeSafe, executeAll }) {
const container = await initializeContainer(directory)
const logger = container.resolve(ContainerRegistrationKeys.LOGGER)
try { try {
const container = await initializeContainer(directory)
await ensureDbExists(container) await ensureDbExists(container)
const configModule = container.resolve( const configModule = container.resolve(
@@ -196,9 +211,14 @@ const main = async function ({ directory, executeSafe, executeAll }) {
const linksSourcePaths = plugins.map((plugin) => const linksSourcePaths = plugins.map((plugin) =>
join(plugin.resolve, "links") join(plugin.resolve, "links")
) )
await new LinkLoader(linksSourcePaths).load() await new LinkLoader(linksSourcePaths, logger).load()
await syncLinks(medusaAppLoader, { executeAll, executeSafe }) await syncLinks(medusaAppLoader, {
executeAll,
executeSafe,
directory,
container,
})
process.exit() process.exit()
} catch (error) { } catch (error) {
logger.error(error) logger.error(error)
+7 -4
View File
@@ -1,12 +1,12 @@
import { MEDUSA_CLI_PATH } from "@medusajs/framework"
import { ContainerRegistrationKeys } from "@medusajs/framework/utils"
import { Store } from "@medusajs/telemetry"
import boxen from "boxen" import boxen from "boxen"
import { ChildProcess, execSync, fork } from "child_process" import { ChildProcess, execSync, fork } from "child_process"
import chokidar, { FSWatcher } from "chokidar" import chokidar, { FSWatcher } from "chokidar"
import { Store } from "@medusajs/telemetry"
import { EOL } from "os" import { EOL } from "os"
import path from "path" import path from "path"
import { initializeContainer } from "../loaders"
import { logger } from "@medusajs/framework/logger"
import { MEDUSA_CLI_PATH } from "@medusajs/framework"
const defaultConfig = { const defaultConfig = {
padding: 5, padding: 5,
@@ -15,6 +15,9 @@ const defaultConfig = {
} as boxen.Options } as boxen.Options
export default async function ({ types, directory }) { export default async function ({ types, directory }) {
const container = await initializeContainer(directory)
const logger = container.resolve(ContainerRegistrationKeys.LOGGER)
const args = process.argv const args = process.argv
const argv = const argv =
+11 -3
View File
@@ -1,10 +1,13 @@
import { logger } from "@medusajs/framework/logger"
import { ExecArgs } from "@medusajs/framework/types" import { ExecArgs } from "@medusajs/framework/types"
import { dynamicImport, isFileSkipped } from "@medusajs/framework/utils" import {
ContainerRegistrationKeys,
dynamicImport,
isFileSkipped,
} from "@medusajs/framework/utils"
import express from "express" import express from "express"
import { existsSync } from "fs" import { existsSync } from "fs"
import path from "path" import path from "path"
import loaders from "../loaders" import loaders, { initializeContainer } from "../loaders"
type Options = { type Options = {
file: string file: string
@@ -12,6 +15,11 @@ type Options = {
} }
export default async function exec({ file, args }: Options) { export default async function exec({ file, args }: Options) {
const container = await initializeContainer(process.cwd(), {
skipDbConnection: true,
})
const logger = container.resolve(ContainerRegistrationKeys.LOGGER)
logger.info(`Executing script at ${file}...`) logger.info(`Executing script at ${file}...`)
const app = express() const app = express()
const directory = process.cwd() const directory = process.cwd()
@@ -1,5 +1,6 @@
import { Compiler } from "@medusajs/framework/build-tools" import { Compiler } from "@medusajs/framework/build-tools"
import { logger } from "@medusajs/framework/logger" import { logger } from "@medusajs/framework/logger"
export default async function build({ directory }: { directory: string }) { export default async function build({ directory }: { directory: string }) {
logger.info("Starting build...") logger.info("Starting build...")
const compiler = new Compiler(directory, logger) const compiler = new Compiler(directory, logger)
@@ -1,5 +1,6 @@
import { logger } from "@medusajs/framework/logger" import type { Logger } from "@medusajs/framework/types"
import { import {
ContainerRegistrationKeys,
defineMikroOrmCliConfig, defineMikroOrmCliConfig,
DmlEntity, DmlEntity,
dynamicImport, dynamicImport,
@@ -11,6 +12,7 @@ import { dirname, join } from "path"
import { MetadataStorage } from "@mikro-orm/core" import { MetadataStorage } from "@mikro-orm/core"
import { MikroORM } from "@mikro-orm/postgresql" import { MikroORM } from "@mikro-orm/postgresql"
import { initializeContainer } from "../../../loaders"
const TERMINAL_SIZE = process.stdout.columns const TERMINAL_SIZE = process.stdout.columns
@@ -18,6 +20,11 @@ const TERMINAL_SIZE = process.stdout.columns
* Generate migrations for all scanned modules in a plugin * Generate migrations for all scanned modules in a plugin
*/ */
const main = async function ({ directory }) { const main = async function ({ directory }) {
const container = await initializeContainer(directory, {
skipDbConnection: true,
})
const logger = container.resolve(ContainerRegistrationKeys.LOGGER)
try { try {
const moduleDescriptors = [] as { const moduleDescriptors = [] as {
serviceName: string serviceName: string
@@ -46,14 +53,14 @@ const main = async function ({ directory }) {
*/ */
logger.info("Generating migrations...") logger.info("Generating migrations...")
await generateMigrations(moduleDescriptors) await generateMigrations(moduleDescriptors, logger)
console.log(new Array(TERMINAL_SIZE).join("-")) logger.log(new Array(TERMINAL_SIZE).join("-"))
logger.info("Migrations generated") logger.info("Migrations generated")
process.exit() process.exit()
} catch (error) { } catch (error) {
console.log(new Array(TERMINAL_SIZE).join("-")) logger.log(new Array(TERMINAL_SIZE).join("-"))
logger.error(error.message, error) logger.error(error.message, error)
process.exit(1) process.exit(1)
@@ -101,7 +108,8 @@ async function generateMigrations(
serviceName: string serviceName: string
migrationsPath: string migrationsPath: string
entities: any[] entities: any[]
}[] = [] }[] = [],
logger: Logger
) { ) {
const DB_HOST = process.env.DB_HOST ?? "localhost" const DB_HOST = process.env.DB_HOST ?? "localhost"
const DB_USERNAME = process.env.DB_USERNAME ?? "" const DB_USERNAME = process.env.DB_USERNAME ?? ""
@@ -1,9 +1,24 @@
import { logger } from "@medusajs/framework/logger"
import { FileSystem } from "@medusajs/framework/utils" import { FileSystem } from "@medusajs/framework/utils"
import { join } from "path" import { join } from "path"
import main from "../../generate" import main from "../../generate"
const logger = {
log: jest.fn(),
info: jest.fn(),
error: jest.fn(),
warn: jest.fn(),
}
jest.mock("@medusajs/framework/logger") jest.mock("@medusajs/framework/logger")
jest.mock("../../../../../loaders", () => {
return {
initializeContainer: jest.fn().mockImplementation(() => {
return {
resolve: jest.fn(() => logger),
}
}),
}
})
describe("plugin-generate", () => { describe("plugin-generate", () => {
beforeEach(() => { beforeEach(() => {
@@ -13,6 +28,8 @@ describe("plugin-generate", () => {
.mockImplementation((code?: string | number | null) => { .mockImplementation((code?: string | number | null) => {
return code as never return code as never
}) })
jest.mock("@medusajs/framework/logger")
}) })
afterEach(async () => { afterEach(async () => {
@@ -1,14 +1,18 @@
import path from "path" import { Compiler } from "@medusajs/framework/build-tools"
import { ContainerRegistrationKeys } from "@medusajs/framework/utils"
import * as swcCore from "@swc/core" import * as swcCore from "@swc/core"
import { execFile } from "child_process" import { execFile } from "child_process"
import { logger } from "@medusajs/framework/logger" import path from "path"
import { Compiler } from "@medusajs/framework/build-tools" import { initializeContainer } from "../../loaders"
export default async function developPlugin({ export default async function developPlugin({
directory, directory,
}: { }: {
directory: string directory: string
}) { }) {
const container = await initializeContainer(directory)
const logger = container.resolve(ContainerRegistrationKeys.LOGGER)
let isBusy = false let isBusy = false
const compiler = new Compiler(directory, logger) const compiler = new Compiler(directory, logger)
const parsedConfig = await compiler.loadTSConfigFile() const parsedConfig = await compiler.loadTSConfigFile()
+12 -4
View File
@@ -6,8 +6,8 @@ import { scheduleJob } from "node-schedule"
import os from "os" import os from "os"
import path from "path" import path from "path"
import { logger } from "@medusajs/framework/logger"
import { import {
ContainerRegistrationKeys,
dynamicImport, dynamicImport,
FileSystem, FileSystem,
generateContainerTypes, generateContainerTypes,
@@ -20,7 +20,7 @@ import {
import { MedusaModule } from "@medusajs/framework/modules-sdk" import { MedusaModule } from "@medusajs/framework/modules-sdk"
import { MedusaContainer } from "@medusajs/framework/types" import { MedusaContainer } from "@medusajs/framework/types"
import { parse } from "url" import { parse } from "url"
import loaders from "../loaders" import loaders, { initializeContainer } from "../loaders"
const EVERY_SIXTH_HOUR = "0 */6 * * *" const EVERY_SIXTH_HOUR = "0 */6 * * *"
const CRON_SCHEDULE = EVERY_SIXTH_HOUR const CRON_SCHEDULE = EVERY_SIXTH_HOUR
@@ -33,6 +33,11 @@ const INSTRUMENTATION_FILE = "instrumentation"
* errors. * errors.
*/ */
export async function registerInstrumentation(directory: string) { export async function registerInstrumentation(directory: string) {
const container = await initializeContainer(directory, {
skipDbConnection: true,
})
const logger = container.resolve(ContainerRegistrationKeys.LOGGER)
const fileSystem = new FileSystem(directory) const fileSystem = new FileSystem(directory)
const exists = const exists =
(await fileSystem.exists(`${INSTRUMENTATION_FILE}.ts`)) || (await fileSystem.exists(`${INSTRUMENTATION_FILE}.ts`)) ||
@@ -82,10 +87,10 @@ function displayAdminUrl({
return return
} }
const logger = container.resolve("logger") const logger = container.resolve(ContainerRegistrationKeys.LOGGER)
const { const {
admin: { path: adminPath, disable }, admin: { path: adminPath, disable },
} = container.resolve("configModule") } = container.resolve(ContainerRegistrationKeys.CONFIG_MODULE)
if (disable) { if (disable) {
return return
@@ -141,6 +146,9 @@ async function start(args: {
}) { }) {
const { port = 9000, host, directory, types } = args const { port = 9000, host, directory, types } = args
const container = await initializeContainer(directory)
const logger = container.resolve(ContainerRegistrationKeys.LOGGER)
async function internalStart(generateTypes: boolean) { async function internalStart(generateTypes: boolean) {
track("CLI_START") track("CLI_START")
await registerInstrumentation(directory) await registerInstrumentation(directory)
+3 -3
View File
@@ -1,7 +1,6 @@
import { logger } from "@medusajs/framework/logger" import { ContainerRegistrationKeys, Modules } from "@medusajs/framework/utils"
import { Modules } from "@medusajs/framework/utils"
import express from "express"
import { track } from "@medusajs/telemetry" import { track } from "@medusajs/telemetry"
import express from "express"
import loaders from "../loaders" import loaders from "../loaders"
export default async function ({ export default async function ({
@@ -25,6 +24,7 @@ export default async function ({
directory, directory,
expressApp: app, expressApp: app,
}) })
const logger = container.resolve(ContainerRegistrationKeys.LOGGER)
const userService = container.resolve(Modules.USER) const userService = container.resolve(Modules.USER)
const authService = container.resolve(Modules.AUTH) const authService = container.resolve(Modules.AUTH)
+1 -1
View File
@@ -1,8 +1,8 @@
import { logger } from "@medusajs/framework/logger"
import { MedusaContainer } from "@medusajs/framework/types" import { MedusaContainer } from "@medusajs/framework/types"
import { ContainerRegistrationKeys } from "@medusajs/framework/utils" import { ContainerRegistrationKeys } from "@medusajs/framework/utils"
export async function ensureDbExists(container: MedusaContainer) { export async function ensureDbExists(container: MedusaContainer) {
const logger = container.resolve(ContainerRegistrationKeys.LOGGER)
const pgConnection = container.resolve( const pgConnection = container.resolve(
ContainerRegistrationKeys.PG_CONNECTION ContainerRegistrationKeys.PG_CONNECTION
) )
@@ -13,10 +13,10 @@ import {
ApiLoader, ApiLoader,
container, container,
featureFlagsLoader, featureFlagsLoader,
logger,
MedusaRequest, MedusaRequest,
} from "@medusajs/framework" } from "@medusajs/framework"
import { configManager } from "@medusajs/framework/config" import { configManager } from "@medusajs/framework/config"
import { logger as defaultLogger } from "@medusajs/framework/logger"
import { ConfigModule, MedusaContainer } from "@medusajs/types" import { ConfigModule, MedusaContainer } from "@medusajs/types"
import { config } from "../mocks" import { config } from "../mocks"
@@ -67,10 +67,8 @@ export const createServer = async (rootDir) => {
container.register(ContainerRegistrationKeys.PG_CONNECTION, asValue({})) container.register(ContainerRegistrationKeys.PG_CONNECTION, asValue({}))
container.register("configModule", asValue(config)) container.register("configModule", asValue(config))
container.register(ContainerRegistrationKeys.LOGGER, asValue(defaultLogger))
container.register({ container.register({
logger: asValue({
error: () => {},
}),
manager: asValue({}), manager: asValue({}),
}) })
@@ -88,7 +86,7 @@ export const createServer = async (rootDir) => {
}) })
await featureFlagsLoader() await featureFlagsLoader()
await moduleLoader({ container, moduleResolutions, logger }) await moduleLoader({ container, moduleResolutions, logger: defaultLogger })
app.use((req, res, next) => { app.use((req, res, next) => {
;(req as MedusaRequest).scope = container.createScope() as MedusaContainer ;(req as MedusaRequest).scope = container.createScope() as MedusaContainer
@@ -98,6 +96,7 @@ export const createServer = async (rootDir) => {
await new ApiLoader({ await new ApiLoader({
app, app,
sourceDir: rootDir, sourceDir: rootDir,
container,
}).load() }).load()
const superRequest = supertest(app) const superRequest = supertest(app)
+4 -3
View File
@@ -1,9 +1,9 @@
import { ConfigModule } from "@medusajs/framework/config"
import { ApiLoader } from "@medusajs/framework/http"
import { MedusaContainer, PluginDetails } from "@medusajs/framework/types"
import { Express } from "express" import { Express } from "express"
import { join } from "path" import { join } from "path"
import qs from "qs" import qs from "qs"
import { ApiLoader } from "@medusajs/framework/http"
import { MedusaContainer, PluginDetails } from "@medusajs/framework/types"
import { ConfigModule } from "@medusajs/framework/config"
type Options = { type Options = {
app: Express app: Express
@@ -59,6 +59,7 @@ export default async ({ app, container, plugins }: Options) => {
app: app, app: app,
sourceDir: sourcePaths, sourceDir: sourcePaths,
baseRestrictedFields: restrictedFields?.store, baseRestrictedFields: restrictedFields?.store,
container,
}).load() }).load()
} catch (err) { } catch (err) {
throw Error( throw Error(
+33 -14
View File
@@ -5,7 +5,7 @@ import { featureFlagsLoader } from "@medusajs/framework/feature-flags"
import { expressLoader } from "@medusajs/framework/http" import { expressLoader } from "@medusajs/framework/http"
import { JobLoader } from "@medusajs/framework/jobs" import { JobLoader } from "@medusajs/framework/jobs"
import { LinkLoader } from "@medusajs/framework/links" import { LinkLoader } from "@medusajs/framework/links"
import { logger } from "@medusajs/framework/logger" import { logger as defaultLogger } from "@medusajs/framework/logger"
import { SubscriberLoader } from "@medusajs/framework/subscribers" import { SubscriberLoader } from "@medusajs/framework/subscribers"
import { import {
ConfigModule, ConfigModule,
@@ -46,7 +46,10 @@ const shouldLoadBackgroundProcessors = (configModule) => {
) )
} }
async function subscribersLoader(plugins: PluginDetails[]) { async function subscribersLoader(
plugins: PluginDetails[],
container: MedusaContainer
) {
const pluginSubscribersSourcePaths = [ const pluginSubscribersSourcePaths = [
/** /**
* Load subscribers from the medusa/medusa package. Remove once the medusa core is converted to a plugin * Load subscribers from the medusa/medusa package. Remove once the medusa core is converted to a plugin
@@ -54,19 +57,26 @@ async function subscribersLoader(plugins: PluginDetails[]) {
join(__dirname, "../subscribers"), join(__dirname, "../subscribers"),
].concat(plugins.map((plugin) => join(plugin.resolve, "subscribers"))) ].concat(plugins.map((plugin) => join(plugin.resolve, "subscribers")))
const subscriberLoader = new SubscriberLoader(pluginSubscribersSourcePaths) const subscriberLoader = new SubscriberLoader(
pluginSubscribersSourcePaths,
undefined,
container
)
await subscriberLoader.load() await subscriberLoader.load()
} }
async function jobsLoader(plugins: PluginDetails[]) { async function jobsLoader(
plugins: PluginDetails[],
container: MedusaContainer
) {
const pluginJobSourcePaths = [ const pluginJobSourcePaths = [
/** /**
* Load jobs from the medusa/medusa package. Remove once the medusa core is converted to a plugin * Load jobs from the medusa/medusa package. Remove once the medusa core is converted to a plugin
*/ */
join(__dirname, "../jobs"), join(__dirname, "../jobs"),
].concat(plugins.map((plugin) => join(plugin.resolve, "jobs"))) ].concat(plugins.map((plugin) => join(plugin.resolve, "jobs")))
const jobLoader = new JobLoader(pluginJobSourcePaths) const jobLoader = new JobLoader(pluginJobSourcePaths, container)
await jobLoader.load() await jobLoader.load()
} }
@@ -81,8 +91,8 @@ async function loadEntrypoints(
) )
if (shouldLoadBackgroundProcessors(configModule)) { if (shouldLoadBackgroundProcessors(configModule)) {
await subscribersLoader(plugins) await subscribersLoader(plugins, container)
await jobsLoader(plugins) await jobsLoader(plugins, container)
} }
if (isWorkerMode(configModule)) { if (isWorkerMode(configModule)) {
@@ -110,6 +120,7 @@ async function loadEntrypoints(
const { shutdown } = await expressLoader({ const { shutdown } = await expressLoader({
app: expressApp, app: expressApp,
container,
}) })
await adminLoader({ app: expressApp, configModule, rootDirectory, plugins }) await adminLoader({ app: expressApp, configModule, rootDirectory, plugins })
@@ -123,17 +134,24 @@ async function loadEntrypoints(
} }
export async function initializeContainer( export async function initializeContainer(
rootDirectory: string rootDirectory: string,
options?: {
skipDbConnection?: boolean
}
): Promise<MedusaContainer> { ): Promise<MedusaContainer> {
await configLoader(rootDirectory, "medusa-config") const configDir = await configLoader(rootDirectory, "medusa-config")
await featureFlagsLoader(join(__dirname, "..")) await featureFlagsLoader(join(__dirname, ".."))
const customLogger = configDir.logger ?? defaultLogger
container.register({ container.register({
[ContainerRegistrationKeys.LOGGER]: asValue(logger), [ContainerRegistrationKeys.LOGGER]: asValue(customLogger),
[ContainerRegistrationKeys.REMOTE_QUERY]: asValue(null), [ContainerRegistrationKeys.REMOTE_QUERY]: asValue(null),
}) })
await pgConnectionLoader() if (!options?.skipDbConnection) {
await pgConnectionLoader()
}
return container return container
} }
@@ -151,6 +169,7 @@ export default async ({
const configModule = container.resolve( const configModule = container.resolve(
ContainerRegistrationKeys.CONFIG_MODULE ContainerRegistrationKeys.CONFIG_MODULE
) )
const logger = container.resolve(ContainerRegistrationKeys.LOGGER)
const plugins = await getResolvedPlugins(rootDirectory, configModule, true) const plugins = await getResolvedPlugins(rootDirectory, configModule, true)
mergePluginModules(configModule, plugins) mergePluginModules(configModule, plugins)
@@ -162,7 +181,7 @@ export default async ({
const linksSourcePaths = plugins.map((plugin) => const linksSourcePaths = plugins.map((plugin) =>
join(plugin.resolve, "links") join(plugin.resolve, "links")
) )
await new LinkLoader(linksSourcePaths).load() await new LinkLoader(linksSourcePaths, logger).load()
const { const {
onApplicationStart, onApplicationStart,
@@ -173,7 +192,7 @@ export default async ({
} = await new MedusaAppLoader().load() } = await new MedusaAppLoader().load()
const workflowsSourcePaths = plugins.map((p) => join(p.resolve, "workflows")) const workflowsSourcePaths = plugins.map((p) => join(p.resolve, "workflows"))
const workflowLoader = new WorkflowLoader(workflowsSourcePaths) const workflowLoader = new WorkflowLoader(workflowsSourcePaths, container)
await workflowLoader.load() await workflowLoader.load()
const entrypointsShutdown = await loadEntrypoints( const entrypointsShutdown = await loadEntrypoints(