feat: add support for loading admin extensions from the source (#10975)

This commit is contained in:
Harminder Virk authored and GitHub committed 2025-01-16 11:06:56 +05:30
1 parent 8792d0c062
commit c75678d6d4
6 files changed
+130 -8

No files matched your search

@@ -34,6 +34,10 @@ describe("getResolvedPlugins | relative paths", () => {
expect(plugins).toEqual([
{
resolve: path.join(fs.basePath, "./plugins/dummy/.medusa/server/src"),
adminResolve: path.join(
fs.basePath,
"./plugins/dummy/.medusa/server/src/admin"
),
name: "my-dummy-plugin",
id: "my-dummy-plugin",
options: { apiKey: "asecret" },
@@ -71,6 +75,10 @@ describe("getResolvedPlugins | relative paths", () => {
expect(plugins).toEqual([
{
resolve: path.join(fs.basePath, "./plugins/dummy/.medusa/server/src"),
adminResolve: path.join(
fs.basePath,
"./plugins/dummy/.medusa/server/src/admin"
),
name: "my-dummy-plugin",
id: "my-dummy-plugin",
options: { apiKey: "asecret" },
@@ -108,6 +116,57 @@ describe("getResolvedPlugins | relative paths", () => {
`Unable to resolve plugin "./plugins/dummy". Make sure the plugin directory has a package.json file`
)
})
test("resolve admin source from medusa-plugin-options file", async () => {
await fs.createJson("plugins/dummy/package.json", {
name: "my-dummy-plugin",
version: "1.0.0",
})
await fs.create(
"plugins/dummy/.medusa/server/src/modules/blog/index.js",
``
)
await fs.createJson(
"plugins/dummy/.medusa/server/medusa-plugin-options.json",
{
srcDir: path.join(fs.basePath, "plugins/dummy/src"),
}
)
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/.medusa/server/src"),
adminResolve: path.join(fs.basePath, "./plugins/dummy/src/admin"),
name: "my-dummy-plugin",
id: "my-dummy-plugin",
options: { apiKey: "asecret" },
version: "1.0.0",
modules: [
{
options: {
apiKey: "asecret",
},
resolve: "./plugins/dummy/.medusa/server/src/modules/blog",
},
],
},
])
})
})
describe("getResolvedPlugins | package reference", () => {
@@ -139,6 +198,10 @@ describe("getResolvedPlugins | package reference", () => {
fs.basePath,
"node_modules/@plugins/dummy/.medusa/server/src"
),
adminResolve: path.join(
fs.basePath,
"node_modules/@plugins/dummy/.medusa/server/src/admin"
),
name: "my-dummy-plugin",
id: "my-dummy-plugin",
options: { apiKey: "asecret" },
@@ -180,6 +243,10 @@ describe("getResolvedPlugins | package reference", () => {
fs.basePath,
"node_modules/@plugins/dummy/.medusa/server/src"
),
adminResolve: path.join(
fs.basePath,
"node_modules/@plugins/dummy/.medusa/server/src/admin"
),
name: "my-dummy-plugin",
id: "my-dummy-plugin",
options: { apiKey: "asecret" },
+2 -5
View File
@@ -33,12 +33,9 @@ export default async function adminLoader({
const { admin } = configModule
const sources: string[] = []
for (const plugin of plugins) {
const pluginSource = path.join(plugin.resolve, "admin")
if (fs.existsSync(pluginSource)) {
sources.push(pluginSource)
if (fs.existsSync(plugin.adminResolve)) {
sources.push(plugin.adminResolve)
}
}
@@ -5,6 +5,8 @@ import { ConfigModule, PluginDetails } from "@medusajs/framework/types"
const MEDUSA_APP_SOURCE_PATH = "src"
const MEDUSA_PLUGIN_SOURCE_PATH = ".medusa/server/src"
const MEDUSA_PLUGIN_OPTIONS_FILE_PATH =
".medusa/server/medusa-plugin-options.json"
export const MEDUSA_PROJECT_NAME = "project-plugin"
function createPluginId(name: string): string {
@@ -41,6 +43,27 @@ async function resolvePluginPkgFile(
}
}
/**
* Reads the "medusa-plugin-options.json" file from the plugin root
* directory and returns its contents as an object.
*/
async function resolvePluginOptions(
pluginRootDir: string
): Promise<Record<string, any>> {
try {
const contents = await fs.readFile(
path.join(pluginRootDir, MEDUSA_PLUGIN_OPTIONS_FILE_PATH),
"utf-8"
)
return JSON.parse(contents)
} catch (error) {
if (error.code === "MODULE_NOT_FOUND" || error.code === "ENOENT") {
return {}
}
throw error
}
}
/**
* 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
@@ -60,6 +83,7 @@ async function resolvePlugin(
const name = pkgJSON.contents.name || pluginPath
const resolve = path.join(resolvedPath, MEDUSA_PLUGIN_SOURCE_PATH)
const pluginStaticOptions = await resolvePluginOptions(resolvedPath)
const modules = await readDir(path.join(resolve, "modules"), {
ignoreMissing: true,
})
@@ -71,6 +95,7 @@ async function resolvePlugin(
id: createPluginId(name),
options: pluginOptions,
version: pkgJSON.contents.version || "0.0.0",
adminResolve: path.join(pluginStaticOptions.srcDir ?? resolve, "admin"),
modules: modules.map((mod) => {
return {
resolve: `${pluginPath}/${MEDUSA_PLUGIN_SOURCE_PATH}/modules/${mod.name}`,
@@ -100,6 +125,7 @@ export async function getResolvedPlugins(
resolve: extensionDirectory,
name: MEDUSA_PROJECT_NAME,
id: createPluginId(MEDUSA_PROJECT_NAME),
adminResolve: path.join(extensionDirectory, "admin"),
options: configModule,
version: createFileContentHash(process.cwd(), `**`),
})