chore(): Allow to register modules through array (#9522)

This commit is contained in:
Adrien de Peretti
2024-10-11 15:17:00 +02:00
committed by GitHub
parent 9c73503084
commit 1d8939df3a
35 changed files with 954 additions and 349 deletions

View File

@@ -0,0 +1,5 @@
import { Module } from "../../../../modules-sdk"
export default Module("GithubModuleService", {
service: class GithubModuleService {},
})

View File

@@ -12,8 +12,10 @@ describe("defineConfig", function () {
},
"featureFlags": {},
"modules": {
"ApiKey": true,
"Auth": {
"api_key": {
"resolve": "@medusajs/medusa/api-key",
},
"auth": {
"options": {
"providers": [
{
@@ -22,14 +24,24 @@ describe("defineConfig", function () {
},
],
},
"resolve": "@medusajs/auth",
"resolve": "@medusajs/medusa/auth",
},
"Cache": true,
"Cart": true,
"Currency": true,
"Customer": true,
"EventBus": true,
"File": {
"cache": {
"resolve": "@medusajs/medusa/cache-inmemory",
},
"cart": {
"resolve": "@medusajs/medusa/cart",
},
"currency": {
"resolve": "@medusajs/medusa/currency",
},
"customer": {
"resolve": "@medusajs/medusa/customer",
},
"event_bus": {
"resolve": "@medusajs/medusa/event-bus-local",
},
"file": {
"options": {
"providers": [
{
@@ -38,9 +50,9 @@ describe("defineConfig", function () {
},
],
},
"resolve": "@medusajs/file",
"resolve": "@medusajs/medusa/file",
},
"Fulfillment": {
"fulfillment": {
"options": {
"providers": [
{
@@ -49,10 +61,12 @@ describe("defineConfig", function () {
},
],
},
"resolve": "@medusajs/fulfillment",
"resolve": "@medusajs/medusa/fulfillment",
},
"Inventory": true,
"Notification": {
"inventory": {
"resolve": "@medusajs/medusa/inventory-next",
},
"notification": {
"options": {
"providers": [
{
@@ -67,25 +81,47 @@ describe("defineConfig", function () {
},
],
},
"resolve": "@medusajs/notification",
"resolve": "@medusajs/medusa/notification",
},
"Order": true,
"Payment": true,
"Pricing": true,
"Product": true,
"Promotion": true,
"Region": true,
"SalesChannel": true,
"StockLocation": true,
"Store": true,
"Tax": true,
"User": {
"order": {
"resolve": "@medusajs/medusa/order",
},
"payment": {
"resolve": "@medusajs/medusa/payment",
},
"pricing": {
"resolve": "@medusajs/medusa/pricing",
},
"product": {
"resolve": "@medusajs/medusa/product",
},
"promotion": {
"resolve": "@medusajs/medusa/promotion",
},
"region": {
"resolve": "@medusajs/medusa/region",
},
"sales_channel": {
"resolve": "@medusajs/medusa/sales-channel",
},
"stock_location": {
"resolve": "@medusajs/medusa/stock-location-next",
},
"store": {
"resolve": "@medusajs/medusa/store",
},
"tax": {
"resolve": "@medusajs/medusa/tax",
},
"user": {
"options": {
"jwt_secret": "supersecret",
},
"resolve": "@medusajs/user",
"resolve": "@medusajs/medusa/user",
},
"workflows": {
"resolve": "@medusajs/medusa/workflow-engine-inmemory",
},
"Workflows": true,
},
"plugins": [],
"projectConfig": {
@@ -120,8 +156,13 @@ describe("defineConfig", function () {
},
"featureFlags": {},
"modules": {
"ApiKey": true,
"Auth": {
"GithubModuleService": {
"resolve": "./modules/github",
},
"api_key": {
"resolve": "@medusajs/medusa/api-key",
},
"auth": {
"options": {
"providers": [
{
@@ -130,14 +171,24 @@ describe("defineConfig", function () {
},
],
},
"resolve": "@medusajs/auth",
"resolve": "@medusajs/medusa/auth",
},
"Cache": true,
"Cart": true,
"Currency": true,
"Customer": true,
"EventBus": true,
"File": {
"cache": {
"resolve": "@medusajs/medusa/cache-inmemory",
},
"cart": {
"resolve": "@medusajs/medusa/cart",
},
"currency": {
"resolve": "@medusajs/medusa/currency",
},
"customer": {
"resolve": "@medusajs/medusa/customer",
},
"event_bus": {
"resolve": "@medusajs/medusa/event-bus-local",
},
"file": {
"options": {
"providers": [
{
@@ -146,9 +197,9 @@ describe("defineConfig", function () {
},
],
},
"resolve": "@medusajs/file",
"resolve": "@medusajs/medusa/file",
},
"Fulfillment": {
"fulfillment": {
"options": {
"providers": [
{
@@ -157,13 +208,12 @@ describe("defineConfig", function () {
},
],
},
"resolve": "@medusajs/fulfillment",
"resolve": "@medusajs/medusa/fulfillment",
},
"GithubModuleService": {
"resolve": "./modules/github",
"inventory": {
"resolve": "@medusajs/medusa/inventory-next",
},
"Inventory": true,
"Notification": {
"notification": {
"options": {
"providers": [
{
@@ -178,25 +228,358 @@ describe("defineConfig", function () {
},
],
},
"resolve": "@medusajs/notification",
"resolve": "@medusajs/medusa/notification",
},
"Order": true,
"Payment": true,
"Pricing": true,
"Product": true,
"Promotion": true,
"Region": true,
"SalesChannel": true,
"StockLocation": true,
"Store": true,
"Tax": true,
"User": {
"order": {
"resolve": "@medusajs/medusa/order",
},
"payment": {
"resolve": "@medusajs/medusa/payment",
},
"pricing": {
"resolve": "@medusajs/medusa/pricing",
},
"product": {
"resolve": "@medusajs/medusa/product",
},
"promotion": {
"resolve": "@medusajs/medusa/promotion",
},
"region": {
"resolve": "@medusajs/medusa/region",
},
"sales_channel": {
"resolve": "@medusajs/medusa/sales-channel",
},
"stock_location": {
"resolve": "@medusajs/medusa/stock-location-next",
},
"store": {
"resolve": "@medusajs/medusa/store",
},
"tax": {
"resolve": "@medusajs/medusa/tax",
},
"user": {
"options": {
"jwt_secret": "supersecret",
},
"resolve": "@medusajs/user",
"resolve": "@medusajs/medusa/user",
},
"workflows": {
"resolve": "@medusajs/medusa/workflow-engine-inmemory",
},
},
"plugins": [],
"projectConfig": {
"databaseUrl": "postgres://localhost/medusa-starter-default",
"http": {
"adminCors": "http://localhost:7000,http://localhost:7001,http://localhost:5173",
"authCors": "http://localhost:7000,http://localhost:7001,http://localhost:5173",
"cookieSecret": "supersecret",
"jwtSecret": "supersecret",
"storeCors": "http://localhost:8000",
},
},
}
`)
})
it("should merge custom modules when an array is provided", function () {
expect(
defineConfig({
modules: [
{
resolve: require.resolve("../__fixtures__/define-config/github"),
options: {
apiKey: "test",
},
},
],
})
).toMatchInlineSnapshot(`
{
"admin": {
"backendUrl": "http://localhost:9000",
"outDir": ".medusa/admin",
"path": "/app",
},
"featureFlags": {},
"modules": {
"GithubModuleService": {
"options": {
"apiKey": "test",
},
"resolve": "${require.resolve(
"../__fixtures__/define-config/github"
)}",
},
"api_key": {
"resolve": "@medusajs/medusa/api-key",
},
"auth": {
"options": {
"providers": [
{
"id": "emailpass",
"resolve": "@medusajs/auth-emailpass",
},
],
},
"resolve": "@medusajs/medusa/auth",
},
"cache": {
"resolve": "@medusajs/medusa/cache-inmemory",
},
"cart": {
"resolve": "@medusajs/medusa/cart",
},
"currency": {
"resolve": "@medusajs/medusa/currency",
},
"customer": {
"resolve": "@medusajs/medusa/customer",
},
"event_bus": {
"resolve": "@medusajs/medusa/event-bus-local",
},
"file": {
"options": {
"providers": [
{
"id": "local",
"resolve": "@medusajs/file-local-next",
},
],
},
"resolve": "@medusajs/medusa/file",
},
"fulfillment": {
"options": {
"providers": [
{
"id": "manual",
"resolve": "@medusajs/fulfillment-manual",
},
],
},
"resolve": "@medusajs/medusa/fulfillment",
},
"inventory": {
"resolve": "@medusajs/medusa/inventory-next",
},
"notification": {
"options": {
"providers": [
{
"id": "local",
"options": {
"channels": [
"feed",
],
"name": "Local Notification Provider",
},
"resolve": "@medusajs/notification-local",
},
],
},
"resolve": "@medusajs/medusa/notification",
},
"order": {
"resolve": "@medusajs/medusa/order",
},
"payment": {
"resolve": "@medusajs/medusa/payment",
},
"pricing": {
"resolve": "@medusajs/medusa/pricing",
},
"product": {
"resolve": "@medusajs/medusa/product",
},
"promotion": {
"resolve": "@medusajs/medusa/promotion",
},
"region": {
"resolve": "@medusajs/medusa/region",
},
"sales_channel": {
"resolve": "@medusajs/medusa/sales-channel",
},
"stock_location": {
"resolve": "@medusajs/medusa/stock-location-next",
},
"store": {
"resolve": "@medusajs/medusa/store",
},
"tax": {
"resolve": "@medusajs/medusa/tax",
},
"user": {
"options": {
"jwt_secret": "supersecret",
},
"resolve": "@medusajs/medusa/user",
},
"workflows": {
"resolve": "@medusajs/medusa/workflow-engine-inmemory",
},
},
"plugins": [],
"projectConfig": {
"databaseUrl": "postgres://localhost/medusa-starter-default",
"http": {
"adminCors": "http://localhost:7000,http://localhost:7001,http://localhost:5173",
"authCors": "http://localhost:7000,http://localhost:7001,http://localhost:5173",
"cookieSecret": "supersecret",
"jwtSecret": "supersecret",
"storeCors": "http://localhost:8000",
},
},
}
`)
})
it("should merge custom modules when an array is provided with a key to override the module registration name", function () {
expect(
defineConfig({
modules: [
{
key: "GithubModuleServiceOverride",
resolve: require.resolve("../__fixtures__/define-config/github"),
options: {
apiKey: "test",
},
},
],
})
).toMatchInlineSnapshot(`
{
"admin": {
"backendUrl": "http://localhost:9000",
"outDir": ".medusa/admin",
"path": "/app",
},
"featureFlags": {},
"modules": {
"GithubModuleServiceOverride": {
"options": {
"apiKey": "test",
},
"resolve": "${require.resolve(
"../__fixtures__/define-config/github"
)}",
},
"api_key": {
"resolve": "@medusajs/medusa/api-key",
},
"auth": {
"options": {
"providers": [
{
"id": "emailpass",
"resolve": "@medusajs/auth-emailpass",
},
],
},
"resolve": "@medusajs/medusa/auth",
},
"cache": {
"resolve": "@medusajs/medusa/cache-inmemory",
},
"cart": {
"resolve": "@medusajs/medusa/cart",
},
"currency": {
"resolve": "@medusajs/medusa/currency",
},
"customer": {
"resolve": "@medusajs/medusa/customer",
},
"event_bus": {
"resolve": "@medusajs/medusa/event-bus-local",
},
"file": {
"options": {
"providers": [
{
"id": "local",
"resolve": "@medusajs/file-local-next",
},
],
},
"resolve": "@medusajs/medusa/file",
},
"fulfillment": {
"options": {
"providers": [
{
"id": "manual",
"resolve": "@medusajs/fulfillment-manual",
},
],
},
"resolve": "@medusajs/medusa/fulfillment",
},
"inventory": {
"resolve": "@medusajs/medusa/inventory-next",
},
"notification": {
"options": {
"providers": [
{
"id": "local",
"options": {
"channels": [
"feed",
],
"name": "Local Notification Provider",
},
"resolve": "@medusajs/notification-local",
},
],
},
"resolve": "@medusajs/medusa/notification",
},
"order": {
"resolve": "@medusajs/medusa/order",
},
"payment": {
"resolve": "@medusajs/medusa/payment",
},
"pricing": {
"resolve": "@medusajs/medusa/pricing",
},
"product": {
"resolve": "@medusajs/medusa/product",
},
"promotion": {
"resolve": "@medusajs/medusa/promotion",
},
"region": {
"resolve": "@medusajs/medusa/region",
},
"sales_channel": {
"resolve": "@medusajs/medusa/sales-channel",
},
"stock_location": {
"resolve": "@medusajs/medusa/stock-location-next",
},
"store": {
"resolve": "@medusajs/medusa/store",
},
"tax": {
"resolve": "@medusajs/medusa/tax",
},
"user": {
"options": {
"jwt_secret": "supersecret",
},
"resolve": "@medusajs/medusa/user",
},
"workflows": {
"resolve": "@medusajs/medusa/workflow-engine-inmemory",
},
"Workflows": true,
},
"plugins": [],
"projectConfig": {
@@ -231,8 +614,10 @@ describe("defineConfig", function () {
},
"featureFlags": {},
"modules": {
"ApiKey": true,
"Auth": {
"api_key": {
"resolve": "@medusajs/medusa/api-key",
},
"auth": {
"options": {
"providers": [
{
@@ -241,14 +626,24 @@ describe("defineConfig", function () {
},
],
},
"resolve": "@medusajs/auth",
"resolve": "@medusajs/medusa/auth",
},
"Cache": true,
"Cart": true,
"Currency": true,
"Customer": true,
"EventBus": true,
"File": {
"cache": {
"resolve": "@medusajs/medusa/cache-inmemory",
},
"cart": {
"resolve": "@medusajs/medusa/cart",
},
"currency": {
"resolve": "@medusajs/medusa/currency",
},
"customer": {
"resolve": "@medusajs/medusa/customer",
},
"event_bus": {
"resolve": "@medusajs/medusa/event-bus-local",
},
"file": {
"options": {
"providers": [
{
@@ -257,9 +652,9 @@ describe("defineConfig", function () {
},
],
},
"resolve": "@medusajs/file",
"resolve": "@medusajs/medusa/file",
},
"Fulfillment": {
"fulfillment": {
"options": {
"providers": [
{
@@ -268,10 +663,12 @@ describe("defineConfig", function () {
},
],
},
"resolve": "@medusajs/fulfillment",
"resolve": "@medusajs/medusa/fulfillment",
},
"Inventory": true,
"Notification": {
"inventory": {
"resolve": "@medusajs/medusa/inventory-next",
},
"notification": {
"options": {
"providers": [
{
@@ -286,25 +683,47 @@ describe("defineConfig", function () {
},
],
},
"resolve": "@medusajs/notification",
"resolve": "@medusajs/medusa/notification",
},
"Order": true,
"Payment": true,
"Pricing": true,
"Product": true,
"Promotion": true,
"Region": true,
"SalesChannel": true,
"StockLocation": true,
"Store": true,
"Tax": true,
"User": {
"order": {
"resolve": "@medusajs/medusa/order",
},
"payment": {
"resolve": "@medusajs/medusa/payment",
},
"pricing": {
"resolve": "@medusajs/medusa/pricing",
},
"product": {
"resolve": "@medusajs/medusa/product",
},
"promotion": {
"resolve": "@medusajs/medusa/promotion",
},
"region": {
"resolve": "@medusajs/medusa/region",
},
"sales_channel": {
"resolve": "@medusajs/medusa/sales-channel",
},
"stock_location": {
"resolve": "@medusajs/medusa/stock-location-next",
},
"store": {
"resolve": "@medusajs/medusa/store",
},
"tax": {
"resolve": "@medusajs/medusa/tax",
},
"user": {
"options": {
"jwt_secret": "supersecret",
},
"resolve": "@medusajs/user",
"resolve": "@medusajs/medusa/user",
},
"workflows": {
"resolve": "@medusajs/medusa/workflow-engine-inmemory",
},
"Workflows": true,
},
"plugins": [],
"projectConfig": {
@@ -342,8 +761,10 @@ describe("defineConfig", function () {
},
"featureFlags": {},
"modules": {
"ApiKey": true,
"Auth": {
"api_key": {
"resolve": "@medusajs/medusa/api-key",
},
"auth": {
"options": {
"providers": [
{
@@ -352,13 +773,21 @@ describe("defineConfig", function () {
},
],
},
"resolve": "@medusajs/auth",
"resolve": "@medusajs/medusa/auth",
},
"Cache": true,
"Currency": true,
"Customer": true,
"EventBus": true,
"File": {
"cache": {
"resolve": "@medusajs/medusa/cache-inmemory",
},
"currency": {
"resolve": "@medusajs/medusa/currency",
},
"customer": {
"resolve": "@medusajs/medusa/customer",
},
"event_bus": {
"resolve": "@medusajs/medusa/event-bus-local",
},
"file": {
"options": {
"providers": [
{
@@ -367,9 +796,9 @@ describe("defineConfig", function () {
},
],
},
"resolve": "@medusajs/file",
"resolve": "@medusajs/medusa/file",
},
"Fulfillment": {
"fulfillment": {
"options": {
"providers": [
{
@@ -378,10 +807,12 @@ describe("defineConfig", function () {
},
],
},
"resolve": "@medusajs/fulfillment",
"resolve": "@medusajs/medusa/fulfillment",
},
"Inventory": true,
"Notification": {
"inventory": {
"resolve": "@medusajs/medusa/inventory-next",
},
"notification": {
"options": {
"providers": [
{
@@ -396,25 +827,47 @@ describe("defineConfig", function () {
},
],
},
"resolve": "@medusajs/notification",
"resolve": "@medusajs/medusa/notification",
},
"Order": true,
"Payment": true,
"Pricing": true,
"Product": true,
"Promotion": true,
"Region": true,
"SalesChannel": true,
"StockLocation": true,
"Store": true,
"Tax": true,
"User": {
"order": {
"resolve": "@medusajs/medusa/order",
},
"payment": {
"resolve": "@medusajs/medusa/payment",
},
"pricing": {
"resolve": "@medusajs/medusa/pricing",
},
"product": {
"resolve": "@medusajs/medusa/product",
},
"promotion": {
"resolve": "@medusajs/medusa/promotion",
},
"region": {
"resolve": "@medusajs/medusa/region",
},
"sales_channel": {
"resolve": "@medusajs/medusa/sales-channel",
},
"stock_location": {
"resolve": "@medusajs/medusa/stock-location-next",
},
"store": {
"resolve": "@medusajs/medusa/store",
},
"tax": {
"resolve": "@medusajs/medusa/tax",
},
"user": {
"options": {
"jwt_secret": "supersecret",
},
"resolve": "@medusajs/user",
"resolve": "@medusajs/medusa/user",
},
"workflows": {
"resolve": "@medusajs/medusa/workflow-engine-inmemory",
},
"Workflows": true,
},
"plugins": [],
"projectConfig": {

View File

@@ -1,5 +1,17 @@
import { ConfigModule } from "@medusajs/types"
import { Modules } from "../modules-sdk/definition"
import {
ConfigModule,
ExternalModuleDeclaration,
InternalModuleDeclaration,
} from "@medusajs/types"
import {
MODULE_PACKAGE_NAMES,
Modules,
REVERSED_MODULE_PACKAGE_NAMES,
} from "../modules-sdk"
import { isString } from "./is-string"
import { resolveExports } from "./resolve-exports"
import { isObject } from "./is-object"
import { normalizeImportPathWithSource } from "./normalize-import-path-with-source"
const DEFAULT_SECRET = "supersecret"
const DEFAULT_ADMIN_URL = "http://localhost:9000"
@@ -8,6 +20,42 @@ const DEFAULT_DATABASE_URL = "postgres://localhost/medusa-starter-default"
const DEFAULT_ADMIN_CORS =
"http://localhost:7000,http://localhost:7001,http://localhost:5173"
type InternalModuleDeclarationOverride = InternalModuleDeclaration & {
/**
* Optional key to be used to identify the module, if not provided, it will be inferred from the module joiner config service name.
*/
key?: string
/**
* By default, modules are enabled, if provided as true, this will disable the module entirely.
*/
disable?: boolean
}
type ExternalModuleDeclarationOverride = ExternalModuleDeclaration & {
/**
* key to be used to identify the module, if not provided, it will be inferred from the module joiner config service name.
*/
key: string
/**
* By default, modules are enabled, if provided as true, this will disable the module entirely.
*/
disable?: boolean
}
type Config = Partial<
Omit<ConfigModule, "admin" | "modules"> & {
admin: Partial<ConfigModule["admin"]>
modules:
| Partial<
InternalModuleDeclarationOverride | ExternalModuleDeclarationOverride
>[]
/**
* @deprecated use the array instead
*/
| ConfigModule["modules"]
}
>
/**
* The "defineConfig" helper can be used to define the configuration
* of a medusa application.
@@ -16,13 +64,7 @@ const DEFAULT_ADMIN_CORS =
* make an application work seamlessly, but still provide you the ability
* to override configuration as needed.
*/
export function defineConfig(
config: Partial<
Omit<ConfigModule, "admin"> & {
admin: Partial<ConfigModule["admin"]>
}
> = {}
): ConfigModule {
export function defineConfig(config: Config = {}): ConfigModule {
const { http, ...restOfProjectConfig } = config.projectConfig || {}
/**
@@ -61,32 +103,54 @@ export function defineConfig(
...config.featureFlags,
}
const modules = resolveModules(config.modules)
return {
projectConfig,
featureFlags,
plugins: config.plugins || [],
admin,
modules: modules,
}
}
/**
* The user API allow to use array of modules configuration. This method manage the loading of the user modules
* along side the default modules and re map them to an object.
*
* @param configModules
*/
function resolveModules(
configModules: Config["modules"]
): ConfigModule["modules"] {
/**
* The default set of modules to always use. The end user can swap
* the modules by providing an alternate implementation via their
* config. But they can never remove a module from this list.
*/
const modules: ConfigModule["modules"] = {
[Modules.CACHE]: true,
[Modules.EVENT_BUS]: true,
[Modules.WORKFLOW_ENGINE]: true,
[Modules.STOCK_LOCATION]: true,
[Modules.INVENTORY]: true,
[Modules.PRODUCT]: true,
[Modules.PRICING]: true,
[Modules.PROMOTION]: true,
[Modules.CUSTOMER]: true,
[Modules.SALES_CHANNEL]: true,
[Modules.CART]: true,
[Modules.REGION]: true,
[Modules.API_KEY]: true,
[Modules.STORE]: true,
[Modules.TAX]: true,
[Modules.CURRENCY]: true,
[Modules.PAYMENT]: true,
[Modules.ORDER]: true,
[Modules.AUTH]: {
resolve: "@medusajs/auth",
const modules: Config["modules"] = [
{ resolve: MODULE_PACKAGE_NAMES[Modules.CACHE] },
{ resolve: MODULE_PACKAGE_NAMES[Modules.EVENT_BUS] },
{ resolve: MODULE_PACKAGE_NAMES[Modules.WORKFLOW_ENGINE] },
{ resolve: MODULE_PACKAGE_NAMES[Modules.STOCK_LOCATION] },
{ resolve: MODULE_PACKAGE_NAMES[Modules.INVENTORY] },
{ resolve: MODULE_PACKAGE_NAMES[Modules.PRODUCT] },
{ resolve: MODULE_PACKAGE_NAMES[Modules.PRICING] },
{ resolve: MODULE_PACKAGE_NAMES[Modules.PROMOTION] },
{ resolve: MODULE_PACKAGE_NAMES[Modules.CUSTOMER] },
{ resolve: MODULE_PACKAGE_NAMES[Modules.SALES_CHANNEL] },
{ resolve: MODULE_PACKAGE_NAMES[Modules.CART] },
{ resolve: MODULE_PACKAGE_NAMES[Modules.REGION] },
{ resolve: MODULE_PACKAGE_NAMES[Modules.API_KEY] },
{ resolve: MODULE_PACKAGE_NAMES[Modules.STORE] },
{ resolve: MODULE_PACKAGE_NAMES[Modules.TAX] },
{ resolve: MODULE_PACKAGE_NAMES[Modules.CURRENCY] },
{ resolve: MODULE_PACKAGE_NAMES[Modules.PAYMENT] },
{ resolve: MODULE_PACKAGE_NAMES[Modules.ORDER] },
{
resolve: MODULE_PACKAGE_NAMES[Modules.AUTH],
options: {
providers: [
{
@@ -96,15 +160,14 @@ export function defineConfig(
],
},
},
[Modules.USER]: {
resolve: "@medusajs/user",
{
resolve: MODULE_PACKAGE_NAMES[Modules.USER],
options: {
jwt_secret: process.env.JWT_SECRET ?? DEFAULT_SECRET,
},
},
[Modules.FILE]: {
resolve: "@medusajs/file",
{
resolve: MODULE_PACKAGE_NAMES[Modules.FILE],
options: {
providers: [
{
@@ -114,8 +177,8 @@ export function defineConfig(
],
},
},
[Modules.FULFILLMENT]: {
resolve: "@medusajs/fulfillment",
{
resolve: MODULE_PACKAGE_NAMES[Modules.FULFILLMENT],
options: {
providers: [
{
@@ -125,8 +188,8 @@ export function defineConfig(
],
},
},
[Modules.NOTIFICATION]: {
resolve: "@medusajs/notification",
{
resolve: MODULE_PACKAGE_NAMES[Modules.NOTIFICATION],
options: {
providers: [
{
@@ -140,21 +203,95 @@ export function defineConfig(
],
},
},
...config.modules,
]
/**
* Backward compatibility for the old way of defining modules (object vs array)
*/
if (configModules) {
if (isObject(configModules)) {
const modules_ = (configModules ??
{}) as unknown as Required<ConfigModule>["modules"]
Object.entries(modules_).forEach(([key, moduleConfig]) => {
modules.push({
key,
...(isObject(moduleConfig)
? moduleConfig
: { disable: !moduleConfig }),
})
})
} else if (Array.isArray(configModules)) {
const modules_ = (configModules ?? []) as InternalModuleDeclaration[]
modules.push(...modules_)
} else {
throw new Error(
"Invalid modules configuration. Should be an array or object."
)
}
}
const remappedModules = modules.reduce((acc, moduleConfig) => {
if (moduleConfig.scope === "external" && !moduleConfig.key) {
throw new Error(
"External modules configuration must have a 'key'. Please provide a key for the module."
)
}
if ("disable" in moduleConfig && "key" in moduleConfig) {
acc[moduleConfig.key!] = moduleConfig
}
// TODO: handle external modules later
let serviceName: string =
"key" in moduleConfig && moduleConfig.key ? moduleConfig.key : ""
delete moduleConfig.key
if (!serviceName && "resolve" in moduleConfig) {
if (
isString(moduleConfig.resolve!) &&
REVERSED_MODULE_PACKAGE_NAMES[moduleConfig.resolve!]
) {
serviceName = REVERSED_MODULE_PACKAGE_NAMES[moduleConfig.resolve!]
acc[serviceName] = moduleConfig
return acc
}
let resolution = isString(moduleConfig.resolve!)
? normalizeImportPathWithSource(moduleConfig.resolve as string)
: moduleConfig.resolve
const moduleExport = isString(resolution)
? require(resolution)
: resolution
const defaultExport = resolveExports(moduleExport).default
const joinerConfig =
typeof defaultExport.service.prototype.__joinerConfig === "function"
? defaultExport.service.prototype.__joinerConfig() ?? {}
: defaultExport.service.prototype.__joinerConfig ?? {}
serviceName = joinerConfig.serviceName
if (!serviceName) {
throw new Error(
`Module ${moduleConfig.resolve} doesn't have a serviceName. Please provide a 'key' for the module or check the service joiner config.`
)
}
}
acc[serviceName] = moduleConfig
return acc
}, {})
// Remove any modules set to false
Object.keys(modules).forEach((key) => {
if (modules[key] === false) {
delete modules[key]
Object.keys(remappedModules).forEach((key) => {
if (remappedModules[key].disable) {
delete remappedModules[key]
}
})
return {
projectConfig,
featureFlags,
plugins: config.plugins || [],
admin,
modules,
}
return remappedModules as ConfigModule["modules"]
}