From e2213448ac9eb93318570fde2807a3036108d44b Mon Sep 17 00:00:00 2001 From: "Carlos R. L. Rodrigues" <37986729+carlos-r-l-rodrigues@users.noreply.github.com> Date: Thu, 28 Aug 2025 10:31:19 -0300 Subject: [PATCH] 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> --- .changeset/seven-pigs-build.md | 9 ++++ packages/core/framework/src/config/config.ts | 23 ++++---- packages/core/framework/src/config/loader.ts | 14 ++--- .../src/feature-flags/feature-flag-loader.ts | 3 +- .../src/http/__fixtures__/server/index.ts | 13 ++--- .../src/http/__tests__/index.spec.ts | 15 +++++- .../core/framework/src/http/express-loader.ts | 12 ++++- packages/core/framework/src/http/router.ts | 54 +++++++++++-------- .../src/jobs/__tests__/register-jobs.spec.ts | 20 +++++-- .../core/framework/src/jobs/job-loader.ts | 11 ++-- .../core/framework/src/links/link-loader.ts | 14 +++-- .../src/subscribers/__tests__/index.spec.ts | 10 +++- .../src/subscribers/subscriber-loader.ts | 28 ++++++---- .../framework/src/utils/resource-loader.ts | 16 ++++-- .../src/workflows/__tests__/index.spec.ts | 17 ++++-- .../src/workflows/workflow-loader.ts | 7 +-- .../core/types/src/common/config-module.ts | 8 ++- packages/core/types/src/logger/index.ts | 29 +++++----- .../common/__tests__/define-config.spec.ts | 10 ++++ .../core/utils/src/common/define-config.ts | 1 + .../src/medusa-test-runner-utils/use-db.ts | 3 +- .../src/commands/__tests__/start.spec.ts | 31 +++++++++-- packages/medusa/src/commands/build.ts | 8 ++- packages/medusa/src/commands/db/create.ts | 17 ++++-- packages/medusa/src/commands/db/generate.ts | 13 ++--- packages/medusa/src/commands/db/migrate.ts | 28 ++++++---- packages/medusa/src/commands/db/rollback.ts | 13 ++--- .../medusa/src/commands/db/run-scripts.ts | 36 ++++++++----- packages/medusa/src/commands/db/setup.ts | 10 +++- packages/medusa/src/commands/db/sync-links.ts | 48 ++++++++++++----- packages/medusa/src/commands/develop.ts | 11 ++-- packages/medusa/src/commands/exec.ts | 14 +++-- packages/medusa/src/commands/plugin/build.ts | 1 + .../medusa/src/commands/plugin/db/generate.ts | 18 +++++-- .../__tests__/plugin-generate.spec.ts | 19 ++++++- .../medusa/src/commands/plugin/develop.ts | 10 ++-- packages/medusa/src/commands/start.ts | 16 ++++-- packages/medusa/src/commands/user.ts | 6 +-- packages/medusa/src/commands/utils/index.ts | 2 +- .../__fixtures__/server/index.ts | 9 ++-- packages/medusa/src/loaders/api.ts | 7 +-- packages/medusa/src/loaders/index.ts | 47 +++++++++++----- 42 files changed, 471 insertions(+), 210 deletions(-) create mode 100644 .changeset/seven-pigs-build.md diff --git a/.changeset/seven-pigs-build.md b/.changeset/seven-pigs-build.md new file mode 100644 index 0000000000..5b89713934 --- /dev/null +++ b/.changeset/seven-pigs-build.md @@ -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 diff --git a/packages/core/framework/src/config/config.ts b/packages/core/framework/src/config/config.ts index f4f70807d7..07fbf7052d 100644 --- a/packages/core/framework/src/config/config.ts +++ b/packages/core/framework/src/config/config.ts @@ -1,6 +1,6 @@ -import { ConfigModule } from "./types" import { deepCopy, isDefined } from "@medusajs/utils" import { logger } from "../logger" +import { ConfigModule } from "./types" export class ConfigManager { /** @@ -124,21 +124,23 @@ export class ConfigManager { /** * Normalizes the project config object and assign the defaults if needed - * @param projectConfig + * @param config * @protected */ protected normalizeProjectConfig( - projectConfig: Partial + config: Partial ): ConfigModule["projectConfig"] { - const outputConfig = deepCopy( - projectConfig - ) as ConfigModule["projectConfig"] + const projConfig = config?.projectConfig ?? {} + const outputConfig = deepCopy(projConfig) as ConfigModule["projectConfig"] 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! @@ -172,9 +174,7 @@ export class ConfigManager { }): ConfigModule { this.#baseDir = baseDir - const normalizedProjectConfig = this.normalizeProjectConfig( - projectConfig.projectConfig ?? {} - ) + const normalizedProjectConfig = this.normalizeProjectConfig(projectConfig) this.#config = { projectConfig: normalizedProjectConfig, @@ -184,6 +184,7 @@ export class ConfigManager { modules: projectConfig.modules ?? {}, featureFlags: projectConfig.featureFlags ?? {}, plugins: projectConfig.plugins ?? [], + logger: projectConfig.logger ?? logger, } return this.#config diff --git a/packages/core/framework/src/config/loader.ts b/packages/core/framework/src/config/loader.ts index 18c555ff84..90292b4672 100644 --- a/packages/core/framework/src/config/loader.ts +++ b/packages/core/framework/src/config/loader.ts @@ -1,14 +1,14 @@ -import { ConfigModule } from "./types" import { ContainerRegistrationKeys, getConfigFile } from "@medusajs/utils" -import { logger } from "../logger" -import { ConfigManager } from "./config" -import { container } from "../container" 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 => { - logger.error(`Error in loading config: ${error.message}`) + defaultLogger.error(`Error in loading config: ${error.message}`) if (error.stack) { - logger.error(error.stack) + defaultLogger.error(error.stack) } process.exit(1) } @@ -28,7 +28,7 @@ container.register( */ export async function configLoader( entryDirectory: string, - configFileName: string + configFileName: string = "medusa-config" ): Promise { const config = await getConfigFile( entryDirectory, diff --git a/packages/core/framework/src/feature-flags/feature-flag-loader.ts b/packages/core/framework/src/feature-flags/feature-flag-loader.ts index 420e5faf3f..4c153ac69a 100644 --- a/packages/core/framework/src/feature-flags/feature-flag-loader.ts +++ b/packages/core/framework/src/feature-flags/feature-flag-loader.ts @@ -10,7 +10,6 @@ import { asFunction } from "awilix" import { normalize } from "path" import { configManager } from "../config" import { container } from "../container" -import { logger } from "../logger" import { FlagSettings } from "./types" container.register( @@ -25,7 +24,7 @@ container.register( export async function featureFlagsLoader( sourcePath?: string ): Promise { - const { featureFlags: projectConfigFlags = {} } = configManager.config + const { featureFlags: projectConfigFlags = {}, logger } = configManager.config if (!sourcePath) { return FeatureFlag diff --git a/packages/core/framework/src/http/__fixtures__/server/index.ts b/packages/core/framework/src/http/__fixtures__/server/index.ts index 5c1f93cd11..7fef285b37 100644 --- a/packages/core/framework/src/http/__fixtures__/server/index.ts +++ b/packages/core/framework/src/http/__fixtures__/server/index.ts @@ -3,17 +3,16 @@ import { ModulesDefinition, registerMedusaModule, } from "@medusajs/modules-sdk" +import { MedusaContainer } from "@medusajs/types" import { ContainerRegistrationKeys, generateJwtToken } from "@medusajs/utils" import { asValue } from "awilix" import express from "express" import querystring from "querystring" import supertest from "supertest" - -import { MedusaContainer } from "@medusajs/types" import { configManager } from "../../../config" import { container } from "../../../container" import { featureFlagsLoader } from "../../../feature-flags" -import { logger } from "../../../logger" +import { logger as defaultLogger } from "../../../logger" import { ApiLoader } from "../../router" import { MedusaRequest } from "../../types" import { config } from "../mocks" @@ -66,11 +65,8 @@ export const createServer = async (rootDir) => { container.register(ContainerRegistrationKeys.PG_CONNECTION, asValue({})) container.register("configModule", asValue(config)) + container.register(ContainerRegistrationKeys.LOGGER, asValue(defaultLogger)) container.register({ - logger: asValue({ - error: () => {}, - info: () => {}, - }), manager: asValue({}), }) @@ -88,7 +84,7 @@ export const createServer = async (rootDir) => { }) await featureFlagsLoader() - await moduleLoader({ container, moduleResolutions, logger }) + await moduleLoader({ container, moduleResolutions, logger: defaultLogger }) app.use((req, res, next) => { ;(req as MedusaRequest).scope = container.createScope() as MedusaContainer @@ -98,6 +94,7 @@ export const createServer = async (rootDir) => { await new ApiLoader({ app, sourceDir: rootDir, + container, }).load() const superRequest = supertest(app) diff --git a/packages/core/framework/src/http/__tests__/index.spec.ts b/packages/core/framework/src/http/__tests__/index.spec.ts index 5aed855a91..5e6e78fda1 100644 --- a/packages/core/framework/src/http/__tests__/index.spec.ts +++ b/packages/core/framework/src/http/__tests__/index.spec.ts @@ -1,5 +1,11 @@ +import { + ContainerRegistrationKeys, + createMedusaContainer, +} from "@medusajs/utils" +import { asValue } from "awilix" import express from "express" import { resolve } from "path" +import { logger as defaultLogger } from "../../logger" import { customersCreateMiddlewareMock, customersCreateMiddlewareValidatorMock, @@ -7,7 +13,7 @@ import { storeGlobalMiddlewareMock, } from "../__fixtures__/mocks" import { createServer } from "../__fixtures__/server" -import { MedusaNextFunction, ApiLoader } from "../index" +import { ApiLoader, MedusaNextFunction } from "../index" jest.setTimeout(30000) @@ -335,9 +341,16 @@ describe("RoutesLoader", function () { __dirname, "../__fixtures__/routers-duplicate-parameter" ) + const container = createMedusaContainer() + container.register( + ContainerRegistrationKeys.LOGGER, + asValue(defaultLogger) + ) + const err = await new ApiLoader({ app, sourceDir: rootDir, + container, }) .load() .catch((e) => e) diff --git a/packages/core/framework/src/http/express-loader.ts b/packages/core/framework/src/http/express-loader.ts index 74c1cafc01..17cf5258f2 100644 --- a/packages/core/framework/src/http/express-loader.ts +++ b/packages/core/framework/src/http/express-loader.ts @@ -1,3 +1,5 @@ +import { MedusaContainer } from "@medusajs/framework/types" +import { ContainerRegistrationKeys } from "@medusajs/framework/utils" import { dynamicImport } from "@medusajs/utils" import createStore from "connect-redis" import cookieParser from "cookie-parser" @@ -7,14 +9,19 @@ import Redis from "ioredis" import morgan from "morgan" import path from "path" import { configManager } from "../config" -import { logger } from "../logger" import { MedusaRequest, MedusaResponse } from "./types" const NOISY_ENDPOINTS_CHUNKS = ["@fs", "@id", "@vite", "@react", "node_modules"] 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 shutdown: () => Promise }> { @@ -25,6 +32,7 @@ export async function expressLoader({ app }: { app: Express }): Promise<{ const IS_DEV = NODE_ENV.startsWith("dev") const isStaging = NODE_ENV === "staging" const isTest = NODE_ENV === "test" + const logger = container.resolve(ContainerRegistrationKeys.LOGGER) let sameSite: string | boolean = false let secure = false diff --git a/packages/core/framework/src/http/router.ts b/packages/core/framework/src/http/router.ts index 0f714eb068..cc7592601f 100644 --- a/packages/core/framework/src/http/router.ts +++ b/packages/core/framework/src/http/router.ts @@ -1,31 +1,31 @@ -import logger from "@medusajs/cli/dist/reporter" +import { ContainerRegistrationKeys, parseCorsOrigins } from "@medusajs/utils" import cors, { CorsOptions } from "cors" -import { parseCorsOrigins } from "@medusajs/utils" -import type { Express, RequestHandler, ErrorRequestHandler } from "express" +import type { ErrorRequestHandler, Express, RequestHandler } from "express" import type { + AdditionalDataValidatorRoute, + BodyParserConfigRoute, + MedusaNextFunction, MedusaRequest, MedusaResponse, + MiddlewareDescriptor, + MiddlewareFunction, MiddlewareVerb, RouteDescriptor, - MiddlewareFunction, - MedusaNextFunction, - MiddlewareDescriptor, - BodyParserConfigRoute, RouteHandler, - AdditionalDataValidatorRoute, } from "./types" -import { RoutesLoader } from "./routes-loader" -import { RoutesFinder } from "./routes-finder" -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 { Logger, MedusaContainer } from "@medusajs/types" +import { configManager } from "../config" import { MiddlewareFileLoader } from "./middleware-file-loader" +import { authenticate, AuthType } from "./middlewares" import { createBodyParserMiddlewaresStack } from "./middlewares/bodyparser" 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 { /** @@ -58,18 +58,23 @@ export class ApiLoader { */ readonly #sourceDirs: string[] + readonly #logger: Logger + constructor({ app, sourceDir, baseRestrictedFields = [], + container, }: { app: Express sourceDir: string | string[] baseRestrictedFields?: string[] + container: MedusaContainer }) { this.#app = app this.#sourceDirs = Array.isArray(sourceDir) ? sourceDir : [sourceDir] this.#assignRestrictedFields(baseRestrictedFields ?? []) + this.#logger = container.resolve(ContainerRegistrationKeys.LOGGER) } /** @@ -105,7 +110,7 @@ export class ApiLoader { route: MiddlewareDescriptor | RouteDescriptor | RouteDescriptor ) { 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 ? ApiLoader.traceRoute(route.handler, { route: route.matcher, @@ -118,7 +123,7 @@ export class ApiLoader { } if (!route.methods) { - logger.debug(`registering global middleware for ${route.matcher}`) + this.#logger.debug(`registering global middleware for ${route.matcher}`) const handler = ApiLoader.traceMiddleware ? (ApiLoader.traceMiddleware(route.handler, { route: route.matcher, @@ -133,7 +138,9 @@ export class ApiLoader { ? route.methods : [route.methods] methods.forEach((method) => { - logger.debug(`registering route middleware ${method} ${route.matcher}`) + this.#logger.debug( + `registering route middleware ${method} ${route.matcher}` + ) const handler = ApiLoader.traceMiddleware ? (ApiLoader.traceMiddleware(wrapHandler(route.handler), { route: route.matcher, @@ -192,6 +199,7 @@ export class ApiLoader { | "shouldAppendStoreCors", corsOptions: CorsOptions ) { + const logger = this.#logger const corsFn = cors(corsOptions) const corsMiddleware: RequestHandler = function corsMiddleware( req, @@ -234,6 +242,7 @@ export class ApiLoader { authType: AuthType | AuthType[], options?: { allowUnauthenticated?: boolean; allowUnregistered?: boolean } ) { + const logger = this.#logger logger.debug(`Registering auth middleware for prefix ${namespace}`) const originalFn = authenticate(actorType, authType, options) @@ -273,7 +282,9 @@ export class ApiLoader { namespace: string, routesFinder: RoutesFinder ): void { - logger.debug(`Registering bodyparser middleware for prefix ${namespace}`) + this.#logger.debug( + `Registering bodyparser middleware for prefix ${namespace}` + ) this.#app.use( namespace, createBodyParserMiddlewaresStack( @@ -292,6 +303,7 @@ export class ApiLoader { namespace: string, routesFinder: RoutesFinder ) { + const logger = this.#logger logger.debug( `Registering assignAdditionalDataValidator middleware for prefix ${namespace}` ) @@ -329,7 +341,7 @@ export class ApiLoader { * a `x-publishable-key` header */ #applyStorePublishableKeyMiddleware(namespace: string) { - logger.debug( + this.#logger.debug( `Registering publishable key middleware for namespace ${namespace}` ) let middleware = ApiLoader.traceMiddleware diff --git a/packages/core/framework/src/jobs/__tests__/register-jobs.spec.ts b/packages/core/framework/src/jobs/__tests__/register-jobs.spec.ts index 24a8612d2f..cb3ab3dd69 100644 --- a/packages/core/framework/src/jobs/__tests__/register-jobs.spec.ts +++ b/packages/core/framework/src/jobs/__tests__/register-jobs.spec.ts @@ -1,5 +1,11 @@ -import { join } from "path" 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 { JobLoader } from "../job-loader" @@ -11,8 +17,12 @@ describe("register jobs", () => { }) it("should registers jobs from plugins", async () => { + const container = createMedusaContainer() + container.register(ContainerRegistrationKeys.LOGGER, asValue(logger)) + const jobLoader: JobLoader = new JobLoader( - join(__dirname, "../__fixtures__/plugin/jobs") + join(__dirname, "../__fixtures__/plugin/jobs"), + container ) await jobLoader.load() const workflow = WorkflowManager.getWorkflow("job-summarize-orders") @@ -24,8 +34,12 @@ describe("register jobs", () => { }) it("should not load non js/ts files", async () => { + const container = createMedusaContainer() + container.register(ContainerRegistrationKeys.LOGGER, asValue(logger)) + 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() const workflow = WorkflowManager.getWorkflow("job-summarize-orders") diff --git a/packages/core/framework/src/jobs/job-loader.ts b/packages/core/framework/src/jobs/job-loader.ts index 228a7b4141..20b79a4d21 100644 --- a/packages/core/framework/src/jobs/job-loader.ts +++ b/packages/core/framework/src/jobs/job-loader.ts @@ -6,7 +6,6 @@ import { createWorkflow, StepResponse, } from "@medusajs/workflows-sdk" -import { logger } from "../logger" import { ResourceLoader } from "../utils/resource-loader" type CronJobConfig = { @@ -20,8 +19,8 @@ type CronJobHandler = (container: MedusaContainer) => Promise export class JobLoader extends ResourceLoader { protected resourceName = "job" - constructor(sourceDir: string | string[]) { - super(sourceDir) + constructor(sourceDir: string | string[], container: MedusaContainer) { + super(sourceDir, container) } protected async onFileLoaded( @@ -36,7 +35,7 @@ export class JobLoader extends ResourceLoader { } this.validateConfig(fileExports.config) - logger.debug(`Registering job from ${path}.`) + this.logger.debug(`Registering job from ${path}.`) this.register({ config: fileExports.config, handler: fileExports.default, @@ -96,7 +95,7 @@ export class JobLoader extends ResourceLoader { const res = await handler(container) return new StepResponse(res, res) } catch (error) { - logger.error( + this.logger.error( `Scheduled job ${config.name} failed with error: ${error.message}` ) throw error @@ -125,6 +124,6 @@ export class JobLoader extends ResourceLoader { async load() { await super.discoverResources() - logger.debug(`Jobs registered.`) + this.logger.debug(`Jobs registered.`) } } diff --git a/packages/core/framework/src/links/link-loader.ts b/packages/core/framework/src/links/link-loader.ts index 1f46f7587b..bb37b6247c 100644 --- a/packages/core/framework/src/links/link-loader.ts +++ b/packages/core/framework/src/links/link-loader.ts @@ -1,8 +1,9 @@ +import { Logger } from "@medusajs/types" import { dynamicImport, promiseAll, readDirRecursive } from "@medusajs/utils" import { Dirent } from "fs" import { access } from "fs/promises" import { join } from "path" -import { logger } from "../logger" +import { logger as defaultLogger } from "../logger" 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.#logger = logger ?? defaultLogger } /** @@ -40,7 +44,7 @@ export class LinkLoader { try { await access(sourcePath) } catch { - logger.info(`No link to load from ${sourcePath}. skipped.`) + this.#logger.info(`No link to load from ${sourcePath}. skipped.`) return } @@ -52,7 +56,7 @@ export class LinkLoader { ) }) - logger.debug(`Registering links from ${sourcePath}.`) + this.#logger.debug(`Registering links from ${sourcePath}.`) return await promiseAll( fileEntries.map(async (entry: Dirent) => { @@ -65,6 +69,6 @@ export class LinkLoader { await promiseAll(promises) - logger.debug(`Links registered.`) + this.#logger.debug(`Links registered.`) } } diff --git a/packages/core/framework/src/subscribers/__tests__/index.spec.ts b/packages/core/framework/src/subscribers/__tests__/index.spec.ts index ef242040ad..16e96c37e1 100644 --- a/packages/core/framework/src/subscribers/__tests__/index.spec.ts +++ b/packages/core/framework/src/subscribers/__tests__/index.spec.ts @@ -1,7 +1,8 @@ -import { Modules } from "@medusajs/utils" +import { ContainerRegistrationKeys, Modules } from "@medusajs/utils" import { asValue } from "awilix" import { join } from "path" import { container } from "../../container" +import { logger } from "../../logger" import { eventBusServiceMock } from "../__mocks__" import { SubscriberLoader } from "../subscriber-loader" @@ -18,8 +19,13 @@ describe("SubscriberLoader", () => { beforeAll(async () => { 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) { registeredPaths = [...registeredPaths, ...paths] diff --git a/packages/core/framework/src/subscribers/subscriber-loader.ts b/packages/core/framework/src/subscribers/subscriber-loader.ts index 75cce22c9b..daa18fd8ed 100644 --- a/packages/core/framework/src/subscribers/subscriber-loader.ts +++ b/packages/core/framework/src/subscribers/subscriber-loader.ts @@ -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 { parse } from "path" - import { configManager } from "../config" import { container } from "../container" -import { logger } from "../logger" import { ResourceLoader } from "../utils/resource-loader" import { SubscriberArgs, SubscriberConfig } from "./types" @@ -32,9 +35,10 @@ export class SubscriberLoader extends ResourceLoader { constructor( sourceDir: string | string[], - options: Record = {} + options: Record = {}, + container: MedusaContainer ) { - super(sourceDir) + super(sourceDir, container) this.#pluginOptions = options } @@ -48,7 +52,7 @@ export class SubscriberLoader extends ResourceLoader { const isValid = this.validateSubscriber(fileExports, path) - logger.debug(`Registering subscribers from ${path}.`) + this.logger.debug(`Registering subscribers from ${path}.`) if (!isValid) { return @@ -73,7 +77,7 @@ export class SubscriberLoader extends ResourceLoader { /** * 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 } @@ -83,7 +87,9 @@ export class SubscriberLoader extends ResourceLoader { /** * 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 } @@ -97,7 +103,7 @@ export class SubscriberLoader extends ResourceLoader { `The subscriber in ${path} is missing an event in the config.` ) } else { - logger.warn( + this.logger.warn( `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 */ - 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.` ) 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 diff --git a/packages/core/framework/src/utils/resource-loader.ts b/packages/core/framework/src/utils/resource-loader.ts index 57ca74f837..b975a7e1af 100644 --- a/packages/core/framework/src/utils/resource-loader.ts +++ b/packages/core/framework/src/utils/resource-loader.ts @@ -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 { access } from "fs/promises" import { join, parse } from "path" -import { logger } from "../logger" export abstract class ResourceLoader { /** @@ -22,8 +27,11 @@ export abstract class ResourceLoader { */ #excludes: RegExp[] = [/^_[^/\\]*(\.[^/\\]+)?$/] - constructor(sourceDir: string | string[]) { + protected logger: Logger + + constructor(sourceDir: string | string[], container: MedusaContainer) { this.#sourceDir = sourceDir + this.logger = container.resolve(ContainerRegistrationKeys.LOGGER) } /** @@ -61,7 +69,7 @@ export abstract class ResourceLoader { try { await access(sourcePath) } catch { - logger.info( + this.logger.info( `No ${this.resourceName} to load from ${sourcePath}. skipped.` ) return diff --git a/packages/core/framework/src/workflows/__tests__/index.spec.ts b/packages/core/framework/src/workflows/__tests__/index.spec.ts index 78c967154c..4a3e91ea5b 100644 --- a/packages/core/framework/src/workflows/__tests__/index.spec.ts +++ b/packages/core/framework/src/workflows/__tests__/index.spec.ts @@ -1,14 +1,23 @@ -import { join } from "path" -import { WorkflowLoader } from "../workflow-loader" 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 { orderWorkflowId } from "../__fixtures__/workflows/order-notifier" +import { WorkflowLoader } from "../workflow-loader" describe("WorkflowLoader", () => { const rootDir = join(__dirname, "../__fixtures__", "workflows") 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 () => { diff --git a/packages/core/framework/src/workflows/workflow-loader.ts b/packages/core/framework/src/workflows/workflow-loader.ts index 99962839af..53cb3677bc 100644 --- a/packages/core/framework/src/workflows/workflow-loader.ts +++ b/packages/core/framework/src/workflows/workflow-loader.ts @@ -1,3 +1,4 @@ +import { MedusaContainer } from "@medusajs/types" import { isFileSkipped } from "@medusajs/utils" import { MedusaWorkflow } from "@medusajs/workflows-sdk" import { logger } from "../logger" @@ -6,8 +7,8 @@ import { ResourceLoader } from "../utils/resource-loader" export class WorkflowLoader extends ResourceLoader { protected resourceName = "workflow" - constructor(sourceDir: string | string[]) { - super(sourceDir) + constructor(sourceDir: string | string[], container: MedusaContainer) { + super(sourceDir, container) } protected async onFileLoaded( @@ -35,6 +36,6 @@ export class WorkflowLoader extends ResourceLoader { async load() { await super.discoverResources() - logger.debug(`Workflows registered.`) + this.logger.debug(`Workflows registered.`) } } diff --git a/packages/core/types/src/common/config-module.ts b/packages/core/types/src/common/config-module.ts index 69f9a79eca..a648dd7891 100644 --- a/packages/core/types/src/common/config-module.ts +++ b/packages/core/types/src/common/config-module.ts @@ -8,6 +8,7 @@ import type { RedisOptions } from "ioredis" import { ConnectionOptions } from "node:tls" // @ts-ignore import type { InlineConfig } from "vite" +import type { Logger } from "../logger" /** * @interface @@ -919,7 +920,7 @@ export type ProjectConfigOptions = { */ 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 @@ -1047,6 +1048,11 @@ export type ConfigModule = { * ::: */ featureFlags: Record> + + /** + * The Logger instance to be used by the application. + */ + logger?: Logger } type InternalModuleDeclarationOverride = InternalModuleDeclaration & { diff --git a/packages/core/types/src/logger/index.ts b/packages/core/types/src/logger/index.ts index fdb30fa5e5..6918cd18be 100644 --- a/packages/core/types/src/logger/index.ts +++ b/packages/core/types/src/logger/index.ts @@ -1,15 +1,18 @@ export interface Logger { - panic: (data: any) => void - shouldLog: (level: string) => boolean - setLogLevel: (level: string) => void - unsetLogLevel: () => void - activity: (message: string, config?: Record) => string - progress: (activityId: string, message: string) => void - error: (messageOrError: string | Error, error?: Error) => void - failure: (activityId: string, message: string) => Record | null - success: (activityId: string, message: string) => Record | null - debug: (message: string) => void - info: (message: string) => void - warn: (message: string) => void - log: (...args: any[]) => void + panic(data: unknown): void + shouldLog(level: string): boolean + setLogLevel(level: string): void + unsetLogLevel(): void + activity(message: string, config?: unknown): string + progress(activityId: string, message: string): void + error(messageOrError: string | Error, error?: Error): void + failure(activityId: string, message: string): unknown + success(activityId: string, message: string): Record + silly(message: string): void + debug(message: string): void + verbose(message: string): void + http(message: string): void + info(message: string): void + warn(message: string): void + log(...args: unknown[]): void } diff --git a/packages/core/utils/src/common/__tests__/define-config.spec.ts b/packages/core/utils/src/common/__tests__/define-config.spec.ts index 14c55c3b39..2276383d02 100644 --- a/packages/core/utils/src/common/__tests__/define-config.spec.ts +++ b/packages/core/utils/src/common/__tests__/define-config.spec.ts @@ -10,6 +10,7 @@ describe("defineConfig", function () { "path": "/app", }, "featureFlags": {}, + "logger": undefined, "modules": { "api_key": { "resolve": "@medusajs/medusa/api-key", @@ -179,6 +180,7 @@ describe("defineConfig", function () { "path": "/app", }, "featureFlags": {}, + "logger": undefined, "modules": { "GithubModuleService": { "resolve": "./modules/github", @@ -354,6 +356,7 @@ describe("defineConfig", function () { "path": "/app", }, "featureFlags": {}, + "logger": undefined, "modules": { "GithubModuleService": { "options": { @@ -535,6 +538,7 @@ describe("defineConfig", function () { "path": "/app", }, "featureFlags": {}, + "logger": undefined, "modules": { "GithubModuleServiceOverride": { "options": { @@ -712,6 +716,7 @@ describe("defineConfig", function () { "path": "/app", }, "featureFlags": {}, + "logger": undefined, "modules": { "api_key": { "resolve": "@medusajs/medusa/api-key", @@ -884,6 +889,7 @@ describe("defineConfig", function () { "path": "/app", }, "featureFlags": {}, + "logger": undefined, "modules": { "api_key": { "resolve": "@medusajs/medusa/api-key", @@ -1058,6 +1064,7 @@ describe("defineConfig", function () { "path": "/app", }, "featureFlags": {}, + "logger": undefined, "modules": { "api_key": { "resolve": "@medusajs/medusa/api-key", @@ -1265,6 +1272,7 @@ describe("defineConfig", function () { "path": "/app", }, "featureFlags": {}, + "logger": undefined, "modules": { "api_key": { "resolve": "@medusajs/medusa/api-key", @@ -1488,6 +1496,7 @@ describe("defineConfig", function () { "path": "/app", }, "featureFlags": {}, + "logger": undefined, "modules": { "api_key": { "resolve": "@medusajs/medusa/api-key", @@ -1791,6 +1800,7 @@ describe("defineConfig", function () { "path": "/app", }, "featureFlags": {}, + "logger": undefined, "modules": { "api_key": { "resolve": "@medusajs/medusa/api-key", diff --git a/packages/core/utils/src/common/define-config.ts b/packages/core/utils/src/common/define-config.ts index 4e277a6921..4e77f79101 100644 --- a/packages/core/utils/src/common/define-config.ts +++ b/packages/core/utils/src/common/define-config.ts @@ -56,6 +56,7 @@ export function defineConfig(config: InputConfig = {}): ConfigModule { featureFlags: (config.featureFlags ?? {}) as ConfigModule["featureFlags"], admin: adminConfig, modules: modules, + logger: config.logger, plugins, } } diff --git a/packages/medusa-test-utils/src/medusa-test-runner-utils/use-db.ts b/packages/medusa-test-utils/src/medusa-test-runner-utils/use-db.ts index af15889769..d0b8bd5f84 100644 --- a/packages/medusa-test-utils/src/medusa-test-runner-utils/use-db.ts +++ b/packages/medusa-test-utils/src/medusa-test-runner-utils/use-db.ts @@ -62,7 +62,8 @@ async function loadCustomLinks(directory: string, container: MedusaContainer) { const linksSourcePaths = plugins.map((plugin) => join(plugin.resolve, "links") ) + const logger = container.resolve(ContainerRegistrationKeys.LOGGER) const { LinkLoader } = await import("@medusajs/framework") - await new LinkLoader(linksSourcePaths).load() + await new LinkLoader(linksSourcePaths, logger).load() } diff --git a/packages/medusa/src/commands/__tests__/start.spec.ts b/packages/medusa/src/commands/__tests__/start.spec.ts index 9bb86367a3..4186a08358 100644 --- a/packages/medusa/src/commands/__tests__/start.spec.ts +++ b/packages/medusa/src/commands/__tests__/start.spec.ts @@ -1,13 +1,36 @@ -import { registerInstrumentation } from "../start" 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 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", () => { beforeEach(() => { jest.clearAllMocks() + jest.doMock("@medusajs/framework/utils", () => ({ + ...jest.requireActual("@medusajs/framework/utils"), + createMedusaContainer: jest.fn(() => ({ + resolve: jest.fn(() => logger), + })), + })) }) describe("registerInstrumentation", () => { @@ -32,7 +55,7 @@ describe("start", () => { "exists", "" as never ) - const loggerSpy = jest.spyOn(logger.logger, "info", "" as never) + const loggerSpy = jest.spyOn(logger, "info", "" as never) await registerInstrumentation( path.join(__dirname, "../__fixtures__/instrumentation-no-register") diff --git a/packages/medusa/src/commands/build.ts b/packages/medusa/src/commands/build.ts index 178b7c5edd..2b84fee600 100644 --- a/packages/medusa/src/commands/build.ts +++ b/packages/medusa/src/commands/build.ts @@ -1,5 +1,6 @@ -import { logger } from "@medusajs/framework/logger" import { Compiler } from "@medusajs/framework/build-tools" +import { ContainerRegistrationKeys } from "@medusajs/framework/utils" +import { initializeContainer } from "../loaders" export default async function build({ directory, @@ -8,6 +9,11 @@ export default async function build({ directory: string adminOnly: boolean }) { + const container = await initializeContainer(directory, { + skipDbConnection: true, + }) + const logger = container.resolve(ContainerRegistrationKeys.LOGGER) + logger.info("Starting build...") const compiler = new Compiler(directory, logger) diff --git a/packages/medusa/src/commands/db/create.ts b/packages/medusa/src/commands/db/create.ts index 5dd2d6b48a..4ad7a24a7b 100644 --- a/packages/medusa/src/commands/db/create.ts +++ b/packages/medusa/src/commands/db/create.ts @@ -1,14 +1,16 @@ -import slugify from "slugify" -import { basename } from "path" import input from "@inquirer/input" -import { logger } from "@medusajs/framework/logger" +import type { Logger } from "@medusajs/framework/types" import { + ContainerRegistrationKeys, createClient, createDb, dbExists, EnvEditor, parseConnectionString, } from "@medusajs/framework/utils" +import { basename } from "path" +import slugify from "slugify" +import { initializeContainer } from "../../loaders" async function connectClient(client: ReturnType) { try { @@ -27,10 +29,12 @@ export async function dbCreate({ db, directory, interactive, + logger, }: { db: string | undefined directory: string interactive: boolean + logger: Logger }): Promise { let dbName = db @@ -155,8 +159,13 @@ export async function dbCreate({ } const main = async function ({ directory, interactive, db }) { + const container = await initializeContainer(directory, { + skipDbConnection: true, + }) + const logger = container.resolve(ContainerRegistrationKeys.LOGGER) + try { - const created = await dbCreate({ directory, interactive, db }) + const created = await dbCreate({ directory, interactive, db, logger }) process.exit(created ? 0 : 1) } catch (error) { if (error.name === "ExitPromptError") { diff --git a/packages/medusa/src/commands/db/generate.ts b/packages/medusa/src/commands/db/generate.ts index 73ab736cac..7ba2262c31 100644 --- a/packages/medusa/src/commands/db/generate.ts +++ b/packages/medusa/src/commands/db/generate.ts @@ -1,6 +1,5 @@ import { MedusaAppLoader } from "@medusajs/framework" import { LinkLoader } from "@medusajs/framework/links" -import { logger } from "@medusajs/framework/logger" import { ContainerRegistrationKeys, getResolvedPlugins, @@ -8,18 +7,20 @@ import { mergePluginModules, } from "@medusajs/framework/utils" import { join } from "path" - import { initializeContainer } from "../../loaders" import { ensureDbExists } from "../utils" const TERMINAL_SIZE = process.stdout.columns const main = async function ({ directory, modules }) { + const container = await initializeContainer(directory) + const logger = container.resolve(ContainerRegistrationKeys.LOGGER) + try { /** * Setup */ - const container = await initializeContainer(directory) + await ensureDbExists(container) const medusaAppLoader = new MedusaAppLoader() @@ -33,7 +34,7 @@ const main = async function ({ directory, modules }) { const linksSourcePaths = plugins.map((plugin) => join(plugin.resolve, "links") ) - await new LinkLoader(linksSourcePaths).load() + await new LinkLoader(linksSourcePaths, logger).load() /** * Generating migrations @@ -45,12 +46,12 @@ const main = async function ({ directory, modules }) { action: "generate", }) - console.log(new Array(TERMINAL_SIZE).join("-")) + logger.log(new Array(TERMINAL_SIZE).join("-")) logger.info("Migrations generated") process.exit() } 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) { logger.error(error.message) const modulesList = error.allModules.map( diff --git a/packages/medusa/src/commands/db/migrate.ts b/packages/medusa/src/commands/db/migrate.ts index fffc189319..59a1af5294 100644 --- a/packages/medusa/src/commands/db/migrate.ts +++ b/packages/medusa/src/commands/db/migrate.ts @@ -1,18 +1,17 @@ import { MEDUSA_CLI_PATH, MedusaAppLoader } from "@medusajs/framework" import { LinkLoader } from "@medusajs/framework/links" -import { logger } from "@medusajs/framework/logger" import { ContainerRegistrationKeys, getResolvedPlugins, mergePluginModules, } from "@medusajs/framework/utils" -import { join } from "path" - +import { Logger, MedusaContainer } from "@medusajs/types" import { fork } from "child_process" -import path from "path" +import path, { join } from "path" import { initializeContainer } from "../../loaders" import { ensureDbExists } from "../utils" import { syncLinks } from "./sync-links" + const TERMINAL_SIZE = process.stdout.columns const cliPath = path.resolve(MEDUSA_CLI_PATH, "..", "..", "cli.js") @@ -27,17 +26,21 @@ export async function migrate({ skipScripts, executeAllLinks, executeSafeLinks, + logger, + container, }: { directory: string skipLinks: boolean skipScripts: boolean executeAllLinks: boolean executeSafeLinks: boolean + logger: Logger + container: MedusaContainer }): Promise { /** * Setup */ - const container = await initializeContainer(directory) + await ensureDbExists(container) const medusaAppLoader = new MedusaAppLoader() @@ -51,7 +54,7 @@ export async function migrate({ const linksSourcePaths = plugins.map((plugin) => join(plugin.resolve, "links") ) - await new LinkLoader(linksSourcePaths).load() + await new LinkLoader(linksSourcePaths, logger).load() /** * Run migrations @@ -60,17 +63,19 @@ export async function migrate({ await medusaAppLoader.runModulesMigrations({ action: "run", }) - console.log(new Array(TERMINAL_SIZE).join("-")) + logger.log(new Array(TERMINAL_SIZE).join("-")) logger.info("Migrations completed") /** * Sync links */ if (!skipLinks) { - console.log(new Array(TERMINAL_SIZE).join("-")) + logger.log(new Array(TERMINAL_SIZE).join("-")) await syncLinks(medusaAppLoader, { executeAll: executeAllLinks, executeSafe: executeSafeLinks, + directory, + container, }) } @@ -78,7 +83,7 @@ export async function migrate({ /** * Run migration scripts */ - console.log(new Array(TERMINAL_SIZE).join("-")) + logger.log(new Array(TERMINAL_SIZE).join("-")) const childProcess = fork(cliPath, ["db:migrate:scripts"], { cwd: directory, env: process.env, @@ -104,6 +109,9 @@ const main = async function ({ executeAllLinks, executeSafeLinks, }) { + const container = await initializeContainer(directory) + const logger = container.resolve(ContainerRegistrationKeys.LOGGER) + try { const migrated = await migrate({ directory, @@ -111,6 +119,8 @@ const main = async function ({ skipScripts, executeAllLinks, executeSafeLinks, + logger, + container, }) process.exit(migrated ? 0 : 1) } catch (error) { diff --git a/packages/medusa/src/commands/db/rollback.ts b/packages/medusa/src/commands/db/rollback.ts index a43d95c774..4c94a861e8 100644 --- a/packages/medusa/src/commands/db/rollback.ts +++ b/packages/medusa/src/commands/db/rollback.ts @@ -1,6 +1,5 @@ import { MedusaAppLoader } from "@medusajs/framework" import { LinkLoader } from "@medusajs/framework/links" -import { logger } from "@medusajs/framework/logger" import { ContainerRegistrationKeys, getResolvedPlugins, @@ -8,18 +7,20 @@ import { mergePluginModules, } from "@medusajs/framework/utils" import { join } from "path" - import { initializeContainer } from "../../loaders" import { ensureDbExists } from "../utils" const TERMINAL_SIZE = process.stdout.columns const main = async function ({ directory, modules }) { + const container = await initializeContainer(directory) + const logger = container.resolve(ContainerRegistrationKeys.LOGGER) + try { /** * Setup */ - const container = await initializeContainer(directory) + await ensureDbExists(container) const medusaAppLoader = new MedusaAppLoader() @@ -33,7 +34,7 @@ const main = async function ({ directory, modules }) { const linksSourcePaths = plugins.map((plugin) => join(plugin.resolve, "links") ) - await new LinkLoader(linksSourcePaths).load() + await new LinkLoader(linksSourcePaths, logger).load() /** * Reverting migrations @@ -43,12 +44,12 @@ const main = async function ({ directory, modules }) { moduleNames: modules, action: "revert", }) - console.log(new Array(TERMINAL_SIZE).join("-")) + logger.log(new Array(TERMINAL_SIZE).join("-")) logger.info("Migrations reverted") process.exit() } 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) { logger.error(error.message) const modulesList = error.allModules.map( diff --git a/packages/medusa/src/commands/db/run-scripts.ts b/packages/medusa/src/commands/db/run-scripts.ts index f443be0f5d..e4d38cd78b 100644 --- a/packages/medusa/src/commands/db/run-scripts.ts +++ b/packages/medusa/src/commands/db/run-scripts.ts @@ -1,6 +1,5 @@ import { MedusaAppLoader } from "@medusajs/framework" import { LinkLoader } from "@medusajs/framework/links" -import { logger } from "@medusajs/framework/logger" import { MigrationScriptsMigrator } from "@medusajs/framework/migrations" import { ContainerRegistrationKeys, @@ -10,7 +9,7 @@ import { import { dirname, join } from "path" 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 { ensureDbExists } from "../utils" @@ -22,20 +21,23 @@ const TERMINAL_SIZE = process.stdout.columns */ export async function runMigrationScripts({ directory, + container, + logger, }: { directory: string + container: MedusaContainer + logger: Logger }): Promise { let onApplicationPrepareShutdown: () => Promise = async () => Promise.resolve() let onApplicationShutdown: () => Promise = async () => Promise.resolve() - let container_: MedusaContainer + let plugins: PluginDetails[] try { - container_ = await initializeContainer(directory) - await ensureDbExists(container_) + await ensureDbExists(container) - const configModule = container_.resolve( + const configModule = container.resolve( ContainerRegistrationKeys.CONFIG_MODULE ) @@ -43,7 +45,7 @@ export async function runMigrationScripts({ mergePluginModules(configModule, plugins) - const resources = await loadResources(plugins) + const resources = await loadResources(plugins, logger) onApplicationPrepareShutdown = resources.onApplicationPrepareShutdown onApplicationShutdown = resources.onApplicationShutdown @@ -52,7 +54,7 @@ export async function runMigrationScripts({ ...plugins.map((plugin) => join(plugin.resolve, "migration-scripts")), ] - const migrator = new MigrationScriptsMigrator({ container: container_ }) + const migrator = new MigrationScriptsMigrator({ container: container }) await migrator.ensureMigrationsTable() const pendingScripts = await migrator.getPendingMigrations( scriptsSourcePaths @@ -63,15 +65,15 @@ export async function runMigrationScripts({ 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(`${pendingScripts.join("\n")}`) - console.log(new Array(TERMINAL_SIZE).join("-")) + logger.log(new Array(TERMINAL_SIZE).join("-")) logger.info("Running migration scripts...") await migrator.run(scriptsSourcePaths) - console.log(new Array(TERMINAL_SIZE).join("-")) + logger.log(new Array(TERMINAL_SIZE).join("-")) logger.info("Migration scripts completed") 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 onApplicationShutdown: () => Promise }> { @@ -97,7 +102,7 @@ async function loadResources(plugins: any): Promise<{ const linksSourcePaths = plugins.map((plugin) => join(plugin.resolve, "links") ) - await new LinkLoader(linksSourcePaths).load() + await new LinkLoader(linksSourcePaths, logger).load() const medusaAppResources = await new MedusaAppLoader().load() const onApplicationPrepareShutdown = @@ -117,9 +122,14 @@ const main = async function ({ directory: string container?: MedusaContainer }) { + const container = await initializeContainer(directory) + const logger = container.resolve(ContainerRegistrationKeys.LOGGER) + try { const migrated = await runMigrationScripts({ directory, + container: container, + logger, }) process.exit(migrated ? 0 : 1) } catch (error) { diff --git a/packages/medusa/src/commands/db/setup.ts b/packages/medusa/src/commands/db/setup.ts index 9a8c837a36..69e9741c4e 100644 --- a/packages/medusa/src/commands/db/setup.ts +++ b/packages/medusa/src/commands/db/setup.ts @@ -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 { migrate } from "./migrate" @@ -11,8 +12,11 @@ const main = async function ({ executeAllLinks, executeSafeLinks, }) { + const container = await initializeContainer(directory) + const logger = container.resolve(ContainerRegistrationKeys.LOGGER) + try { - const created = await dbCreate({ directory, interactive, db }) + const created = await dbCreate({ directory, interactive, db, logger }) if (!created) { process.exit(1) } @@ -23,6 +27,8 @@ const main = async function ({ skipScripts, executeAllLinks, executeSafeLinks, + logger, + container, }) process.exit(migrated ? 0 : 1) diff --git a/packages/medusa/src/commands/db/sync-links.ts b/packages/medusa/src/commands/db/sync-links.ts index a1be09f985..825a54248c 100644 --- a/packages/medusa/src/commands/db/sync-links.ts +++ b/packages/medusa/src/commands/db/sync-links.ts @@ -1,8 +1,11 @@ import checkbox from "@inquirer/checkbox" import { MedusaAppLoader } from "@medusajs/framework" import { LinkLoader } from "@medusajs/framework/links" -import { logger } from "@medusajs/framework/logger" -import { LinkMigrationsPlannerAction } from "@medusajs/framework/types" +import { + LinkMigrationsPlannerAction, + Logger, + MedusaContainer, +} from "@medusajs/framework/types" import { ContainerRegistrationKeys, getResolvedPlugins, @@ -52,13 +55,14 @@ function buildLinkDescription(action: LinkMigrationsPlannerAction) { */ function logActions( title: string, - actionsOrContext: LinkMigrationsPlannerAction[] + actionsOrContext: LinkMigrationsPlannerAction[], + logger: Logger ) { const actionsList = actionsOrContext .map((action) => ` - ${buildLinkDescription(action)}`) .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( 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({ message: "Select tables to act upon", @@ -95,11 +100,17 @@ export async function syncLinks( { executeAll, executeSafe, + directory, + container, }: { executeSafe: boolean executeAll: boolean + directory: string + container: MedusaContainer } ) { + const logger = container.resolve(ContainerRegistrationKeys.LOGGER) + const planner = await medusaAppLoader.getLinksExecutionPlanner() logger.info("Syncing links...") @@ -120,7 +131,8 @@ export async function syncLinks( `Select the tables to ${chalk.red( "DELETE" )}. 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( "UPDATE" )}. The following links have been updated`, - groupActionPlan.notify + groupActionPlan.notify, + logger ) } @@ -163,13 +176,13 @@ export async function syncLinks( await planner.executePlan(actionsToExecute) if (toCreate.length) { - logActions("Created following links tables", toCreate) + logActions("Created following links tables", toCreate, logger) } if (toUpdate.length) { - logActions("Updated following links tables", toUpdate) + logActions("Updated following links tables", toUpdate, logger) } if (toDelete.length) { - logActions("Deleted following links tables", toDelete) + logActions("Deleted following links tables", toDelete, logger) } if (actionsToExecute.length) { @@ -180,8 +193,10 @@ export async function syncLinks( } const main = async function ({ directory, executeSafe, executeAll }) { + const container = await initializeContainer(directory) + const logger = container.resolve(ContainerRegistrationKeys.LOGGER) + try { - const container = await initializeContainer(directory) await ensureDbExists(container) const configModule = container.resolve( @@ -196,9 +211,14 @@ const main = async function ({ directory, executeSafe, executeAll }) { const linksSourcePaths = plugins.map((plugin) => 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() } catch (error) { logger.error(error) diff --git a/packages/medusa/src/commands/develop.ts b/packages/medusa/src/commands/develop.ts index f87b44f652..6425b6e4f8 100644 --- a/packages/medusa/src/commands/develop.ts +++ b/packages/medusa/src/commands/develop.ts @@ -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 { ChildProcess, execSync, fork } from "child_process" import chokidar, { FSWatcher } from "chokidar" -import { Store } from "@medusajs/telemetry" import { EOL } from "os" import path from "path" - -import { logger } from "@medusajs/framework/logger" -import { MEDUSA_CLI_PATH } from "@medusajs/framework" +import { initializeContainer } from "../loaders" const defaultConfig = { padding: 5, @@ -15,6 +15,9 @@ const defaultConfig = { } as boxen.Options export default async function ({ types, directory }) { + const container = await initializeContainer(directory) + const logger = container.resolve(ContainerRegistrationKeys.LOGGER) + const args = process.argv const argv = diff --git a/packages/medusa/src/commands/exec.ts b/packages/medusa/src/commands/exec.ts index 1bc22e16d5..b5b7d4cdc6 100644 --- a/packages/medusa/src/commands/exec.ts +++ b/packages/medusa/src/commands/exec.ts @@ -1,10 +1,13 @@ -import { logger } from "@medusajs/framework/logger" 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 { existsSync } from "fs" import path from "path" -import loaders from "../loaders" +import loaders, { initializeContainer } from "../loaders" type Options = { file: string @@ -12,6 +15,11 @@ type 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}...`) const app = express() const directory = process.cwd() diff --git a/packages/medusa/src/commands/plugin/build.ts b/packages/medusa/src/commands/plugin/build.ts index 9680388cca..e9628ebc7f 100644 --- a/packages/medusa/src/commands/plugin/build.ts +++ b/packages/medusa/src/commands/plugin/build.ts @@ -1,5 +1,6 @@ import { Compiler } from "@medusajs/framework/build-tools" import { logger } from "@medusajs/framework/logger" + export default async function build({ directory }: { directory: string }) { logger.info("Starting build...") const compiler = new Compiler(directory, logger) diff --git a/packages/medusa/src/commands/plugin/db/generate.ts b/packages/medusa/src/commands/plugin/db/generate.ts index fdb757b389..534f76e3ef 100644 --- a/packages/medusa/src/commands/plugin/db/generate.ts +++ b/packages/medusa/src/commands/plugin/db/generate.ts @@ -1,5 +1,6 @@ -import { logger } from "@medusajs/framework/logger" +import type { Logger } from "@medusajs/framework/types" import { + ContainerRegistrationKeys, defineMikroOrmCliConfig, DmlEntity, dynamicImport, @@ -11,6 +12,7 @@ import { dirname, join } from "path" import { MetadataStorage } from "@mikro-orm/core" import { MikroORM } from "@mikro-orm/postgresql" +import { initializeContainer } from "../../../loaders" 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 */ const main = async function ({ directory }) { + const container = await initializeContainer(directory, { + skipDbConnection: true, + }) + const logger = container.resolve(ContainerRegistrationKeys.LOGGER) + try { const moduleDescriptors = [] as { serviceName: string @@ -46,14 +53,14 @@ const main = async function ({ directory }) { */ 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") process.exit() } catch (error) { - console.log(new Array(TERMINAL_SIZE).join("-")) + logger.log(new Array(TERMINAL_SIZE).join("-")) logger.error(error.message, error) process.exit(1) @@ -101,7 +108,8 @@ async function generateMigrations( serviceName: string migrationsPath: string entities: any[] - }[] = [] + }[] = [], + logger: Logger ) { const DB_HOST = process.env.DB_HOST ?? "localhost" const DB_USERNAME = process.env.DB_USERNAME ?? "" diff --git a/packages/medusa/src/commands/plugin/db/integration-tests/__tests__/plugin-generate.spec.ts b/packages/medusa/src/commands/plugin/db/integration-tests/__tests__/plugin-generate.spec.ts index b4dbad7fa4..28be2bb689 100644 --- a/packages/medusa/src/commands/plugin/db/integration-tests/__tests__/plugin-generate.spec.ts +++ b/packages/medusa/src/commands/plugin/db/integration-tests/__tests__/plugin-generate.spec.ts @@ -1,9 +1,24 @@ -import { logger } from "@medusajs/framework/logger" import { FileSystem } from "@medusajs/framework/utils" import { join } from "path" 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("../../../../../loaders", () => { + return { + initializeContainer: jest.fn().mockImplementation(() => { + return { + resolve: jest.fn(() => logger), + } + }), + } +}) describe("plugin-generate", () => { beforeEach(() => { @@ -13,6 +28,8 @@ describe("plugin-generate", () => { .mockImplementation((code?: string | number | null) => { return code as never }) + + jest.mock("@medusajs/framework/logger") }) afterEach(async () => { diff --git a/packages/medusa/src/commands/plugin/develop.ts b/packages/medusa/src/commands/plugin/develop.ts index b808bdad29..8c4146231f 100644 --- a/packages/medusa/src/commands/plugin/develop.ts +++ b/packages/medusa/src/commands/plugin/develop.ts @@ -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 { execFile } from "child_process" -import { logger } from "@medusajs/framework/logger" -import { Compiler } from "@medusajs/framework/build-tools" +import path from "path" +import { initializeContainer } from "../../loaders" export default async function developPlugin({ directory, }: { directory: string }) { + const container = await initializeContainer(directory) + const logger = container.resolve(ContainerRegistrationKeys.LOGGER) + let isBusy = false const compiler = new Compiler(directory, logger) const parsedConfig = await compiler.loadTSConfigFile() diff --git a/packages/medusa/src/commands/start.ts b/packages/medusa/src/commands/start.ts index e0b3be72f7..dc844c7cfe 100644 --- a/packages/medusa/src/commands/start.ts +++ b/packages/medusa/src/commands/start.ts @@ -6,8 +6,8 @@ import { scheduleJob } from "node-schedule" import os from "os" import path from "path" -import { logger } from "@medusajs/framework/logger" import { + ContainerRegistrationKeys, dynamicImport, FileSystem, generateContainerTypes, @@ -20,7 +20,7 @@ import { import { MedusaModule } from "@medusajs/framework/modules-sdk" import { MedusaContainer } from "@medusajs/framework/types" import { parse } from "url" -import loaders from "../loaders" +import loaders, { initializeContainer } from "../loaders" const EVERY_SIXTH_HOUR = "0 */6 * * *" const CRON_SCHEDULE = EVERY_SIXTH_HOUR @@ -33,6 +33,11 @@ const INSTRUMENTATION_FILE = "instrumentation" * errors. */ 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 exists = (await fileSystem.exists(`${INSTRUMENTATION_FILE}.ts`)) || @@ -82,10 +87,10 @@ function displayAdminUrl({ return } - const logger = container.resolve("logger") + const logger = container.resolve(ContainerRegistrationKeys.LOGGER) const { admin: { path: adminPath, disable }, - } = container.resolve("configModule") + } = container.resolve(ContainerRegistrationKeys.CONFIG_MODULE) if (disable) { return @@ -141,6 +146,9 @@ async function start(args: { }) { const { port = 9000, host, directory, types } = args + const container = await initializeContainer(directory) + const logger = container.resolve(ContainerRegistrationKeys.LOGGER) + async function internalStart(generateTypes: boolean) { track("CLI_START") await registerInstrumentation(directory) diff --git a/packages/medusa/src/commands/user.ts b/packages/medusa/src/commands/user.ts index 4cf51411bd..fc4416803d 100644 --- a/packages/medusa/src/commands/user.ts +++ b/packages/medusa/src/commands/user.ts @@ -1,7 +1,6 @@ -import { logger } from "@medusajs/framework/logger" -import { Modules } from "@medusajs/framework/utils" -import express from "express" +import { ContainerRegistrationKeys, Modules } from "@medusajs/framework/utils" import { track } from "@medusajs/telemetry" +import express from "express" import loaders from "../loaders" export default async function ({ @@ -25,6 +24,7 @@ export default async function ({ directory, expressApp: app, }) + const logger = container.resolve(ContainerRegistrationKeys.LOGGER) const userService = container.resolve(Modules.USER) const authService = container.resolve(Modules.AUTH) diff --git a/packages/medusa/src/commands/utils/index.ts b/packages/medusa/src/commands/utils/index.ts index 3d7983de98..08c5512d77 100644 --- a/packages/medusa/src/commands/utils/index.ts +++ b/packages/medusa/src/commands/utils/index.ts @@ -1,8 +1,8 @@ -import { logger } from "@medusajs/framework/logger" import { MedusaContainer } from "@medusajs/framework/types" import { ContainerRegistrationKeys } from "@medusajs/framework/utils" export async function ensureDbExists(container: MedusaContainer) { + const logger = container.resolve(ContainerRegistrationKeys.LOGGER) const pgConnection = container.resolve( ContainerRegistrationKeys.PG_CONNECTION ) diff --git a/packages/medusa/src/instrumentation/__fixtures__/server/index.ts b/packages/medusa/src/instrumentation/__fixtures__/server/index.ts index 6ed0b0f675..efc4608d6a 100644 --- a/packages/medusa/src/instrumentation/__fixtures__/server/index.ts +++ b/packages/medusa/src/instrumentation/__fixtures__/server/index.ts @@ -13,10 +13,10 @@ import { ApiLoader, container, featureFlagsLoader, - logger, MedusaRequest, } from "@medusajs/framework" import { configManager } from "@medusajs/framework/config" +import { logger as defaultLogger } from "@medusajs/framework/logger" import { ConfigModule, MedusaContainer } from "@medusajs/types" import { config } from "../mocks" @@ -67,10 +67,8 @@ export const createServer = async (rootDir) => { container.register(ContainerRegistrationKeys.PG_CONNECTION, asValue({})) container.register("configModule", asValue(config)) + container.register(ContainerRegistrationKeys.LOGGER, asValue(defaultLogger)) container.register({ - logger: asValue({ - error: () => {}, - }), manager: asValue({}), }) @@ -88,7 +86,7 @@ export const createServer = async (rootDir) => { }) await featureFlagsLoader() - await moduleLoader({ container, moduleResolutions, logger }) + await moduleLoader({ container, moduleResolutions, logger: defaultLogger }) app.use((req, res, next) => { ;(req as MedusaRequest).scope = container.createScope() as MedusaContainer @@ -98,6 +96,7 @@ export const createServer = async (rootDir) => { await new ApiLoader({ app, sourceDir: rootDir, + container, }).load() const superRequest = supertest(app) diff --git a/packages/medusa/src/loaders/api.ts b/packages/medusa/src/loaders/api.ts index 159304d6c7..16c30e8364 100644 --- a/packages/medusa/src/loaders/api.ts +++ b/packages/medusa/src/loaders/api.ts @@ -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 { join } from "path" 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 = { app: Express @@ -59,6 +59,7 @@ export default async ({ app, container, plugins }: Options) => { app: app, sourceDir: sourcePaths, baseRestrictedFields: restrictedFields?.store, + container, }).load() } catch (err) { throw Error( diff --git a/packages/medusa/src/loaders/index.ts b/packages/medusa/src/loaders/index.ts index 5b56916004..164095c912 100644 --- a/packages/medusa/src/loaders/index.ts +++ b/packages/medusa/src/loaders/index.ts @@ -5,7 +5,7 @@ import { featureFlagsLoader } from "@medusajs/framework/feature-flags" import { expressLoader } from "@medusajs/framework/http" import { JobLoader } from "@medusajs/framework/jobs" 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 { ConfigModule, @@ -46,7 +46,10 @@ const shouldLoadBackgroundProcessors = (configModule) => { ) } -async function subscribersLoader(plugins: PluginDetails[]) { +async function subscribersLoader( + plugins: PluginDetails[], + container: MedusaContainer +) { const pluginSubscribersSourcePaths = [ /** * 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"), ].concat(plugins.map((plugin) => join(plugin.resolve, "subscribers"))) - const subscriberLoader = new SubscriberLoader(pluginSubscribersSourcePaths) + const subscriberLoader = new SubscriberLoader( + pluginSubscribersSourcePaths, + undefined, + container + ) await subscriberLoader.load() } -async function jobsLoader(plugins: PluginDetails[]) { +async function jobsLoader( + plugins: PluginDetails[], + container: MedusaContainer +) { 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"), ].concat(plugins.map((plugin) => join(plugin.resolve, "jobs"))) - const jobLoader = new JobLoader(pluginJobSourcePaths) + const jobLoader = new JobLoader(pluginJobSourcePaths, container) await jobLoader.load() } @@ -81,8 +91,8 @@ async function loadEntrypoints( ) if (shouldLoadBackgroundProcessors(configModule)) { - await subscribersLoader(plugins) - await jobsLoader(plugins) + await subscribersLoader(plugins, container) + await jobsLoader(plugins, container) } if (isWorkerMode(configModule)) { @@ -110,6 +120,7 @@ async function loadEntrypoints( const { shutdown } = await expressLoader({ app: expressApp, + container, }) await adminLoader({ app: expressApp, configModule, rootDirectory, plugins }) @@ -123,17 +134,24 @@ async function loadEntrypoints( } export async function initializeContainer( - rootDirectory: string + rootDirectory: string, + options?: { + skipDbConnection?: boolean + } ): Promise { - await configLoader(rootDirectory, "medusa-config") + const configDir = await configLoader(rootDirectory, "medusa-config") await featureFlagsLoader(join(__dirname, "..")) + const customLogger = configDir.logger ?? defaultLogger container.register({ - [ContainerRegistrationKeys.LOGGER]: asValue(logger), + [ContainerRegistrationKeys.LOGGER]: asValue(customLogger), [ContainerRegistrationKeys.REMOTE_QUERY]: asValue(null), }) - await pgConnectionLoader() + if (!options?.skipDbConnection) { + await pgConnectionLoader() + } + return container } @@ -151,6 +169,7 @@ export default async ({ const configModule = container.resolve( ContainerRegistrationKeys.CONFIG_MODULE ) + const logger = container.resolve(ContainerRegistrationKeys.LOGGER) const plugins = await getResolvedPlugins(rootDirectory, configModule, true) mergePluginModules(configModule, plugins) @@ -162,7 +181,7 @@ export default async ({ const linksSourcePaths = plugins.map((plugin) => join(plugin.resolve, "links") ) - await new LinkLoader(linksSourcePaths).load() + await new LinkLoader(linksSourcePaths, logger).load() const { onApplicationStart, @@ -173,7 +192,7 @@ export default async ({ } = await new MedusaAppLoader().load() const workflowsSourcePaths = plugins.map((p) => join(p.resolve, "workflows")) - const workflowLoader = new WorkflowLoader(workflowsSourcePaths) + const workflowLoader = new WorkflowLoader(workflowsSourcePaths, container) await workflowLoader.load() const entrypointsShutdown = await loadEntrypoints(