feat: Merge plugin modules (#10895)
Fixes: FRMW-2858 This PR merge the modules exported by the plugins with the modules defined within the user config. As a result, all modules get loaded without changing the internals of the loader. However, you cannot disable the module of a plugin by re-adding it to the `modules` array. That is something we should handle separately. We've added the breaking change label because of the following fix: We did broke the ability to completely disable modules in the past pr's, in this pr we re add the ability to disable a module and that this modules does not get loaded at all. ([here](https://github.com/medusajs/medusa/pull/10895/commits/6dd164f783d632c927e0a48c50090dcf7387ccdd)) Co-authored-by: Adrien de Peretti <25098370+adrien2p@users.noreply.github.com>
This commit is contained in:
co-authored by
Adrien de Peretti
parent
a607b8e800
commit
c1930bd656
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
"@medusajs/medusa": patch
|
||||||
|
"@medusajs/types": patch
|
||||||
|
"@medusajs/utils": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Feat/merge plugin modules
|
||||||
@@ -106,7 +106,8 @@ export async function loadModules(args: {
|
|||||||
let declaration: any = {}
|
let declaration: any = {}
|
||||||
let definition: Partial<ModuleDefinition> | undefined = undefined
|
let definition: Partial<ModuleDefinition> | undefined = undefined
|
||||||
|
|
||||||
if (mod === false) {
|
// TODO: We are keeping mod === false for backward compatibility for now
|
||||||
|
if (mod === false || (isObject(mod) && "disable" in mod && mod.disable)) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -944,6 +944,13 @@ type ExternalModuleDeclarationOverride = ExternalModuleDeclaration & {
|
|||||||
disable?: boolean
|
disable?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modules accepted by the defineConfig function
|
||||||
|
*/
|
||||||
|
export type InputConfigModules = Partial<
|
||||||
|
InternalModuleDeclarationOverride | ExternalModuleDeclarationOverride
|
||||||
|
>[]
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The configuration accepted by the "defineConfig" helper
|
* The configuration accepted by the "defineConfig" helper
|
||||||
*/
|
*/
|
||||||
@@ -951,9 +958,7 @@ export type InputConfig = Partial<
|
|||||||
Omit<ConfigModule, "admin" | "modules"> & {
|
Omit<ConfigModule, "admin" | "modules"> & {
|
||||||
admin: Partial<ConfigModule["admin"]>
|
admin: Partial<ConfigModule["admin"]>
|
||||||
modules:
|
modules:
|
||||||
| Partial<
|
| InputConfigModules
|
||||||
InternalModuleDeclarationOverride | ExternalModuleDeclarationOverride
|
|
||||||
>[]
|
|
||||||
/**
|
/**
|
||||||
* @deprecated use the array instead
|
* @deprecated use the array instead
|
||||||
*/
|
*/
|
||||||
@@ -967,5 +972,5 @@ export type PluginDetails = {
|
|||||||
id: string
|
id: string
|
||||||
options: Record<string, unknown>
|
options: Record<string, unknown>
|
||||||
version: string
|
version: string
|
||||||
modules?: InputConfig["modules"]
|
modules?: InputConfigModules
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -800,7 +800,7 @@ describe("defineConfig", function () {
|
|||||||
`)
|
`)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should not include disabled modules", function () {
|
it("should include disabled modules", function () {
|
||||||
expect(
|
expect(
|
||||||
defineConfig({
|
defineConfig({
|
||||||
projectConfig: {
|
projectConfig: {
|
||||||
@@ -837,6 +837,9 @@ describe("defineConfig", function () {
|
|||||||
"cache": {
|
"cache": {
|
||||||
"resolve": "@medusajs/medusa/cache-inmemory",
|
"resolve": "@medusajs/medusa/cache-inmemory",
|
||||||
},
|
},
|
||||||
|
"cart": {
|
||||||
|
"disable": true,
|
||||||
|
},
|
||||||
"currency": {
|
"currency": {
|
||||||
"resolve": "@medusajs/medusa/currency",
|
"resolve": "@medusajs/medusa/currency",
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
import { MODULE_PACKAGE_NAMES, Modules } from "../../modules-sdk"
|
||||||
|
import { transformModules } from "../define-config"
|
||||||
|
|
||||||
|
describe("transformModules", () => {
|
||||||
|
test("convert array of modules to an object", () => {
|
||||||
|
const modules = transformModules([
|
||||||
|
{
|
||||||
|
resolve: require.resolve("../__fixtures__/define-config/github"),
|
||||||
|
options: {
|
||||||
|
apiKey: "test",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
expect(modules).toEqual({
|
||||||
|
GithubModuleService: {
|
||||||
|
options: {
|
||||||
|
apiKey: "test",
|
||||||
|
},
|
||||||
|
resolve: require.resolve("../__fixtures__/define-config/github"),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test("transform default module", () => {
|
||||||
|
const modules = transformModules([
|
||||||
|
{
|
||||||
|
resolve: MODULE_PACKAGE_NAMES[Modules.CACHE],
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
expect(modules).toEqual({
|
||||||
|
cache: {
|
||||||
|
resolve: "@medusajs/medusa/cache-inmemory",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test("should manage loading priority of modules when its disabled at a later stage in the array", () => {
|
||||||
|
const modules = transformModules([
|
||||||
|
{
|
||||||
|
resolve: MODULE_PACKAGE_NAMES[Modules.CACHE],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
resolve: MODULE_PACKAGE_NAMES[Modules.CACHE],
|
||||||
|
disable: true,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
expect(modules).toEqual({
|
||||||
|
cache: {
|
||||||
|
resolve: MODULE_PACKAGE_NAMES[Modules.CACHE],
|
||||||
|
disable: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test("should manage loading priority of modules when its not disabled at a later stage in the array", () => {
|
||||||
|
const modules = transformModules([
|
||||||
|
{
|
||||||
|
resolve: MODULE_PACKAGE_NAMES[Modules.CACHE],
|
||||||
|
disable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
resolve: MODULE_PACKAGE_NAMES[Modules.CACHE],
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
expect(modules).toEqual({
|
||||||
|
cache: {
|
||||||
|
resolve: MODULE_PACKAGE_NAMES[Modules.CACHE],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
ConfigModule,
|
ConfigModule,
|
||||||
InputConfig,
|
InputConfig,
|
||||||
|
InputConfigModules,
|
||||||
InternalModuleDeclaration,
|
InternalModuleDeclaration,
|
||||||
} from "@medusajs/types"
|
} from "@medusajs/types"
|
||||||
import {
|
import {
|
||||||
@@ -108,14 +109,79 @@ export function defineConfig(config: InputConfig = {}): ConfigModule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The user API allow to use array of modules configuration. This method manage the loading of the user modules
|
* Transforms an array of modules into an object. The last module will
|
||||||
* along side the default modules and re map them to an object.
|
* take precedence in case of duplicate modules
|
||||||
|
*/
|
||||||
|
export function transformModules(
|
||||||
|
modules: InputConfigModules
|
||||||
|
): Exclude<ConfigModule["modules"], undefined> {
|
||||||
|
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
|
||||||
|
}, {})
|
||||||
|
|
||||||
|
return remappedModules as Exclude<ConfigModule["modules"], undefined>
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
* @param configModules
|
||||||
*/
|
*/
|
||||||
function resolveModules(
|
function resolveModules(
|
||||||
configModules: InputConfig["modules"]
|
configModules: InputConfig["modules"]
|
||||||
): ConfigModule["modules"] {
|
): Exclude<ConfigModule["modules"], undefined> {
|
||||||
/**
|
/**
|
||||||
* The default set of modules to always use. The end user can swap
|
* The default set of modules to always use. The end user can swap
|
||||||
* the modules by providing an alternate implementation via their
|
* the modules by providing an alternate implementation via their
|
||||||
@@ -225,67 +291,5 @@ function resolveModules(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const remappedModules = modules.reduce((acc, moduleConfig) => {
|
return transformModules(modules)
|
||||||
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(remappedModules).forEach((key) => {
|
|
||||||
if (remappedModules[key].disable) {
|
|
||||||
delete remappedModules[key]
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return remappedModules as ConfigModule["modules"]
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,3 +80,4 @@ export * from "./trim-zeros"
|
|||||||
export * from "./upper-case-first"
|
export * from "./upper-case-first"
|
||||||
export * from "./validate-handle"
|
export * from "./validate-handle"
|
||||||
export * from "./wrap-handler"
|
export * from "./wrap-handler"
|
||||||
|
export * from "./merge-plugin-modules"
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import type {
|
||||||
|
PluginDetails,
|
||||||
|
ConfigModule,
|
||||||
|
InputConfigModules,
|
||||||
|
} from "@medusajs/types"
|
||||||
|
import { transformModules } from "./define-config"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mutates the configModules object and merges the plugin modules with
|
||||||
|
* the modules defined inside the user-config file
|
||||||
|
*/
|
||||||
|
export function mergePluginModules(
|
||||||
|
configModule: ConfigModule,
|
||||||
|
plugins: PluginDetails[]
|
||||||
|
) {
|
||||||
|
/**
|
||||||
|
* Create a flat array of all the modules exposed by the registered
|
||||||
|
* plugins
|
||||||
|
*/
|
||||||
|
const pluginsModules = plugins.reduce((result, plugin) => {
|
||||||
|
if (plugin.modules) {
|
||||||
|
result = result.concat(plugin.modules)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}, [] as InputConfigModules)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merge plugin modules with the modules defined within the
|
||||||
|
* config file.
|
||||||
|
*/
|
||||||
|
configModule.modules = {
|
||||||
|
...transformModules(pluginsModules),
|
||||||
|
...configModule.modules,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ import { join } from "path"
|
|||||||
import {
|
import {
|
||||||
ContainerRegistrationKeys,
|
ContainerRegistrationKeys,
|
||||||
MedusaError,
|
MedusaError,
|
||||||
|
mergePluginModules,
|
||||||
} from "@medusajs/framework/utils"
|
} from "@medusajs/framework/utils"
|
||||||
import { LinkLoader } from "@medusajs/framework/links"
|
import { LinkLoader } from "@medusajs/framework/links"
|
||||||
import { logger } from "@medusajs/framework/logger"
|
import { logger } from "@medusajs/framework/logger"
|
||||||
@@ -27,6 +28,8 @@ const main = async function ({ directory, modules }) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
const plugins = await getResolvedPlugins(directory, configModule, true)
|
const plugins = await getResolvedPlugins(directory, configModule, true)
|
||||||
|
mergePluginModules(configModule, plugins)
|
||||||
|
|
||||||
const linksSourcePaths = plugins.map((plugin) =>
|
const linksSourcePaths = plugins.map((plugin) =>
|
||||||
join(plugin.resolve, "links")
|
join(plugin.resolve, "links")
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
import { join } from "path"
|
import { join } from "path"
|
||||||
import { ContainerRegistrationKeys } from "@medusajs/framework/utils"
|
import {
|
||||||
|
ContainerRegistrationKeys,
|
||||||
|
mergePluginModules,
|
||||||
|
} from "@medusajs/framework/utils"
|
||||||
import { LinkLoader } from "@medusajs/framework/links"
|
import { LinkLoader } from "@medusajs/framework/links"
|
||||||
import { logger } from "@medusajs/framework/logger"
|
import { logger } from "@medusajs/framework/logger"
|
||||||
import { MedusaAppLoader } from "@medusajs/framework"
|
import { MedusaAppLoader } from "@medusajs/framework"
|
||||||
@@ -38,6 +41,8 @@ export async function migrate({
|
|||||||
)
|
)
|
||||||
|
|
||||||
const plugins = await getResolvedPlugins(directory, configModule, true)
|
const plugins = await getResolvedPlugins(directory, configModule, true)
|
||||||
|
mergePluginModules(configModule, plugins)
|
||||||
|
|
||||||
const linksSourcePaths = plugins.map((plugin) =>
|
const linksSourcePaths = plugins.map((plugin) =>
|
||||||
join(plugin.resolve, "links")
|
join(plugin.resolve, "links")
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { join } from "path"
|
|||||||
import {
|
import {
|
||||||
ContainerRegistrationKeys,
|
ContainerRegistrationKeys,
|
||||||
MedusaError,
|
MedusaError,
|
||||||
|
mergePluginModules,
|
||||||
} from "@medusajs/framework/utils"
|
} from "@medusajs/framework/utils"
|
||||||
import { LinkLoader } from "@medusajs/framework/links"
|
import { LinkLoader } from "@medusajs/framework/links"
|
||||||
import { logger } from "@medusajs/framework/logger"
|
import { logger } from "@medusajs/framework/logger"
|
||||||
@@ -27,6 +28,8 @@ const main = async function ({ directory, modules }) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
const plugins = await getResolvedPlugins(directory, configModule, true)
|
const plugins = await getResolvedPlugins(directory, configModule, true)
|
||||||
|
mergePluginModules(configModule, plugins)
|
||||||
|
|
||||||
const linksSourcePaths = plugins.map((plugin) =>
|
const linksSourcePaths = plugins.map((plugin) =>
|
||||||
join(plugin.resolve, "links")
|
join(plugin.resolve, "links")
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -2,7 +2,10 @@ import boxen from "boxen"
|
|||||||
import chalk from "chalk"
|
import chalk from "chalk"
|
||||||
import { join } from "path"
|
import { join } from "path"
|
||||||
import checkbox from "@inquirer/checkbox"
|
import checkbox from "@inquirer/checkbox"
|
||||||
import { ContainerRegistrationKeys } from "@medusajs/framework/utils"
|
import {
|
||||||
|
ContainerRegistrationKeys,
|
||||||
|
mergePluginModules,
|
||||||
|
} from "@medusajs/framework/utils"
|
||||||
import { LinkMigrationsPlannerAction } from "@medusajs/framework/types"
|
import { LinkMigrationsPlannerAction } from "@medusajs/framework/types"
|
||||||
import { LinkLoader } from "@medusajs/framework/links"
|
import { LinkLoader } from "@medusajs/framework/links"
|
||||||
import { logger } from "@medusajs/framework/logger"
|
import { logger } from "@medusajs/framework/logger"
|
||||||
@@ -188,6 +191,8 @@ const main = async function ({ directory, executeSafe, executeAll }) {
|
|||||||
const medusaAppLoader = new MedusaAppLoader()
|
const medusaAppLoader = new MedusaAppLoader()
|
||||||
|
|
||||||
const plugins = await getResolvedPlugins(directory, configModule, true)
|
const plugins = await getResolvedPlugins(directory, configModule, true)
|
||||||
|
mergePluginModules(configModule, plugins)
|
||||||
|
|
||||||
const linksSourcePaths = plugins.map((plugin) =>
|
const linksSourcePaths = plugins.map((plugin) =>
|
||||||
join(plugin.resolve, "links")
|
join(plugin.resolve, "links")
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ describe("getResolvedPlugins | relative paths", () => {
|
|||||||
|
|
||||||
expect(plugins).toEqual([
|
expect(plugins).toEqual([
|
||||||
{
|
{
|
||||||
resolve: path.join(fs.basePath, "./plugins/dummy/build"),
|
resolve: path.join(fs.basePath, "./plugins/dummy/.medusa/server/src"),
|
||||||
name: "my-dummy-plugin",
|
name: "my-dummy-plugin",
|
||||||
id: "my-dummy-plugin",
|
id: "my-dummy-plugin",
|
||||||
options: { apiKey: "asecret" },
|
options: { apiKey: "asecret" },
|
||||||
@@ -48,7 +48,10 @@ describe("getResolvedPlugins | relative paths", () => {
|
|||||||
name: "my-dummy-plugin",
|
name: "my-dummy-plugin",
|
||||||
version: "1.0.0",
|
version: "1.0.0",
|
||||||
})
|
})
|
||||||
await fs.create("plugins/dummy/build/modules/blog/index.js", ``)
|
await fs.create(
|
||||||
|
"plugins/dummy/.medusa/server/src/modules/blog/index.js",
|
||||||
|
``
|
||||||
|
)
|
||||||
|
|
||||||
const plugins = await getResolvedPlugins(
|
const plugins = await getResolvedPlugins(
|
||||||
fs.basePath,
|
fs.basePath,
|
||||||
@@ -67,7 +70,7 @@ describe("getResolvedPlugins | relative paths", () => {
|
|||||||
|
|
||||||
expect(plugins).toEqual([
|
expect(plugins).toEqual([
|
||||||
{
|
{
|
||||||
resolve: path.join(fs.basePath, "./plugins/dummy/build"),
|
resolve: path.join(fs.basePath, "./plugins/dummy/.medusa/server/src"),
|
||||||
name: "my-dummy-plugin",
|
name: "my-dummy-plugin",
|
||||||
id: "my-dummy-plugin",
|
id: "my-dummy-plugin",
|
||||||
options: { apiKey: "asecret" },
|
options: { apiKey: "asecret" },
|
||||||
@@ -77,7 +80,7 @@ describe("getResolvedPlugins | relative paths", () => {
|
|||||||
options: {
|
options: {
|
||||||
apiKey: "asecret",
|
apiKey: "asecret",
|
||||||
},
|
},
|
||||||
resolve: "./plugins/dummy/build/modules/blog",
|
resolve: "./plugins/dummy/.medusa/server/src/modules/blog",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -132,7 +135,10 @@ describe("getResolvedPlugins | package reference", () => {
|
|||||||
|
|
||||||
expect(plugins).toEqual([
|
expect(plugins).toEqual([
|
||||||
{
|
{
|
||||||
resolve: path.join(fs.basePath, "node_modules/@plugins/dummy/build"),
|
resolve: path.join(
|
||||||
|
fs.basePath,
|
||||||
|
"node_modules/@plugins/dummy/.medusa/server/src"
|
||||||
|
),
|
||||||
name: "my-dummy-plugin",
|
name: "my-dummy-plugin",
|
||||||
id: "my-dummy-plugin",
|
id: "my-dummy-plugin",
|
||||||
options: { apiKey: "asecret" },
|
options: { apiKey: "asecret" },
|
||||||
@@ -149,7 +155,7 @@ describe("getResolvedPlugins | package reference", () => {
|
|||||||
version: "1.0.0",
|
version: "1.0.0",
|
||||||
})
|
})
|
||||||
await fs.create(
|
await fs.create(
|
||||||
"node_modules/@plugins/dummy/build/modules/blog/index.js",
|
"node_modules/@plugins/dummy/.medusa/server/src/modules/blog/index.js",
|
||||||
``
|
``
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -170,7 +176,10 @@ describe("getResolvedPlugins | package reference", () => {
|
|||||||
|
|
||||||
expect(plugins).toEqual([
|
expect(plugins).toEqual([
|
||||||
{
|
{
|
||||||
resolve: path.join(fs.basePath, "node_modules/@plugins/dummy/build"),
|
resolve: path.join(
|
||||||
|
fs.basePath,
|
||||||
|
"node_modules/@plugins/dummy/.medusa/server/src"
|
||||||
|
),
|
||||||
name: "my-dummy-plugin",
|
name: "my-dummy-plugin",
|
||||||
id: "my-dummy-plugin",
|
id: "my-dummy-plugin",
|
||||||
options: { apiKey: "asecret" },
|
options: { apiKey: "asecret" },
|
||||||
@@ -180,7 +189,7 @@ describe("getResolvedPlugins | package reference", () => {
|
|||||||
options: {
|
options: {
|
||||||
apiKey: "asecret",
|
apiKey: "asecret",
|
||||||
},
|
},
|
||||||
resolve: "@plugins/dummy/build/modules/blog",
|
resolve: "@plugins/dummy/.medusa/server/src/modules/blog",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { isString, readDir } from "@medusajs/framework/utils"
|
|||||||
import { ConfigModule, PluginDetails } from "@medusajs/framework/types"
|
import { ConfigModule, PluginDetails } from "@medusajs/framework/types"
|
||||||
|
|
||||||
const MEDUSA_APP_SOURCE_PATH = "src"
|
const MEDUSA_APP_SOURCE_PATH = "src"
|
||||||
|
const MEDUSA_PLUGIN_SOURCE_PATH = ".medusa/server/src"
|
||||||
export const MEDUSA_PROJECT_NAME = "project-plugin"
|
export const MEDUSA_PROJECT_NAME = "project-plugin"
|
||||||
|
|
||||||
function createPluginId(name: string): string {
|
function createPluginId(name: string): string {
|
||||||
@@ -57,11 +58,8 @@ async function resolvePlugin(
|
|||||||
const resolvedPath = path.dirname(pkgJSON.path)
|
const resolvedPath = path.dirname(pkgJSON.path)
|
||||||
|
|
||||||
const name = pkgJSON.contents.name || pluginPath
|
const name = pkgJSON.contents.name || pluginPath
|
||||||
const srcDir = pkgJSON.contents.main
|
|
||||||
? path.dirname(pkgJSON.contents.main)
|
|
||||||
: "build"
|
|
||||||
|
|
||||||
const resolve = path.join(resolvedPath, srcDir)
|
const resolve = path.join(resolvedPath, MEDUSA_PLUGIN_SOURCE_PATH)
|
||||||
const modules = await readDir(path.join(resolve, "modules"), {
|
const modules = await readDir(path.join(resolve, "modules"), {
|
||||||
ignoreMissing: true,
|
ignoreMissing: true,
|
||||||
})
|
})
|
||||||
@@ -75,7 +73,7 @@ async function resolvePlugin(
|
|||||||
version: pkgJSON.contents.version || "0.0.0",
|
version: pkgJSON.contents.version || "0.0.0",
|
||||||
modules: modules.map((mod) => {
|
modules: modules.map((mod) => {
|
||||||
return {
|
return {
|
||||||
resolve: `${pluginPath}/${srcDir}/modules/${mod.name}`,
|
resolve: `${pluginPath}/${MEDUSA_PLUGIN_SOURCE_PATH}/modules/${mod.name}`,
|
||||||
options: pluginOptions,
|
options: pluginOptions,
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
import {
|
import {
|
||||||
ContainerRegistrationKeys,
|
ContainerRegistrationKeys,
|
||||||
GraphQLSchema,
|
GraphQLSchema,
|
||||||
|
mergePluginModules,
|
||||||
promiseAll,
|
promiseAll,
|
||||||
} from "@medusajs/framework/utils"
|
} from "@medusajs/framework/utils"
|
||||||
import { asValue } from "awilix"
|
import { asValue } from "awilix"
|
||||||
@@ -147,6 +148,8 @@ export default async ({
|
|||||||
)
|
)
|
||||||
|
|
||||||
const plugins = await getResolvedPlugins(rootDirectory, configModule, true)
|
const plugins = await getResolvedPlugins(rootDirectory, configModule, true)
|
||||||
|
mergePluginModules(configModule, plugins)
|
||||||
|
|
||||||
const linksSourcePaths = plugins.map((plugin) =>
|
const linksSourcePaths = plugins.map((plugin) =>
|
||||||
join(plugin.resolve, "links")
|
join(plugin.resolve, "links")
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user