feature: bundle all modules (#9324)

This commit is contained in:
Harminder Virk
2024-09-30 12:34:03 +05:30
committed by GitHub
parent a4fc9d6e0b
commit a578313db9
81 changed files with 640 additions and 226 deletions

View File

@@ -7,31 +7,31 @@ import {
import { MODULE_RESOURCE_TYPE, MODULE_SCOPE } from "./types"
export const MODULE_PACKAGE_NAMES = {
[Modules.AUTH]: "@medusajs/auth",
[Modules.CACHE]: "@medusajs/cache-inmemory",
[Modules.CART]: "@medusajs/cart",
[Modules.CUSTOMER]: "@medusajs/customer",
[Modules.EVENT_BUS]: "@medusajs/event-bus-local",
[Modules.INVENTORY]: "@medusajs/inventory-next", // TODO: To be replaced when current `@medusajs/inventory` is deprecated
[Modules.LINK]: "@medusajs/link-modules",
[Modules.PAYMENT]: "@medusajs/payment",
[Modules.PRICING]: "@medusajs/pricing",
[Modules.PRODUCT]: "@medusajs/product",
[Modules.PROMOTION]: "@medusajs/promotion",
[Modules.SALES_CHANNEL]: "@medusajs/sales-channel",
[Modules.FULFILLMENT]: "@medusajs/fulfillment",
[Modules.STOCK_LOCATION]: "@medusajs/stock-location-next", // TODO: To be replaced when current `@medusajs/stock-location` is deprecated
[Modules.TAX]: "@medusajs/tax",
[Modules.USER]: "@medusajs/user",
[Modules.WORKFLOW_ENGINE]: "@medusajs/workflow-engine-inmemory",
[Modules.REGION]: "@medusajs/region",
[Modules.ORDER]: "@medusajs/order",
[Modules.API_KEY]: "@medusajs/api-key",
[Modules.STORE]: "@medusajs/store",
[Modules.CURRENCY]: "@medusajs/currency",
[Modules.FILE]: "@medusajs/file",
[Modules.NOTIFICATION]: "@medusajs/notification",
[Modules.INDEX]: "@medusajs/index",
[Modules.AUTH]: "@medusajs/medusa/auth",
[Modules.CACHE]: "@medusajs/medusa/cache-inmemory",
[Modules.CART]: "@medusajs/medusa/cart",
[Modules.CUSTOMER]: "@medusajs/medusa/customer",
[Modules.EVENT_BUS]: "@medusajs/medusa/event-bus-local",
[Modules.INVENTORY]: "@medusajs/medusa/inventory-next", // TODO: To be replaced when current `@medusajs/inventory` is deprecated
[Modules.LINK]: "@medusajs/medusa/link-modules",
[Modules.PAYMENT]: "@medusajs/medusa/payment",
[Modules.PRICING]: "@medusajs/medusa/pricing",
[Modules.PRODUCT]: "@medusajs/medusa/product",
[Modules.PROMOTION]: "@medusajs/medusa/promotion",
[Modules.SALES_CHANNEL]: "@medusajs/medusa/sales-channel",
[Modules.FULFILLMENT]: "@medusajs/medusa/fulfillment",
[Modules.STOCK_LOCATION]: "@medusajs/medusa/stock-location-next", // TODO: To be replaced when current `@medusajs/stock-location` is deprecated
[Modules.TAX]: "@medusajs/medusa/tax",
[Modules.USER]: "@medusajs/medusa/user",
[Modules.WORKFLOW_ENGINE]: "@medusajs/medusa/workflow-engine-inmemory",
[Modules.REGION]: "@medusajs/medusa/region",
[Modules.ORDER]: "@medusajs/medusa/order",
[Modules.API_KEY]: "@medusajs/medusa/api-key",
[Modules.STORE]: "@medusajs/medusa/store",
[Modules.CURRENCY]: "@medusajs/medusa/currency",
[Modules.FILE]: "@medusajs/medusa/file",
[Modules.NOTIFICATION]: "@medusajs/medusa/notification",
[Modules.INDEX]: "@medusajs/medusa/index-module",
}
export const ModulesDefinition: {

View File

@@ -35,7 +35,10 @@ describe("load internal - load resources", () => {
(ModuleService.prototype as IModuleService).__joinerConfig
).toBeUndefined()
const resources = await loadResources(moduleResolution)
const resources = await loadResources({
moduleResolution,
discoveryPath: moduleResolution.resolutionPath as string,
})
expect(resources).toBeDefined()
expect(resources.services).toHaveLength(1)
@@ -115,7 +118,10 @@ describe("load internal - load resources", () => {
(ModuleService.prototype as IModuleService).__joinerConfig
).toBeUndefined()
const resources = await loadResources(moduleResolution)
const resources = await loadResources({
moduleResolution,
discoveryPath: moduleResolution.resolutionPath as string,
})
expect(resources).toBeDefined()
expect(resources.services).toHaveLength(1)
@@ -195,7 +201,10 @@ describe("load internal - load resources", () => {
(ModuleService.prototype as IModuleService).__joinerConfig
).toBeUndefined()
const resources = await loadResources(moduleResolution)
const resources = await loadResources({
moduleResolution,
discoveryPath: moduleResolution.resolutionPath as string,
})
expect(resources).toBeDefined()
expect(resources.services).toHaveLength(1)
@@ -274,7 +283,10 @@ describe("load internal - load resources", () => {
(ModuleService.prototype as IModuleService).__joinerConfig
).toBeDefined()
const resources = await loadResources(moduleResolution)
const resources = await loadResources({
moduleResolution,
discoveryPath: moduleResolution.resolutionPath as string,
})
expect(resources).toBeDefined()
expect(resources.services).toHaveLength(1)

View File

@@ -22,7 +22,7 @@ import {
import { asFunction, asValue } from "awilix"
import { statSync } from "fs"
import { readdir } from "fs/promises"
import { join, resolve } from "path"
import { dirname, join, resolve } from "path"
import { MODULE_RESOURCE_TYPE } from "../../types"
type ModuleResource = {
@@ -39,35 +39,40 @@ type MigrationFunction = (
moduleDeclaration?: InternalModuleDeclaration
) => Promise<void>
export async function loadInternalModule(
container: MedusaContainer,
resolution: ModuleResolution,
logger: Logger,
migrationOnly?: boolean,
loaderOnly?: boolean
): Promise<{ error?: Error } | void> {
const keyName = !loaderOnly
? resolution.definition.key
: resolution.definition.key + "__loaderOnly"
const { resources } =
resolution.moduleDeclaration as InternalModuleDeclaration
let loadedModule: ModuleExports
export async function resolveModuleExports({
resolution,
}: {
resolution: ModuleResolution
}): Promise<
| (ModuleExports & {
discoveryPath: string
})
| { error: any }
> {
let resolvedModuleExports: ModuleExports
try {
// When loading manually, we pass the exports to be loaded, meaning that we do not need to import the package to find
// the exports. This is useful when a package export an initialize function which will bootstrap itself and therefore
// does not need to import the package that is currently being loaded as it would create a
// circular reference.
const modulePath = resolution.resolutionPath as string
if (resolution.moduleExports) {
// TODO:
// If we want to benefit from the auto load mechanism, even if the module exports is provided, we need to ask for the module path
loadedModule = resolution.moduleExports
resolvedModuleExports = resolution.moduleExports
resolvedModuleExports.discoveryPath = resolution.resolutionPath as string
} else {
loadedModule = await dynamicImport(modulePath)
loadedModule = (loadedModule as any).default
const module = await dynamicImport(resolution.resolutionPath as string)
if ("discoveryPath" in module) {
const reExportedLoadedModule = await dynamicImport(module.discoveryPath)
const discoveryPath = module.discoveryPath
resolvedModuleExports = reExportedLoadedModule.default
resolvedModuleExports.discoveryPath = discoveryPath as string
} else {
resolvedModuleExports = (module as { default: ModuleExports }).default
resolvedModuleExports.discoveryPath =
resolution.resolutionPath as string
}
}
return resolvedModuleExports as ModuleExports & {
discoveryPath: string
}
} catch (error) {
if (
@@ -83,15 +88,37 @@ export async function loadInternalModule(
return { error }
}
}
export async function loadInternalModule(
container: MedusaContainer,
resolution: ModuleResolution,
logger: Logger,
migrationOnly?: boolean,
loaderOnly?: boolean
): Promise<{ error?: Error } | void> {
const keyName = !loaderOnly
? resolution.definition.key
: resolution.definition.key + "__loaderOnly"
const { resources } =
resolution.moduleDeclaration as InternalModuleDeclaration
const loadedModule = await resolveModuleExports({ resolution })
if ("error" in loadedModule) {
return loadedModule
}
let moduleResources = {} as ModuleResource
if (resolution.resolutionPath) {
moduleResources = await loadResources(
resolution,
if (loadedModule.discoveryPath) {
moduleResources = await loadResources({
moduleResolution: resolution,
discoveryPath: loadedModule.discoveryPath,
logger,
loadedModule?.loaders ?? []
)
loadedModuleLoaders: loadedModule?.loaders,
})
}
if (!loadedModule?.service && !moduleResources.moduleService) {
@@ -193,22 +220,25 @@ export async function loadModuleMigrations(
revertMigration?: MigrationFunction
generateMigration?: MigrationFunction
}> {
let loadedModule: ModuleExports
try {
loadedModule =
moduleExports ??
(await dynamicImport(resolution.resolutionPath as string))
const loadedModule = await resolveModuleExports({
resolution: { ...resolution, moduleExports },
})
if ("error" in loadedModule) {
throw loadedModule.error
}
try {
let runMigrations = loadedModule.runMigrations
let revertMigration = loadedModule.revertMigration
let generateMigration = loadedModule.generateMigration
if (!runMigrations || !revertMigration) {
const moduleResources = await loadResources(
resolution,
console as unknown as Logger,
loadedModule?.loaders ?? []
)
const moduleResources = await loadResources({
moduleResolution: resolution,
discoveryPath: loadedModule.discoveryPath,
loadedModuleLoaders: loadedModule?.loaders,
})
const migrationScriptOptions = {
moduleName: resolution.definition.key,
@@ -269,15 +299,22 @@ async function importAllFromDir(path: string) {
})
}
export async function loadResources(
moduleResolution: ModuleResolution,
logger: Logger = console as unknown as Logger,
export async function loadResources({
moduleResolution,
discoveryPath,
logger,
loadedModuleLoaders,
}: {
moduleResolution: ModuleResolution
discoveryPath: string
logger?: Logger
loadedModuleLoaders?: ModuleLoaderFunction[]
): Promise<ModuleResource> {
let modulePath = moduleResolution.resolutionPath as string
let normalizedPath = modulePath
.replace("index.js", "")
.replace("index.ts", "")
}): Promise<ModuleResource> {
logger ??= console as unknown as Logger
loadedModuleLoaders ??= []
const modulePath = discoveryPath
let normalizedPath = dirname(require.resolve(modulePath))
normalizedPath = resolve(normalizedPath)
try {

View File

@@ -206,8 +206,16 @@ async function initializeLinks({
moduleExports,
}) {
try {
const { initialize, getMigrationPlanner } =
moduleExports ?? (await dynamicImport(LinkModulePackage))
let resources = moduleExports
if (!resources) {
const module = await dynamicImport(LinkModulePackage)
if ("discoveryPath" in module) {
const reExportedLoadedModule = await dynamicImport(module.discoveryPath)
resources = reExportedLoadedModule.default ?? reExportedLoadedModule
}
}
const { initialize, getMigrationPlanner } = resources
const linkResolution = await initialize(
config,