diff --git a/packages/core/types/src/common/config-module.ts b/packages/core/types/src/common/config-module.ts index 472511a2f2..d8e034277c 100644 --- a/packages/core/types/src/common/config-module.ts +++ b/packages/core/types/src/common/config-module.ts @@ -862,6 +862,10 @@ export type ConfigModule = { * ::: */ featureFlags: Record + + directories?: { + srcDir?: string + } } export type PluginDetails = { diff --git a/packages/core/types/src/currency/service.ts b/packages/core/types/src/currency/service.ts index ffb946b15e..87c8ac7700 100644 --- a/packages/core/types/src/currency/service.ts +++ b/packages/core/types/src/currency/service.ts @@ -1,5 +1,4 @@ import { FindConfig } from "../common" -import { RestoreReturn, SoftDeleteReturn } from "../dal" import { IModuleService } from "../modules-sdk" import { Context } from "../shared-context" import { FilterableCurrencyProps, CurrencyDTO } from "./common" diff --git a/packages/core/types/src/dal/index.ts b/packages/core/types/src/dal/index.ts index 325360d3ee..fe9646a67c 100644 --- a/packages/core/types/src/dal/index.ts +++ b/packages/core/types/src/dal/index.ts @@ -1,4 +1,4 @@ -import { Dictionary, FilterQuery, OperatorMap, Order } from "./utils" +import { Dictionary, FilterQuery, Order } from "./utils" export { FilterQuery, OperatorMap } from "./utils" diff --git a/packages/core/types/src/dal/repository-service.ts b/packages/core/types/src/dal/repository-service.ts index 5a50102ce6..55d4a575c4 100644 --- a/packages/core/types/src/dal/repository-service.ts +++ b/packages/core/types/src/dal/repository-service.ts @@ -33,8 +33,6 @@ interface BaseRepositoryService { ): Promise } -type DtoBasedMutationMethods = "create" | "update" - export interface RepositoryService extends BaseRepositoryService { find(options?: FindOptions, context?: Context): Promise diff --git a/packages/core/types/src/http/collection/common.ts b/packages/core/types/src/http/collection/common.ts index 31990b803a..286d6cf307 100644 --- a/packages/core/types/src/http/collection/common.ts +++ b/packages/core/types/src/http/collection/common.ts @@ -1,4 +1,4 @@ -import { BaseFilterable, OperatorMap } from "../../dal" +import { BaseFilterable } from "../../dal" import { BaseProduct } from "../product/common" export interface BaseProductCollection { diff --git a/packages/core/types/src/stock-location/common.ts b/packages/core/types/src/stock-location/common.ts index 8f8ea3fc17..703e46c197 100644 --- a/packages/core/types/src/stock-location/common.ts +++ b/packages/core/types/src/stock-location/common.ts @@ -1,6 +1,4 @@ import { BaseFilterable, OperatorMap } from "../dal" - -import { StringComparisonOperator } from "../common/common" import { FulfillmentSetDTO } from "../fulfillment" /** diff --git a/packages/core/types/src/stock-location/service-next.ts b/packages/core/types/src/stock-location/service-next.ts index 8fb1cc4e79..f1dcf68309 100644 --- a/packages/core/types/src/stock-location/service-next.ts +++ b/packages/core/types/src/stock-location/service-next.ts @@ -3,7 +3,6 @@ import { FilterableStockLocationProps, StockLocationDTO, UpdateStockLocationInput, - UpdateStockLocationNextInput, UpsertStockLocationInput, } from "./common" import { RestoreReturn, SoftDeleteReturn } from "../dal" diff --git a/packages/medusa/src/api/admin/api-keys/[id]/route.ts b/packages/medusa/src/api/admin/api-keys/[id]/route.ts index 75e8cdbeca..cd91dfee0d 100644 --- a/packages/medusa/src/api/admin/api-keys/[id]/route.ts +++ b/packages/medusa/src/api/admin/api-keys/[id]/route.ts @@ -7,10 +7,6 @@ import { MedusaResponse, } from "../../../../types/routing" -import { - ContainerRegistrationKeys, - remoteQueryObjectFromString, -} from "@medusajs/utils" import { refetchApiKey } from "../helpers" import { AdminUpdateApiKeyType } from "../validators" @@ -31,7 +27,7 @@ export const POST = async ( req: AuthenticatedMedusaRequest, res: MedusaResponse ) => { - const { result, errors } = await updateApiKeysWorkflow(req.scope).run({ + const { errors } = await updateApiKeysWorkflow(req.scope).run({ input: { selector: { id: req.params.id }, update: req.validatedBody, diff --git a/packages/medusa/src/api/admin/campaigns/[id]/route.ts b/packages/medusa/src/api/admin/campaigns/[id]/route.ts index 1b82c6eaa8..710643fa59 100644 --- a/packages/medusa/src/api/admin/campaigns/[id]/route.ts +++ b/packages/medusa/src/api/admin/campaigns/[id]/route.ts @@ -43,7 +43,7 @@ export const POST = async ( }, ] - const { result, errors } = await updateCampaigns.run({ + const { errors } = await updateCampaigns.run({ input: { campaignsData }, throwOnError: false, }) diff --git a/packages/medusa/src/api/admin/collections/[id]/products/route.ts b/packages/medusa/src/api/admin/collections/[id]/products/route.ts index b8abee70ab..92e9fe12e4 100644 --- a/packages/medusa/src/api/admin/collections/[id]/products/route.ts +++ b/packages/medusa/src/api/admin/collections/[id]/products/route.ts @@ -14,7 +14,7 @@ export const POST = async ( const { add = [], remove = [] } = req.validatedBody const workflow = batchLinkProductsToCollectionWorkflow(req.scope) - const { result, errors } = await workflow.run({ + const { errors } = await workflow.run({ input: { id, add, diff --git a/packages/medusa/src/api/admin/collections/[id]/route.ts b/packages/medusa/src/api/admin/collections/[id]/route.ts index 9b3f9ebad5..61c9480d91 100644 --- a/packages/medusa/src/api/admin/collections/[id]/route.ts +++ b/packages/medusa/src/api/admin/collections/[id]/route.ts @@ -27,7 +27,7 @@ export const POST = async ( req: AuthenticatedMedusaRequest, res: MedusaResponse ) => { - const { result, errors } = await updateCollectionsWorkflow(req.scope).run({ + const { errors } = await updateCollectionsWorkflow(req.scope).run({ input: { selector: { id: req.params.id }, update: req.validatedBody, diff --git a/packages/medusa/src/api/admin/customer-groups/[id]/route.ts b/packages/medusa/src/api/admin/customer-groups/[id]/route.ts index 41bf74cf94..4085d0e865 100644 --- a/packages/medusa/src/api/admin/customer-groups/[id]/route.ts +++ b/packages/medusa/src/api/admin/customer-groups/[id]/route.ts @@ -28,7 +28,7 @@ export const POST = async ( res: MedusaResponse ) => { const updateGroups = updateCustomerGroupsWorkflow(req.scope) - const { result, errors } = await updateGroups.run({ + const { errors } = await updateGroups.run({ input: { selector: { id: req.params.id }, update: req.validatedBody, diff --git a/packages/medusa/src/api/admin/customers/[id]/addresses/[address_id]/route.ts b/packages/medusa/src/api/admin/customers/[id]/addresses/[address_id]/route.ts index c011a5540f..3d731f827e 100644 --- a/packages/medusa/src/api/admin/customers/[id]/addresses/[address_id]/route.ts +++ b/packages/medusa/src/api/admin/customers/[id]/addresses/[address_id]/route.ts @@ -37,7 +37,7 @@ export const POST = async ( res: MedusaResponse ) => { const updateAddresses = updateCustomerAddressesWorkflow(req.scope) - const { result, errors } = await updateAddresses.run({ + const { errors } = await updateAddresses.run({ input: { selector: { id: req.params.address_id, customer_id: req.params.id }, update: req.validatedBody, diff --git a/packages/medusa/src/api/admin/customers/[id]/addresses/route.ts b/packages/medusa/src/api/admin/customers/[id]/addresses/route.ts index 52b92c2f24..dc3332490e 100644 --- a/packages/medusa/src/api/admin/customers/[id]/addresses/route.ts +++ b/packages/medusa/src/api/admin/customers/[id]/addresses/route.ts @@ -49,7 +49,7 @@ export const POST = async ( }, ] - const { result, errors } = await createAddresses.run({ + const { errors } = await createAddresses.run({ input: { addresses }, throwOnError: false, }) diff --git a/packages/medusa/src/api/admin/price-lists/[id]/products/route.ts b/packages/medusa/src/api/admin/price-lists/[id]/products/route.ts index 4543f5483a..0e453bc716 100644 --- a/packages/medusa/src/api/admin/price-lists/[id]/products/route.ts +++ b/packages/medusa/src/api/admin/price-lists/[id]/products/route.ts @@ -34,7 +34,7 @@ export const POST = async ( ) const workflow = batchPriceListPricesWorkflow(req.scope) - const { result, errors } = await workflow.run({ + const { errors } = await workflow.run({ input: { data: { id, diff --git a/packages/medusa/src/api/admin/pricing/rule-types/[id]/route.ts b/packages/medusa/src/api/admin/pricing/rule-types/[id]/route.ts index d250678527..55c4fe5350 100644 --- a/packages/medusa/src/api/admin/pricing/rule-types/[id]/route.ts +++ b/packages/medusa/src/api/admin/pricing/rule-types/[id]/route.ts @@ -38,7 +38,7 @@ export const POST = async ( res: MedusaResponse ) => { const workflow = updatePricingRuleTypesWorkflow(req.scope) - const { result, errors } = await workflow.run({ + const { errors } = await workflow.run({ input: { data: [{ ...req.validatedBody, id: req.params.id }], }, diff --git a/packages/medusa/src/api/admin/products/[id]/options/[option_id]/route.ts b/packages/medusa/src/api/admin/products/[id]/options/[option_id]/route.ts index e9f84b994f..3fe078fe39 100644 --- a/packages/medusa/src/api/admin/products/[id]/options/[option_id]/route.ts +++ b/packages/medusa/src/api/admin/products/[id]/options/[option_id]/route.ts @@ -42,7 +42,7 @@ export const POST = async ( const productId = req.params.id const optionId = req.params.option_id - const { result, errors } = await updateProductOptionsWorkflow(req.scope).run({ + const { errors } = await updateProductOptionsWorkflow(req.scope).run({ input: { selector: { id: optionId, product_id: productId }, update: req.validatedBody, diff --git a/packages/medusa/src/api/admin/products/[id]/options/route.ts b/packages/medusa/src/api/admin/products/[id]/options/route.ts index cd9dc95b76..caa0379476 100644 --- a/packages/medusa/src/api/admin/products/[id]/options/route.ts +++ b/packages/medusa/src/api/admin/products/[id]/options/route.ts @@ -51,7 +51,7 @@ export const POST = async ( }, ] - const { result, errors } = await createProductOptionsWorkflow(req.scope).run({ + const { errors } = await createProductOptionsWorkflow(req.scope).run({ input: { product_options: input }, throwOnError: false, }) diff --git a/packages/medusa/src/api/admin/products/[id]/variants/route.ts b/packages/medusa/src/api/admin/products/[id]/variants/route.ts index 0cf89e3a49..22cb9f88a6 100644 --- a/packages/medusa/src/api/admin/products/[id]/variants/route.ts +++ b/packages/medusa/src/api/admin/products/[id]/variants/route.ts @@ -56,12 +56,10 @@ export const POST = async ( }, ] - const { result, errors } = await createProductVariantsWorkflow(req.scope).run( - { - input: { product_variants: input }, - throwOnError: false, - } - ) + const { errors } = await createProductVariantsWorkflow(req.scope).run({ + input: { product_variants: input }, + throwOnError: false, + }) if (Array.isArray(errors) && errors[0]) { throw errors[0].error diff --git a/packages/medusa/src/api/admin/promotions/[id]/route.ts b/packages/medusa/src/api/admin/promotions/[id]/route.ts index 7457c90e27..ce43f63c5d 100644 --- a/packages/medusa/src/api/admin/promotions/[id]/route.ts +++ b/packages/medusa/src/api/admin/promotions/[id]/route.ts @@ -54,7 +54,7 @@ export const POST = async ( } as any, ] - const { result, errors } = await updatePromotions.run({ + const { errors } = await updatePromotions.run({ input: { promotionsData }, throwOnError: false, }) diff --git a/packages/medusa/src/api/admin/users/[id]/route.ts b/packages/medusa/src/api/admin/users/[id]/route.ts index 4d68e9775d..1241ec204a 100644 --- a/packages/medusa/src/api/admin/users/[id]/route.ts +++ b/packages/medusa/src/api/admin/users/[id]/route.ts @@ -54,7 +54,7 @@ export const POST = async ( ], } - const { result } = await workflow.run({ input }) + await workflow.run({ input }) const user = await refetchUser( req.params.id, diff --git a/packages/medusa/src/loaders/admin.ts b/packages/medusa/src/loaders/admin.ts index e4eb3ec5c0..fb06608b2e 100644 --- a/packages/medusa/src/loaders/admin.ts +++ b/packages/medusa/src/loaders/admin.ts @@ -3,7 +3,7 @@ import { Express } from "express" type Options = { app: Express - configModule: ConfigModule + adminConfig: ConfigModule["admin"] } type IntializedOptions = Required< @@ -11,17 +11,15 @@ type IntializedOptions = Required< > & AdminOptions -export default async function adminLoader({ app, configModule }: Options) { - const { admin } = configModule - +export default async function adminLoader({ app, adminConfig }: Options) { const adminOptions: IntializedOptions = { disable: false, path: "/app", outDir: "./build", - ...admin, + ...adminConfig, } - if (admin?.disable) { + if (adminOptions?.disable) { return app } diff --git a/packages/medusa/src/loaders/api.ts b/packages/medusa/src/loaders/api.ts index 8783a080fe..689ac95d7d 100644 --- a/packages/medusa/src/loaders/api.ts +++ b/packages/medusa/src/loaders/api.ts @@ -1,19 +1,17 @@ -import { ConfigModule } from "@medusajs/types" -import { FlagRouter } from "@medusajs/utils" -import { AwilixContainer } from "awilix" +import { ContainerRegistrationKeys } from "@medusajs/utils" import { Express } from "express" import path from "path" import qs from "qs" import { RoutesLoader } from "./helpers/routing" +import { MedusaContainer, PluginDetails } from "@medusajs/types" type Options = { app: Express - container: AwilixContainer - configModule: ConfigModule - featureFlagRouter?: FlagRouter + plugins: PluginDetails[] + container: MedusaContainer } -export default async ({ app, configModule }: Options) => { +export default async ({ app, container, plugins }: Options) => { // This is a workaround for the issue described here: https://github.com/expressjs/express/issues/3454 // We parse the url and get the qs to be parsed and override the query prop from the request app.use(function (req, res, next) { @@ -26,6 +24,10 @@ export default async ({ app, configModule }: Options) => { next() }) + const configModule = container.resolve( + ContainerRegistrationKeys.CONFIG_MODULE + ) + // TODO: Figure out why this is causing issues with test when placed inside ./api.ts // Adding this here temporarily // Test: (packages/medusa/src/api/routes/admin/currencies/update-currency.ts) @@ -40,9 +42,20 @@ export default async ({ app, configModule }: Options) => { }).load() } catch (err) { throw Error( - "An error occurred while registering Medusa Core API Routes. See error in logs for more details." + "An error occurred while registering Medusa Core API Routes. See error in logs for more details.", + { cause: err } ) } + await Promise.all( + plugins.map(async (pluginDetails) => { + return new RoutesLoader({ + app: app, + configModule, + rootDir: path.join(pluginDetails.resolve, "api"), + }).load() + }) + ) + return app } diff --git a/packages/medusa/src/loaders/config.ts b/packages/medusa/src/loaders/config.ts index 767f175098..33754ec78f 100644 --- a/packages/medusa/src/loaders/config.ts +++ b/packages/medusa/src/loaders/config.ts @@ -102,5 +102,8 @@ export default (rootDirectory: string): ConfigModule => { modules: configModule.modules ?? {}, featureFlags: configModule?.featureFlags ?? {}, plugins: configModule?.plugins ?? [], + directories: configModule?.directories ?? { + srcDir: "dist", + }, } } diff --git a/packages/medusa/src/loaders/helpers/register-workflows.ts b/packages/medusa/src/loaders/helpers/register-workflows.ts index 0ddea527ab..e939c30b29 100644 --- a/packages/medusa/src/loaders/helpers/register-workflows.ts +++ b/packages/medusa/src/loaders/helpers/register-workflows.ts @@ -1,21 +1,22 @@ -import { PluginDetails } from "@medusajs/types" import { glob } from "glob" -import { getResolvedPlugins } from "./resolve-plugins" +import { PluginDetails } from "@medusajs/types" /** * import files from the workflows directory to run the registration of the wofklows * @param pluginDetails */ -async function registerWorkflows(pluginDetails: PluginDetails): Promise { - const files = glob.sync(`${pluginDetails.resolve}/workflows/*.js`, {}) - await Promise.all(files.map(async (file) => import(file))) -} - -export async function registerProjectWorkflows({ - rootDirectory, - configModule, -}) { - const [resolved] = - getResolvedPlugins(rootDirectory, configModule, "dist", true) || [] - await registerWorkflows(resolved) +export async function registerWorkflows( + plugins: PluginDetails[] +): Promise { + await Promise.all( + plugins.map(async (pluginDetails) => { + const files = glob.sync( + `${pluginDetails.resolve}/workflows/*.{ts,js,mjs,mts}`, + { + ignore: ["**/*.d.ts", "**/*.map"], + } + ) + return Promise.all(files.map(async (file) => import(file))) + }) + ) } diff --git a/packages/medusa/src/loaders/helpers/resolve-plugins.ts b/packages/medusa/src/loaders/helpers/resolve-plugins.ts index 9c2ad317ad..ecde1c809e 100644 --- a/packages/medusa/src/loaders/helpers/resolve-plugins.ts +++ b/packages/medusa/src/loaders/helpers/resolve-plugins.ts @@ -106,15 +106,22 @@ function resolvePlugin(pluginName: string): { export function getResolvedPlugins( rootDirectory: string, - configModule: ConfigModule, - extensionDirectoryPath = "dist", + configModule: { + plugins: ConfigModule["plugins"] + directories?: ConfigModule["directories"] + }, isMedusaProject = false ): undefined | PluginDetails[] { - const { plugins } = configModule - if (isMedusaProject) { + /** + * Grab directory for loading resources inside a starter kit from + * the medusa-config file. + * + * This is because, we do not have a "dist" directory inside a starter + * kit. Instead we discover resources from the "src" directory. + */ + const extensionDirectoryPath = configModule.directories?.srcDir ?? "dist" const extensionDirectory = path.join(rootDirectory, extensionDirectoryPath) - return [ { resolve: extensionDirectory, @@ -126,7 +133,8 @@ export function getResolvedPlugins( ] } - const resolved = plugins.map((plugin) => { + const extensionDirectoryPath = "dist" + const resolved = configModule?.plugins.map((plugin) => { if (isString(plugin)) { return resolvePlugin(plugin) } diff --git a/packages/medusa/src/loaders/helpers/routing/__fixtures__/mocks/index.ts b/packages/medusa/src/loaders/helpers/routing/__fixtures__/mocks/index.ts index dd93d44728..ddaf7beb40 100644 --- a/packages/medusa/src/loaders/helpers/routing/__fixtures__/mocks/index.ts +++ b/packages/medusa/src/loaders/helpers/routing/__fixtures__/mocks/index.ts @@ -1,11 +1,14 @@ +import { ConfigModule } from "@medusajs/types" + export const customersGlobalMiddlewareMock = jest.fn() export const customersCreateMiddlewareMock = jest.fn() export const storeGlobalMiddlewareMock = jest.fn() -export const config = { +export const config: ConfigModule = { projectConfig: { database_logging: false, http: { + authCors: "http://localhost:9000", storeCors: "http://localhost:8000", adminCors: "http://localhost:7001", jwtSecret: "supersecret", diff --git a/packages/medusa/src/loaders/helpers/routing/__fixtures__/server/index.js b/packages/medusa/src/loaders/helpers/routing/__fixtures__/server/index.ts similarity index 88% rename from packages/medusa/src/loaders/helpers/routing/__fixtures__/server/index.js rename to packages/medusa/src/loaders/helpers/routing/__fixtures__/server/index.ts index de999ef069..d6df98a480 100644 --- a/packages/medusa/src/loaders/helpers/routing/__fixtures__/server/index.js +++ b/packages/medusa/src/loaders/helpers/routing/__fixtures__/server/index.ts @@ -3,14 +3,18 @@ import { ModulesDefinition, registerMedusaModule, } from "@medusajs/modules-sdk" -import { ContainerRegistrationKeys } from "@medusajs/utils" -import { asValue, createContainer } from "awilix" +import { + ContainerRegistrationKeys, + createMedusaContainer, +} from "@medusajs/utils" +import { asValue } from "awilix" import express from "express" import jwt from "jsonwebtoken" import { MockManager } from "medusa-test-utils" import querystring from "querystring" import supertest from "supertest" import apiLoader from "../../../../api" +import { getResolvedPlugins } from "../../../../helpers/resolve-plugins" import featureFlagLoader, { featureFlagRouter } from "../../../../feature-flags" import passportLoader from "../../../../passport" @@ -42,7 +46,7 @@ export const createServer = async (rootDir) => { )[moduleKey] }) - const container = createContainer() + const container = createMedusaContainer() container.registerAdd = function (name, registration) { const storeKey = name + "_STORE" @@ -83,8 +87,10 @@ export const createServer = async (rootDir) => { next() }) + const plugins = getResolvedPlugins(rootDir, config) || [] + featureFlagLoader(config) - await passportLoader({ app: app, container, configModule: config }) + await passportLoader({ app: app, configModule: config }) await moduleLoader({ container, moduleResolutions }) app.use((req, res, next) => { @@ -103,14 +109,13 @@ export const createServer = async (rootDir) => { await apiLoader({ container, app: app, - configModule: config, - featureFlagRouter, + plugins, }) const superRequest = supertest(app) return { - request: async (method, url, opts = {}) => { + request: async (method, url, opts: any = {}) => { const { payload, query, headers = {} } = opts const queryParams = query && querystring.stringify(query) @@ -124,7 +129,7 @@ export const createServer = async (rootDir) => { user_id: opts.adminSession.userId || opts.adminSession.jwt?.userId, domain: "admin", }, - config.projectConfig.http.jwtSecret + config.projectConfig.http.jwtSecret! ) headers.Authorization = `Bearer ${token}` @@ -137,7 +142,7 @@ export const createServer = async (rootDir) => { opts.clientSession.jwt?.customer_id, domain: "store", }, - config.projectConfig.http.jwtSecret + config.projectConfig.http.jwtSecret! ) headers.Authorization = `Bearer ${token}` diff --git a/packages/medusa/src/loaders/helpers/routing/index.ts b/packages/medusa/src/loaders/helpers/routing/index.ts index 6ba15fd2fb..c4b40cd702 100644 --- a/packages/medusa/src/loaders/helpers/routing/index.ts +++ b/packages/medusa/src/loaders/helpers/routing/index.ts @@ -568,8 +568,6 @@ export class RoutesLoader { } if (mostSpecificConfig?.bodyParser) { - const sizeLimit = mostSpecificConfig?.bodyParser?.sizeLimit - this.router[method.toLowerCase()]( path, ...getBodyParserMiddleware(mostSpecificConfig?.bodyParser) diff --git a/packages/medusa/src/loaders/index.ts b/packages/medusa/src/loaders/index.ts index 8baade8d6e..cbe6e8b84e 100644 --- a/packages/medusa/src/loaders/index.ts +++ b/packages/medusa/src/loaders/index.ts @@ -1,5 +1,5 @@ import { createDefaultsWorkflow } from "@medusajs/core-flows" -import { ConfigModule } from "@medusajs/types" +import { ConfigModule, MedusaContainer } from "@medusajs/types" import { ContainerRegistrationKeys, promiseAll } from "@medusajs/utils" import { asValue } from "awilix" import { Express, NextFunction, Request, Response } from "express" @@ -7,17 +7,19 @@ import { createMedusaContainer } from "medusa-core-utils" import requestIp from "request-ip" import { v4 } from "uuid" import path from "path" -import { MedusaContainer } from "../types/global" import adminLoader from "./admin" import apiLoader from "./api" import loadConfig from "./config" import expressLoader from "./express" import featureFlagsLoader from "./feature-flags" -import { registerProjectWorkflows } from "./helpers/register-workflows" +import { registerWorkflows } from "./helpers/register-workflows" import Logger from "./logger" import loadMedusaApp from "./medusa-app" -import pgConnectionLoader from "./pg-connection" +import registerPgConnection from "./pg-connection" import { SubscriberLoader } from "./helpers/subscribers" +import { getResolvedPlugins } from "./helpers/resolve-plugins" +import { PluginDetails } from "@medusajs/types" +import glob from "glob" type Options = { directory: string @@ -28,17 +30,45 @@ const isWorkerMode = (configModule) => { return configModule.projectConfig.worker_mode === "worker" } -async function subscribersLoader(container) { - const subscribersPath = path.join(__dirname, "../subscribers") - await new SubscriberLoader(subscribersPath, container).load() +async function subscribersLoader( + plugins: PluginDetails[], + container: MedusaContainer +) { + /** + * Load subscribers from the medusa/medusa package + */ + await new SubscriberLoader( + path.join(__dirname, "../subscribers"), + container + ).load() + + /** + * Load subscribers from all the plugins. + */ + await Promise.all( + plugins.map(async (pluginDetails) => { + const files = glob.sync( + `${pluginDetails.resolve}/subscribers/*.{ts,js,mjs,mts}`, + { + ignore: ["**/*.d.ts", "**/*.map"], + } + ) + return Promise.all( + files.map(async (file) => new SubscriberLoader(file, container).load()) + ) + }) + ) } async function loadEntrypoints( - configModule, - container, - expressApp, - featureFlagRouter + plugins: PluginDetails[], + container: MedusaContainer, + expressApp: Express ) { + const configModule: ConfigModule = container.resolve( + ContainerRegistrationKeys.CONFIG_MODULE + ) + if (isWorkerMode(configModule)) { return async () => {} } @@ -59,33 +89,22 @@ async function loadEntrypoints( next() }) - await adminLoader({ app: expressApp, configModule }) - await subscribersLoader(container) + await adminLoader({ app: expressApp, adminConfig: configModule.admin }) + await subscribersLoader(plugins, container) await apiLoader({ container, + plugins, app: expressApp, - configModule, - featureFlagRouter, }) return shutdown } -export default async ({ - directory: rootDirectory, - expressApp, -}: Options): Promise<{ - configModule: ConfigModule - container: MedusaContainer - app: Express - pgConnection: unknown - shutdown: () => Promise - prepareShutdown: () => Promise -}> => { +async function initializeContainer(rootDirectory: string) { + const container = createMedusaContainer() const configModule = loadConfig(rootDirectory) const featureFlagRouter = featureFlagsLoader(configModule, Logger) - const container = createMedusaContainer() - const pgConnection = await pgConnectionLoader({ container, configModule }) + container.register({ [ContainerRegistrationKeys.LOGGER]: asValue(Logger), [ContainerRegistrationKeys.FEATURE_FLAG_ROUTER]: asValue(featureFlagRouter), @@ -93,28 +112,45 @@ export default async ({ [ContainerRegistrationKeys.REMOTE_QUERY]: asValue(null), }) - // Workflows are registered before the app to allow modules to run workflows as part of bootstrapping - // e.g. the workflow engine will resume workflows that were running when the server was shut down - await registerProjectWorkflows({ rootDirectory, configModule }) + await registerPgConnection({ container, configModule }) + return container +} + +export default async ({ + directory: rootDirectory, + expressApp, +}: Options): Promise<{ + container: MedusaContainer + app: Express + shutdown: () => Promise + prepareShutdown: () => Promise +}> => { + const container = await initializeContainer(rootDirectory) + const configModule = container.resolve( + ContainerRegistrationKeys.CONFIG_MODULE + ) + + const plugins = getResolvedPlugins(rootDirectory, configModule, true) || [] + await registerWorkflows(plugins) const { onApplicationShutdown: medusaAppOnApplicationShutdown, onApplicationPrepareShutdown: medusaAppOnApplicationPrepareShutdown, } = await loadMedusaApp({ - configModule, container, }) const entrypointsShutdown = await loadEntrypoints( - configModule, + plugins, container, - expressApp, - featureFlagRouter + expressApp ) - await createDefaultsWorkflow(container).run() const shutdown = async () => { + const pgConnection = container.resolve( + ContainerRegistrationKeys.PG_CONNECTION + ) await medusaAppOnApplicationShutdown() await promiseAll([ @@ -126,10 +162,8 @@ export default async ({ } return { - configModule, container, app: expressApp, - pgConnection, shutdown, prepareShutdown: medusaAppOnApplicationPrepareShutdown, } diff --git a/packages/medusa/src/loaders/medusa-app.ts b/packages/medusa/src/loaders/medusa-app.ts index d4798a86b1..71695b9df6 100644 --- a/packages/medusa/src/loaders/medusa-app.ts +++ b/packages/medusa/src/loaders/medusa-app.ts @@ -7,6 +7,7 @@ import { } from "@medusajs/modules-sdk" import { CommonTypes, + ConfigModule, InternalModuleDeclaration, LoadedModule, MedusaContainer, @@ -143,13 +144,8 @@ export async function revertMedusaApp({ export const loadMedusaApp = async ( { - configModule, container, }: { - configModule: { - modules?: CommonTypes.ConfigModule["modules"] - projectConfig: CommonTypes.ConfigModule["projectConfig"] - } container: MedusaContainer }, config = { registerInContainer: true } @@ -163,6 +159,10 @@ export const loadMedusaApp = async ( ), } + const configModule: ConfigModule = container.resolve( + ContainerRegistrationKeys.CONFIG_MODULE + ) + const sharedResourcesConfig = { database: { clientUrl: configModule.projectConfig.database_url, diff --git a/packages/medusa/src/loaders/pg-connection.ts b/packages/medusa/src/loaders/pg-connection.ts index 7cb73970fb..6e16993faa 100644 --- a/packages/medusa/src/loaders/pg-connection.ts +++ b/packages/medusa/src/loaders/pg-connection.ts @@ -3,8 +3,8 @@ import { ContainerRegistrationKeys, ModulesSdkUtils } from "@medusajs/utils" import { asValue, AwilixContainer } from "awilix" type Options = { - configModule: ConfigModule container: AwilixContainer + configModule: ConfigModule } export default async ({ container, configModule }: Options): Promise => { diff --git a/packages/medusa/src/utils/format-registration-name.ts b/packages/medusa/src/utils/format-registration-name.ts index 0831ed959a..067cbc4258 100644 --- a/packages/medusa/src/utils/format-registration-name.ts +++ b/packages/medusa/src/utils/format-registration-name.ts @@ -11,7 +11,6 @@ import { toCamelCase, upperCaseFirst } from "@medusajs/utils" export function formatRegistrationName(path: string): string { const parsed = parse(path) const parsedDir = parse(parsed.dir) - const rawname = parsed.name let directoryNamespace = parsedDir.name if (directoryNamespace.startsWith("__")) { diff --git a/packages/medusa/src/utils/get-query-config.ts b/packages/medusa/src/utils/get-query-config.ts index 0d7d6090ad..8f08204811 100644 --- a/packages/medusa/src/utils/get-query-config.ts +++ b/packages/medusa/src/utils/get-query-config.ts @@ -90,7 +90,6 @@ export function prepareListQuery( } }) - const allAllowedFields = new Set(allowedFields) // In case there is no allowedFields, allow all fields const notAllowedFields: string[] = [] if (allowedFields.length) { diff --git a/packages/medusa/tsconfig.json b/packages/medusa/tsconfig.json index 210e36b52d..a1e687b384 100644 --- a/packages/medusa/tsconfig.json +++ b/packages/medusa/tsconfig.json @@ -13,6 +13,7 @@ "noImplicitReturns": true, "strictNullChecks": true, "strictFunctionTypes": true, + "noUnusedLocals": true, "noImplicitThis": true, "allowJs": true, "skipLibCheck": true,