feat: remove dead code and refactor the logic of resolving plugins (#10874)
This commit is contained in:
@@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
"@medusajs/medusa": patch
|
||||||
|
"@medusajs/test-utils": patch
|
||||||
|
"@medusajs/types": patch
|
||||||
|
"@medusajs/utils": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
feat: remove dead code and refactor the logic of resolving plugins
|
||||||
@@ -922,10 +922,50 @@ export type ConfigModule = {
|
|||||||
featureFlags: Record<string, boolean | string | Record<string, boolean>>
|
featureFlags: Record<string, boolean | string | Record<string, boolean>>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The configuration accepted by the "defineConfig" helper
|
||||||
|
*/
|
||||||
|
export type InputConfig = Partial<
|
||||||
|
Omit<ConfigModule, "admin" | "modules"> & {
|
||||||
|
admin: Partial<ConfigModule["admin"]>
|
||||||
|
modules:
|
||||||
|
| Partial<
|
||||||
|
InternalModuleDeclarationOverride | ExternalModuleDeclarationOverride
|
||||||
|
>[]
|
||||||
|
/**
|
||||||
|
* @deprecated use the array instead
|
||||||
|
*/
|
||||||
|
| ConfigModule["modules"]
|
||||||
|
}
|
||||||
|
>
|
||||||
|
|
||||||
export type PluginDetails = {
|
export type PluginDetails = {
|
||||||
resolve: string
|
resolve: string
|
||||||
name: string
|
name: string
|
||||||
id: string
|
id: string
|
||||||
options: Record<string, unknown>
|
options: Record<string, unknown>
|
||||||
version: string
|
version: string
|
||||||
|
modules?: InputConfig["modules"]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import {
|
import {
|
||||||
ConfigModule,
|
ConfigModule,
|
||||||
ExternalModuleDeclaration,
|
InputConfig,
|
||||||
InternalModuleDeclaration,
|
InternalModuleDeclaration,
|
||||||
} from "@medusajs/types"
|
} from "@medusajs/types"
|
||||||
import {
|
import {
|
||||||
@@ -29,42 +29,6 @@ export const DEFAULT_STORE_RESTRICTED_FIELDS = [
|
|||||||
"payment_collections"*/
|
"payment_collections"*/
|
||||||
]
|
]
|
||||||
|
|
||||||
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
|
* The "defineConfig" helper can be used to define the configuration
|
||||||
* of a medusa application.
|
* of a medusa application.
|
||||||
@@ -73,7 +37,7 @@ type Config = Partial<
|
|||||||
* make an application work seamlessly, but still provide you the ability
|
* make an application work seamlessly, but still provide you the ability
|
||||||
* to override configuration as needed.
|
* to override configuration as needed.
|
||||||
*/
|
*/
|
||||||
export function defineConfig(config: Config = {}): ConfigModule {
|
export function defineConfig(config: InputConfig = {}): ConfigModule {
|
||||||
const { http, redisOptions, ...restOfProjectConfig } =
|
const { http, redisOptions, ...restOfProjectConfig } =
|
||||||
config.projectConfig || {}
|
config.projectConfig || {}
|
||||||
|
|
||||||
@@ -150,14 +114,14 @@ export function defineConfig(config: Config = {}): ConfigModule {
|
|||||||
* @param configModules
|
* @param configModules
|
||||||
*/
|
*/
|
||||||
function resolveModules(
|
function resolveModules(
|
||||||
configModules: Config["modules"]
|
configModules: InputConfig["modules"]
|
||||||
): ConfigModule["modules"] {
|
): ConfigModule["modules"] {
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
* config. But they can never remove a module from this list.
|
* config. But they can never remove a module from this list.
|
||||||
*/
|
*/
|
||||||
const modules: Config["modules"] = [
|
const modules: InputConfig["modules"] = [
|
||||||
{ resolve: MODULE_PACKAGE_NAMES[Modules.CACHE] },
|
{ resolve: MODULE_PACKAGE_NAMES[Modules.CACHE] },
|
||||||
{ resolve: MODULE_PACKAGE_NAMES[Modules.EVENT_BUS] },
|
{ resolve: MODULE_PACKAGE_NAMES[Modules.EVENT_BUS] },
|
||||||
{ resolve: MODULE_PACKAGE_NAMES[Modules.WORKFLOW_ENGINE] },
|
{ resolve: MODULE_PACKAGE_NAMES[Modules.WORKFLOW_ENGINE] },
|
||||||
|
|||||||
@@ -2,21 +2,51 @@ import { Dirent } from "fs"
|
|||||||
import { readdir } from "fs/promises"
|
import { readdir } from "fs/promises"
|
||||||
import { join } from "path"
|
import { join } from "path"
|
||||||
|
|
||||||
export async function readDirRecursive(dir: string): Promise<Dirent[]> {
|
const MISSING_NODE_ERRORS = ["ENOTDIR", "ENOENT"]
|
||||||
let allEntries: Dirent[] = []
|
|
||||||
const readRecursive = async (dir) => {
|
export async function readDir(
|
||||||
|
dir: string,
|
||||||
|
options?: {
|
||||||
|
ignoreMissing?: boolean
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
try {
|
||||||
const entries = await readdir(dir, { withFileTypes: true })
|
const entries = await readdir(dir, { withFileTypes: true })
|
||||||
|
return entries
|
||||||
|
} catch (error) {
|
||||||
|
if (options?.ignoreMissing && MISSING_NODE_ERRORS.includes(error.code)) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (const entry of entries) {
|
export async function readDirRecursive(
|
||||||
const fullPath = join(dir, entry.name)
|
dir: string,
|
||||||
Object.defineProperty(entry, "path", {
|
options?: {
|
||||||
value: dir,
|
ignoreMissing?: boolean
|
||||||
})
|
}
|
||||||
allEntries.push(entry)
|
): Promise<Dirent[]> {
|
||||||
|
let allEntries: Dirent[] = []
|
||||||
|
const readRecursive = async (dir: string) => {
|
||||||
|
try {
|
||||||
|
const entries = await readdir(dir, { withFileTypes: true })
|
||||||
|
for (const entry of entries) {
|
||||||
|
const fullPath = join(dir, entry.name)
|
||||||
|
Object.defineProperty(entry, "path", {
|
||||||
|
value: dir,
|
||||||
|
})
|
||||||
|
allEntries.push(entry)
|
||||||
|
|
||||||
if (entry.isDirectory()) {
|
if (entry.isDirectory()) {
|
||||||
await readRecursive(fullPath)
|
await readRecursive(fullPath)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
|
if (options?.ignoreMissing && error.code === "ENOENT") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
throw error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ async function loadCustomLinks(directory: string, container: MedusaContainer) {
|
|||||||
const configModule = container.resolve(
|
const configModule = container.resolve(
|
||||||
ContainerRegistrationKeys.CONFIG_MODULE
|
ContainerRegistrationKeys.CONFIG_MODULE
|
||||||
)
|
)
|
||||||
const plugins = getResolvedPlugins(directory, configModule, true) || []
|
const plugins = await getResolvedPlugins(directory, configModule, true)
|
||||||
const linksSourcePaths = plugins.map((plugin) =>
|
const linksSourcePaths = plugins.map((plugin) =>
|
||||||
join(plugin.resolve, "links")
|
join(plugin.resolve, "links")
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -40,7 +40,7 @@
|
|||||||
"watch": "tsc --build --watch",
|
"watch": "tsc --build --watch",
|
||||||
"build": "rimraf dist && tsc --build",
|
"build": "rimraf dist && tsc --build",
|
||||||
"serve": "node dist/app.js",
|
"serve": "node dist/app.js",
|
||||||
"test": "jest --silent --bail --maxWorkers=50% --forceExit"
|
"test": "jest --silent=false --bail --maxWorkers=50% --forceExit"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@medusajs/framework": "^2.2.0",
|
"@medusajs/framework": "^2.2.0",
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ const main = async function ({ directory, modules }) {
|
|||||||
ContainerRegistrationKeys.CONFIG_MODULE
|
ContainerRegistrationKeys.CONFIG_MODULE
|
||||||
)
|
)
|
||||||
|
|
||||||
const plugins = getResolvedPlugins(directory, configModule, true) || []
|
const plugins = await getResolvedPlugins(directory, configModule, true)
|
||||||
const linksSourcePaths = plugins.map((plugin) =>
|
const linksSourcePaths = plugins.map((plugin) =>
|
||||||
join(plugin.resolve, "links")
|
join(plugin.resolve, "links")
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ export async function migrate({
|
|||||||
ContainerRegistrationKeys.CONFIG_MODULE
|
ContainerRegistrationKeys.CONFIG_MODULE
|
||||||
)
|
)
|
||||||
|
|
||||||
const plugins = getResolvedPlugins(directory, configModule, true) || []
|
const plugins = await getResolvedPlugins(directory, configModule, true)
|
||||||
const linksSourcePaths = plugins.map((plugin) =>
|
const linksSourcePaths = plugins.map((plugin) =>
|
||||||
join(plugin.resolve, "links")
|
join(plugin.resolve, "links")
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ const main = async function ({ directory, modules }) {
|
|||||||
ContainerRegistrationKeys.CONFIG_MODULE
|
ContainerRegistrationKeys.CONFIG_MODULE
|
||||||
)
|
)
|
||||||
|
|
||||||
const plugins = getResolvedPlugins(directory, configModule, true) || []
|
const plugins = await getResolvedPlugins(directory, configModule, true)
|
||||||
const linksSourcePaths = plugins.map((plugin) =>
|
const linksSourcePaths = plugins.map((plugin) =>
|
||||||
join(plugin.resolve, "links")
|
join(plugin.resolve, "links")
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -187,7 +187,7 @@ const main = async function ({ directory, executeSafe, executeAll }) {
|
|||||||
|
|
||||||
const medusaAppLoader = new MedusaAppLoader()
|
const medusaAppLoader = new MedusaAppLoader()
|
||||||
|
|
||||||
const plugins = getResolvedPlugins(directory, configModule, true) || []
|
const plugins = await getResolvedPlugins(directory, configModule, true)
|
||||||
const linksSourcePaths = plugins.map((plugin) =>
|
const linksSourcePaths = plugins.map((plugin) =>
|
||||||
join(plugin.resolve, "links")
|
join(plugin.resolve, "links")
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -0,0 +1,211 @@
|
|||||||
|
import path from "path"
|
||||||
|
import { defineConfig, FileSystem } from "@medusajs/framework/utils"
|
||||||
|
import { getResolvedPlugins } from "../helpers/resolve-plugins"
|
||||||
|
|
||||||
|
const BASE_DIR = path.join(__dirname, "sample-proj")
|
||||||
|
const fs = new FileSystem(BASE_DIR)
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
await fs.cleanup()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("getResolvedPlugins | relative paths", () => {
|
||||||
|
test("resolve configured plugins", async () => {
|
||||||
|
await fs.createJson("plugins/dummy/package.json", {
|
||||||
|
name: "my-dummy-plugin",
|
||||||
|
version: "1.0.0",
|
||||||
|
})
|
||||||
|
|
||||||
|
const plugins = await getResolvedPlugins(
|
||||||
|
fs.basePath,
|
||||||
|
defineConfig({
|
||||||
|
plugins: [
|
||||||
|
{
|
||||||
|
resolve: "./plugins/dummy",
|
||||||
|
options: {
|
||||||
|
apiKey: "asecret",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
false
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(plugins).toEqual([
|
||||||
|
{
|
||||||
|
resolve: path.join(fs.basePath, "./plugins/dummy/build"),
|
||||||
|
name: "my-dummy-plugin",
|
||||||
|
id: "my-dummy-plugin",
|
||||||
|
options: { apiKey: "asecret" },
|
||||||
|
version: "1.0.0",
|
||||||
|
modules: [],
|
||||||
|
},
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
test("scan plugin modules", async () => {
|
||||||
|
await fs.createJson("plugins/dummy/package.json", {
|
||||||
|
name: "my-dummy-plugin",
|
||||||
|
version: "1.0.0",
|
||||||
|
})
|
||||||
|
await fs.create("plugins/dummy/build/modules/blog/index.js", ``)
|
||||||
|
|
||||||
|
const plugins = await getResolvedPlugins(
|
||||||
|
fs.basePath,
|
||||||
|
defineConfig({
|
||||||
|
plugins: [
|
||||||
|
{
|
||||||
|
resolve: "./plugins/dummy",
|
||||||
|
options: {
|
||||||
|
apiKey: "asecret",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
false
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(plugins).toEqual([
|
||||||
|
{
|
||||||
|
resolve: path.join(fs.basePath, "./plugins/dummy/build"),
|
||||||
|
name: "my-dummy-plugin",
|
||||||
|
id: "my-dummy-plugin",
|
||||||
|
options: { apiKey: "asecret" },
|
||||||
|
version: "1.0.0",
|
||||||
|
modules: [
|
||||||
|
{
|
||||||
|
options: {
|
||||||
|
apiKey: "asecret",
|
||||||
|
},
|
||||||
|
resolve: "./plugins/dummy/build/modules/blog",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
test("throw error when package.json file is missing", async () => {
|
||||||
|
const resolvePlugins = async () =>
|
||||||
|
getResolvedPlugins(
|
||||||
|
fs.basePath,
|
||||||
|
defineConfig({
|
||||||
|
plugins: [
|
||||||
|
{
|
||||||
|
resolve: "./plugins/dummy",
|
||||||
|
options: {
|
||||||
|
apiKey: "asecret",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
false
|
||||||
|
)
|
||||||
|
|
||||||
|
await expect(resolvePlugins()).rejects.toThrow(
|
||||||
|
`Unable to resolve plugin "./plugins/dummy". Make sure the plugin directory has a package.json file`
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("getResolvedPlugins | package reference", () => {
|
||||||
|
test("resolve configured plugins", async () => {
|
||||||
|
await fs.createJson("package.json", {})
|
||||||
|
await fs.createJson("node_modules/@plugins/dummy/package.json", {
|
||||||
|
name: "my-dummy-plugin",
|
||||||
|
version: "1.0.0",
|
||||||
|
})
|
||||||
|
|
||||||
|
const plugins = await getResolvedPlugins(
|
||||||
|
fs.basePath,
|
||||||
|
defineConfig({
|
||||||
|
plugins: [
|
||||||
|
{
|
||||||
|
resolve: "@plugins/dummy",
|
||||||
|
options: {
|
||||||
|
apiKey: "asecret",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
false
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(plugins).toEqual([
|
||||||
|
{
|
||||||
|
resolve: path.join(fs.basePath, "node_modules/@plugins/dummy/build"),
|
||||||
|
name: "my-dummy-plugin",
|
||||||
|
id: "my-dummy-plugin",
|
||||||
|
options: { apiKey: "asecret" },
|
||||||
|
version: "1.0.0",
|
||||||
|
modules: [],
|
||||||
|
},
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
test("scan plugin modules", async () => {
|
||||||
|
await fs.createJson("package.json", {})
|
||||||
|
await fs.createJson("node_modules/@plugins/dummy/package.json", {
|
||||||
|
name: "my-dummy-plugin",
|
||||||
|
version: "1.0.0",
|
||||||
|
})
|
||||||
|
await fs.create(
|
||||||
|
"node_modules/@plugins/dummy/build/modules/blog/index.js",
|
||||||
|
``
|
||||||
|
)
|
||||||
|
|
||||||
|
const plugins = await getResolvedPlugins(
|
||||||
|
fs.basePath,
|
||||||
|
defineConfig({
|
||||||
|
plugins: [
|
||||||
|
{
|
||||||
|
resolve: "@plugins/dummy",
|
||||||
|
options: {
|
||||||
|
apiKey: "asecret",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
false
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(plugins).toEqual([
|
||||||
|
{
|
||||||
|
resolve: path.join(fs.basePath, "node_modules/@plugins/dummy/build"),
|
||||||
|
name: "my-dummy-plugin",
|
||||||
|
id: "my-dummy-plugin",
|
||||||
|
options: { apiKey: "asecret" },
|
||||||
|
version: "1.0.0",
|
||||||
|
modules: [
|
||||||
|
{
|
||||||
|
options: {
|
||||||
|
apiKey: "asecret",
|
||||||
|
},
|
||||||
|
resolve: "@plugins/dummy/build/modules/blog",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
test("throw error when package.json file is missing", async () => {
|
||||||
|
const resolvePlugins = async () =>
|
||||||
|
getResolvedPlugins(
|
||||||
|
fs.basePath,
|
||||||
|
defineConfig({
|
||||||
|
plugins: [
|
||||||
|
{
|
||||||
|
resolve: "@plugins/dummy",
|
||||||
|
options: {
|
||||||
|
apiKey: "asecret",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
false
|
||||||
|
)
|
||||||
|
|
||||||
|
await expect(resolvePlugins()).rejects.toThrow(
|
||||||
|
`Unable to resolve plugin "@plugins/dummy". Make sure the plugin directory has a package.json file`
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -1,148 +1,103 @@
|
|||||||
|
import path from "path"
|
||||||
|
import fs from "fs/promises"
|
||||||
|
import { isString, readDir } from "@medusajs/framework/utils"
|
||||||
import { ConfigModule, PluginDetails } from "@medusajs/framework/types"
|
import { ConfigModule, PluginDetails } from "@medusajs/framework/types"
|
||||||
import { isString } from "@medusajs/framework/utils"
|
|
||||||
import fs from "fs"
|
|
||||||
import { sync as existsSync } from "fs-exists-cached"
|
|
||||||
import path, { isAbsolute } from "path"
|
|
||||||
|
|
||||||
|
const MEDUSA_APP_SOURCE_PATH = "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 {
|
||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
|
|
||||||
function createFileContentHash(path, files): string {
|
function createFileContentHash(path: string, files: string): string {
|
||||||
return path + files
|
return path + files
|
||||||
}
|
}
|
||||||
|
|
||||||
function getExtensionDirectoryPath() {
|
|
||||||
return "src"
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load plugin details from a path. Return undefined if does not contains a package.json
|
* Returns the absolute path to the package.json file for a
|
||||||
* @param pluginName
|
* given plugin identifier.
|
||||||
* @param path
|
|
||||||
* @param includeExtensionDirectoryPath should include src | dist for the resolved details
|
|
||||||
*/
|
*/
|
||||||
function loadPluginDetails({
|
async function resolvePluginPkgFile(
|
||||||
pluginName,
|
rootDirectory: string,
|
||||||
resolvedPath,
|
pluginPath: string
|
||||||
includeExtensionDirectoryPath,
|
): Promise<{ path: string; contents: any }> {
|
||||||
}: {
|
try {
|
||||||
pluginName: string
|
const pkgJSONPath = require.resolve(path.join(pluginPath, "package.json"), {
|
||||||
resolvedPath: string
|
paths: [rootDirectory],
|
||||||
includeExtensionDirectoryPath?: boolean
|
})
|
||||||
}) {
|
const packageJSONContents = JSON.parse(
|
||||||
if (existsSync(`${resolvedPath}/package.json`)) {
|
await fs.readFile(pkgJSONPath, "utf-8")
|
||||||
const packageJSON = JSON.parse(
|
|
||||||
fs.readFileSync(`${resolvedPath}/package.json`, `utf-8`)
|
|
||||||
)
|
)
|
||||||
const name = packageJSON.name || pluginName
|
return { path: pkgJSONPath, contents: packageJSONContents }
|
||||||
|
} catch (error) {
|
||||||
const extensionDirectoryPath = getExtensionDirectoryPath()
|
if (error.code === "MODULE_NOT_FOUND" || error.code === "ENOENT") {
|
||||||
const resolve = includeExtensionDirectoryPath
|
throw new Error(
|
||||||
? path.join(resolvedPath, extensionDirectoryPath)
|
`Unable to resolve plugin "${pluginPath}". Make sure the plugin directory has a package.json file`
|
||||||
: resolvedPath
|
)
|
||||||
|
|
||||||
return {
|
|
||||||
resolve,
|
|
||||||
name,
|
|
||||||
id: createPluginId(name),
|
|
||||||
options: {},
|
|
||||||
version: packageJSON.version || createFileContentHash(path, `**`),
|
|
||||||
}
|
}
|
||||||
|
throw error
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make package.json a requirement for local plugins too
|
|
||||||
throw new Error(`Plugin ${pluginName} requires a package.json file`)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds the correct path for the plugin. If it is a local plugin it will be
|
* Finds the correct path for the plugin. If it is a local plugin it will be
|
||||||
* found in the plugins folder. Otherwise we will look for the plugin in the
|
* found in the plugins folder. Otherwise we will look for the plugin in the
|
||||||
* installed npm packages.
|
* installed npm packages.
|
||||||
* @param {string} pluginName - the name of the plugin to find. Should match
|
* @param {string} pluginPath - the name of the plugin to find. Should match
|
||||||
* the name of the folder where the plugin is contained.
|
* the name of the folder where the plugin is contained.
|
||||||
* @return {object} the plugin details
|
* @return {object} the plugin details
|
||||||
*/
|
*/
|
||||||
function resolvePlugin(pluginName: string): {
|
async function resolvePlugin(
|
||||||
resolve: string
|
rootDirectory: string,
|
||||||
id: string
|
pluginPath: string,
|
||||||
name: string
|
options?: any
|
||||||
options: Record<string, unknown>
|
): Promise<PluginDetails> {
|
||||||
version: string
|
const pkgJSON = await resolvePluginPkgFile(rootDirectory, pluginPath)
|
||||||
} {
|
const resolvedPath = path.dirname(pkgJSON.path)
|
||||||
if (!isAbsolute(pluginName)) {
|
|
||||||
let resolvedPath = path.resolve(`./plugins/${pluginName}`)
|
|
||||||
const doesExistsInPlugin = existsSync(resolvedPath)
|
|
||||||
|
|
||||||
if (doesExistsInPlugin) {
|
const name = pkgJSON.contents.name || pluginPath
|
||||||
return loadPluginDetails({
|
const srcDir = pkgJSON.contents.main
|
||||||
pluginName,
|
? path.dirname(pkgJSON.contents.main)
|
||||||
resolvedPath,
|
: "build"
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the plugin in the file system
|
const resolve = path.join(resolvedPath, srcDir)
|
||||||
resolvedPath = path.resolve(pluginName)
|
const modules = await readDir(path.join(resolve, "modules"), {
|
||||||
const doesExistsInFileSystem = existsSync(resolvedPath)
|
ignoreMissing: true,
|
||||||
|
})
|
||||||
|
const pluginOptions = options ?? {}
|
||||||
|
|
||||||
if (doesExistsInFileSystem) {
|
return {
|
||||||
return loadPluginDetails({
|
resolve,
|
||||||
pluginName,
|
name,
|
||||||
resolvedPath,
|
id: createPluginId(name),
|
||||||
includeExtensionDirectoryPath: true,
|
options: pluginOptions,
|
||||||
})
|
version: pkgJSON.contents.version || "0.0.0",
|
||||||
}
|
modules: modules.map((mod) => {
|
||||||
|
return {
|
||||||
throw new Error(`Unable to find the plugin "${pluginName}".`)
|
resolve: `${pluginPath}/${srcDir}/modules/${mod.name}`,
|
||||||
}
|
options: pluginOptions,
|
||||||
|
}
|
||||||
try {
|
}),
|
||||||
// If the path is absolute, resolve the directory of the internal plugin,
|
|
||||||
// otherwise resolve the directory containing the package.json
|
|
||||||
const resolvedPath = require.resolve(pluginName, {
|
|
||||||
paths: [process.cwd()],
|
|
||||||
})
|
|
||||||
|
|
||||||
const packageJSON = JSON.parse(
|
|
||||||
fs.readFileSync(`${resolvedPath}/package.json`, `utf-8`)
|
|
||||||
)
|
|
||||||
|
|
||||||
const computedResolvedPath = path.join(resolvedPath, "dist")
|
|
||||||
|
|
||||||
return {
|
|
||||||
resolve: computedResolvedPath,
|
|
||||||
id: createPluginId(packageJSON.name),
|
|
||||||
name: packageJSON.name,
|
|
||||||
options: {},
|
|
||||||
version: packageJSON.version,
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
throw new Error(
|
|
||||||
`Unable to find plugin "${pluginName}". Perhaps you need to install its package?`
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getResolvedPlugins(
|
export async function getResolvedPlugins(
|
||||||
rootDirectory: string,
|
rootDirectory: string,
|
||||||
configModule: ConfigModule,
|
configModule: ConfigModule,
|
||||||
isMedusaProject = false
|
isMedusaProject = false
|
||||||
): undefined | PluginDetails[] {
|
): Promise<PluginDetails[]> {
|
||||||
const resolved = configModule?.plugins?.map((plugin) => {
|
const resolved = await Promise.all(
|
||||||
if (isString(plugin)) {
|
(configModule?.plugins || []).map(async (plugin) => {
|
||||||
return resolvePlugin(plugin)
|
if (isString(plugin)) {
|
||||||
}
|
return resolvePlugin(rootDirectory, plugin)
|
||||||
|
}
|
||||||
const details = resolvePlugin(plugin.resolve)
|
return resolvePlugin(rootDirectory, plugin.resolve, plugin.options)
|
||||||
details.options = plugin.options
|
})
|
||||||
|
)
|
||||||
return details
|
|
||||||
})
|
|
||||||
|
|
||||||
if (isMedusaProject) {
|
if (isMedusaProject) {
|
||||||
const extensionDirectoryPath = getExtensionDirectoryPath()
|
const extensionDirectory = path.join(rootDirectory, MEDUSA_APP_SOURCE_PATH)
|
||||||
const extensionDirectory = path.join(rootDirectory, extensionDirectoryPath)
|
|
||||||
resolved.push({
|
resolved.push({
|
||||||
resolve: extensionDirectory,
|
resolve: extensionDirectory,
|
||||||
name: MEDUSA_PROJECT_NAME,
|
name: MEDUSA_PROJECT_NAME,
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ export default async ({
|
|||||||
ContainerRegistrationKeys.CONFIG_MODULE
|
ContainerRegistrationKeys.CONFIG_MODULE
|
||||||
)
|
)
|
||||||
|
|
||||||
const plugins = getResolvedPlugins(rootDirectory, configModule, true) || []
|
const plugins = await getResolvedPlugins(rootDirectory, configModule, true)
|
||||||
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