fix(medusa, modules-sdk, modules): Module loading missing dependencies + remote query reference issue (#5468)

This commit is contained in:
Adrien de Peretti
2023-10-26 20:24:38 +02:00
committed by GitHub
parent 725ba9bb9b
commit a45da9215d
15 changed files with 371 additions and 226 deletions
+15
View File
@@ -0,0 +1,15 @@
---
"@medusajs/medusa": patch
"@medusajs/cache-inmemory": patch
"@medusajs/cache-redis": patch
"@medusajs/event-bus-local": patch
"@medusajs/event-bus-redis": patch
"@medusajs/inventory": patch
"@medusajs/link-modules": patch
"@medusajs/modules-sdk": patch
"@medusajs/pricing": patch
"@medusajs/product": patch
"@medusajs/stock-location": patch
---
fix(medusa, modules-sdk, modules): Module loading was missing the expected dependencies and remote query reference fix
@@ -11,12 +11,13 @@ export const initialize = async (
options?: InMemoryCacheModuleOptions | ExternalModuleDeclaration options?: InMemoryCacheModuleOptions | ExternalModuleDeclaration
): Promise<ICacheService> => { ): Promise<ICacheService> => {
const serviceKey = Modules.CACHE const serviceKey = Modules.CACHE
const loaded = await MedusaModule.bootstrap<ICacheService>( const loaded = await MedusaModule.bootstrap<ICacheService>({
serviceKey, moduleKey: serviceKey,
"@medusajs/cache-inmemory", defaultPath: "@medusajs/cache-inmemory",
options as InternalModuleDeclaration | ExternalModuleDeclaration, declaration: options as
undefined | InternalModuleDeclaration
) | ExternalModuleDeclaration,
})
return loaded[serviceKey] return loaded[serviceKey]
} }
+7 -6
View File
@@ -11,12 +11,13 @@ export const initialize = async (
options?: RedisCacheModuleOptions | ExternalModuleDeclaration options?: RedisCacheModuleOptions | ExternalModuleDeclaration
): Promise<ICacheService> => { ): Promise<ICacheService> => {
const serviceKey = Modules.CACHE const serviceKey = Modules.CACHE
const loaded = await MedusaModule.bootstrap<ICacheService>( const loaded = await MedusaModule.bootstrap<ICacheService>({
serviceKey, moduleKey: serviceKey,
"@medusajs/cache-redis", defaultPath: "@medusajs/cache-redis",
options as InternalModuleDeclaration | ExternalModuleDeclaration, declaration: options as
undefined | InternalModuleDeclaration
) | ExternalModuleDeclaration,
})
return loaded[serviceKey] return loaded[serviceKey]
} }
@@ -3,10 +3,10 @@ import { IEventBusService } from "@medusajs/types"
export const initialize = async (): Promise<IEventBusService> => { export const initialize = async (): Promise<IEventBusService> => {
const serviceKey = Modules.EVENT_BUS const serviceKey = Modules.EVENT_BUS
const loaded = await MedusaModule.bootstrap<IEventBusService>( const loaded = await MedusaModule.bootstrap<IEventBusService>({
serviceKey, moduleKey: serviceKey,
"@medusajs/event-bus-local" defaultPath: "@medusajs/event-bus-local",
) })
return loaded[serviceKey] return loaded[serviceKey]
} }
@@ -11,12 +11,13 @@ export const initialize = async (
options?: EventBusRedisModuleOptions | ExternalModuleDeclaration options?: EventBusRedisModuleOptions | ExternalModuleDeclaration
): Promise<IEventBusService> => { ): Promise<IEventBusService> => {
const serviceKey = Modules.EVENT_BUS const serviceKey = Modules.EVENT_BUS
const loaded = await MedusaModule.bootstrap<IEventBusService>( const loaded = await MedusaModule.bootstrap<IEventBusService>({
serviceKey, moduleKey: serviceKey,
"@medusajs/event-bus-redis", defaultPath: "@medusajs/event-bus-redis",
options as InternalModuleDeclaration | ExternalModuleDeclaration, declaration: options as
undefined | InternalModuleDeclaration
) | ExternalModuleDeclaration,
})
return loaded[serviceKey] return loaded[serviceKey]
} }
+10 -7
View File
@@ -2,6 +2,7 @@ import {
ExternalModuleDeclaration, ExternalModuleDeclaration,
InternalModuleDeclaration, InternalModuleDeclaration,
MedusaModule, MedusaModule,
MODULE_PACKAGE_NAMES,
Modules, Modules,
} from "@medusajs/modules-sdk" } from "@medusajs/modules-sdk"
import { IEventBusService, IInventoryService } from "@medusajs/types" import { IEventBusService, IInventoryService } from "@medusajs/types"
@@ -15,13 +16,15 @@ export const initialize = async (
} }
): Promise<IInventoryService> => { ): Promise<IInventoryService> => {
const serviceKey = Modules.INVENTORY const serviceKey = Modules.INVENTORY
const loaded = await MedusaModule.bootstrap<IInventoryService>( const loaded = await MedusaModule.bootstrap<IInventoryService>({
serviceKey, moduleKey: serviceKey,
"@medusajs/inventory", defaultPath: MODULE_PACKAGE_NAMES[Modules.INVENTORY],
options as InternalModuleDeclaration | ExternalModuleDeclaration, declaration: options as
moduleDefinition, | InternalModuleDeclaration
injectedDependencies | ExternalModuleDeclaration,
) injectedDependencies,
moduleExports: moduleDefinition,
})
return loaded[serviceKey] return loaded[serviceKey]
} }
@@ -120,12 +120,12 @@ export const initialize = async (
}, },
} }
const loaded = await MedusaModule.bootstrapLink( const loaded = await MedusaModule.bootstrapLink({
linkModuleDefinition, definition: linkModuleDefinition,
options as InternalModuleDeclaration, declaration: options as InternalModuleDeclaration,
moduleDefinition, moduleExports: moduleDefinition,
injectedDependencies injectedDependencies,
) })
allLinks[serviceKey as string] = Object.values(loaded)[0] allLinks[serviceKey as string] = Object.values(loaded)[0]
} }
+1
View File
@@ -234,6 +234,7 @@ export default async ({
modulesConfig, modulesConfig,
servicesConfig: joinerConfig, servicesConfig: joinerConfig,
remoteFetchData: remoteQueryFetchData(container), remoteFetchData: remoteQueryFetchData(container),
sharedContainer: container,
injectedDependencies: { injectedDependencies: {
[ContainerRegistrationKeys.PG_CONNECTION]: container.resolve( [ContainerRegistrationKeys.PG_CONNECTION]: container.resolve(
ContainerRegistrationKeys.PG_CONNECTION ContainerRegistrationKeys.PG_CONNECTION
@@ -46,35 +46,47 @@ describe("Medusa Modules", () => {
}) })
it("should create singleton instances", async () => { it("should create singleton instances", async () => {
await MedusaModule.bootstrap("moduleKey", "@path", { await MedusaModule.bootstrap({
scope: MODULE_SCOPE.INTERNAL, moduleKey: "moduleKey",
resources: MODULE_RESOURCE_TYPE.ISOLATED, defaultPath: "@path",
resolve: "@path", declaration: {
options: { scope: MODULE_SCOPE.INTERNAL,
abc: 123, resources: MODULE_RESOURCE_TYPE.ISOLATED,
}, resolve: "@path",
} as InternalModuleDeclaration) options: {
abc: 123,
},
} as InternalModuleDeclaration,
})
expect(mockRegisterMedusaModule).toBeCalledTimes(1) expect(mockRegisterMedusaModule).toBeCalledTimes(1)
expect(mockModuleLoader).toBeCalledTimes(1) expect(mockModuleLoader).toBeCalledTimes(1)
await MedusaModule.bootstrap("moduleKey", "@path", { await MedusaModule.bootstrap({
scope: MODULE_SCOPE.INTERNAL, moduleKey: "moduleKey",
resources: MODULE_RESOURCE_TYPE.ISOLATED, defaultPath: "@path",
resolve: "@path", declaration: {
options: { scope: MODULE_SCOPE.INTERNAL,
abc: 123, resources: MODULE_RESOURCE_TYPE.ISOLATED,
}, resolve: "@path",
} as InternalModuleDeclaration) options: {
abc: 123,
},
} as InternalModuleDeclaration,
})
await MedusaModule.bootstrap("moduleKey", "@path", { await MedusaModule.bootstrap({
scope: MODULE_SCOPE.INTERNAL, moduleKey: "moduleKey",
resources: MODULE_RESOURCE_TYPE.ISOLATED, defaultPath: "@path",
resolve: "@path", declaration: {
options: { scope: MODULE_SCOPE.INTERNAL,
different_options: "abc", resources: MODULE_RESOURCE_TYPE.ISOLATED,
}, resolve: "@path",
} as InternalModuleDeclaration) options: {
different_options: "abc",
},
} as InternalModuleDeclaration,
})
expect(mockRegisterMedusaModule).toBeCalledTimes(2) expect(mockRegisterMedusaModule).toBeCalledTimes(2)
expect(mockModuleLoader).toBeCalledTimes(2) expect(mockModuleLoader).toBeCalledTimes(2)
@@ -85,14 +97,18 @@ describe("Medusa Modules", () => {
for (let i = 5; i--; ) { for (let i = 5; i--; ) {
load.push( load.push(
MedusaModule.bootstrap("moduleKey", "@path", { MedusaModule.bootstrap({
scope: MODULE_SCOPE.INTERNAL, moduleKey: "moduleKey",
resources: MODULE_RESOURCE_TYPE.ISOLATED, defaultPath: "@path",
resolve: "@path", declaration: {
options: { scope: MODULE_SCOPE.INTERNAL,
abc: 123, resources: MODULE_RESOURCE_TYPE.ISOLATED,
}, resolve: "@path",
} as InternalModuleDeclaration) options: {
abc: 123,
},
} as InternalModuleDeclaration,
})
) )
} }
@@ -104,81 +120,109 @@ describe("Medusa Modules", () => {
}) })
it("getModuleInstance should return the first instance of the module if there is none flagged as 'main'", async () => { it("getModuleInstance should return the first instance of the module if there is none flagged as 'main'", async () => {
const moduleA = await MedusaModule.bootstrap("moduleKey", "@path", { const moduleA = await MedusaModule.bootstrap({
scope: MODULE_SCOPE.INTERNAL, moduleKey: "moduleKey",
resources: MODULE_RESOURCE_TYPE.ISOLATED, defaultPath: "@path",
resolve: "@path", declaration: {
options: { scope: MODULE_SCOPE.INTERNAL,
abc: 123, resources: MODULE_RESOURCE_TYPE.ISOLATED,
}, resolve: "@path",
} as InternalModuleDeclaration) options: {
abc: 123,
},
} as InternalModuleDeclaration,
})
const moduleB = await MedusaModule.bootstrap("moduleKey", "@path", { const moduleB = await MedusaModule.bootstrap({
scope: MODULE_SCOPE.INTERNAL, moduleKey: "moduleKey",
resources: MODULE_RESOURCE_TYPE.ISOLATED, defaultPath: "@path",
resolve: "@path", declaration: {
options: { scope: MODULE_SCOPE.INTERNAL,
different_options: "abc", resources: MODULE_RESOURCE_TYPE.ISOLATED,
}, resolve: "@path",
} as InternalModuleDeclaration) options: {
different_options: "abc",
},
} as InternalModuleDeclaration,
})
expect(MedusaModule.getModuleInstance("moduleKey")).toEqual(moduleA) expect(MedusaModule.getModuleInstance("moduleKey")).toEqual(moduleA)
}) })
it("should return the module flagged as 'main' when multiple instances are available", async () => { it("should return the module flagged as 'main' when multiple instances are available", async () => {
const moduleA = await MedusaModule.bootstrap("moduleKey", "@path", { const moduleA = await MedusaModule.bootstrap({
scope: MODULE_SCOPE.INTERNAL, moduleKey: "moduleKey",
resources: MODULE_RESOURCE_TYPE.ISOLATED, defaultPath: "@path",
resolve: "@path", declaration: {
options: { scope: MODULE_SCOPE.INTERNAL,
abc: 123, resources: MODULE_RESOURCE_TYPE.ISOLATED,
}, resolve: "@path",
} as InternalModuleDeclaration) options: {
abc: 123,
},
} as InternalModuleDeclaration,
})
const moduleB = await MedusaModule.bootstrap("moduleKey", "@path", { const moduleB = await MedusaModule.bootstrap({
scope: MODULE_SCOPE.INTERNAL, moduleKey: "moduleKey",
resources: MODULE_RESOURCE_TYPE.ISOLATED, defaultPath: "@path",
resolve: "@path", declaration: {
main: true, scope: MODULE_SCOPE.INTERNAL,
options: { resources: MODULE_RESOURCE_TYPE.ISOLATED,
different_options: "abc", resolve: "@path",
}, main: true,
} as InternalModuleDeclaration) options: {
different_options: "abc",
},
} as InternalModuleDeclaration,
})
expect(MedusaModule.getModuleInstance("moduleKey")).toEqual(moduleB) expect(MedusaModule.getModuleInstance("moduleKey")).toEqual(moduleB)
}) })
it("should retrieve the module by their given alias", async () => { it("should retrieve the module by their given alias", async () => {
const moduleA = await MedusaModule.bootstrap("moduleKey", "@path", { const moduleA = await MedusaModule.bootstrap({
scope: MODULE_SCOPE.INTERNAL, moduleKey: "moduleKey",
resources: MODULE_RESOURCE_TYPE.ISOLATED, defaultPath: "@path",
resolve: "@path", declaration: {
alias: "mod_A", scope: MODULE_SCOPE.INTERNAL,
options: { resources: MODULE_RESOURCE_TYPE.ISOLATED,
abc: 123, resolve: "@path",
}, alias: "mod_A",
} as InternalModuleDeclaration) options: {
abc: 123,
},
} as InternalModuleDeclaration,
})
const moduleB = await MedusaModule.bootstrap("moduleKey", "@path", { const moduleB = await MedusaModule.bootstrap({
scope: MODULE_SCOPE.INTERNAL, moduleKey: "moduleKey",
resources: MODULE_RESOURCE_TYPE.ISOLATED, defaultPath: "@path",
resolve: "@path", declaration: {
main: true, scope: MODULE_SCOPE.INTERNAL,
alias: "mod_B", resources: MODULE_RESOURCE_TYPE.ISOLATED,
options: { resolve: "@path",
different_options: "abc", main: true,
}, alias: "mod_B",
} as InternalModuleDeclaration) options: {
different_options: "abc",
},
} as InternalModuleDeclaration,
})
const moduleC = await MedusaModule.bootstrap("moduleKey", "@path", { const moduleC = await MedusaModule.bootstrap({
scope: MODULE_SCOPE.INTERNAL, moduleKey: "moduleKey",
resources: MODULE_RESOURCE_TYPE.ISOLATED, defaultPath: "@path",
resolve: "@path", declaration: {
alias: "mod_C", scope: MODULE_SCOPE.INTERNAL,
options: { resources: MODULE_RESOURCE_TYPE.ISOLATED,
moduleC: true, resolve: "@path",
}, alias: "mod_C",
} as InternalModuleDeclaration) options: {
moduleC: true,
},
} as InternalModuleDeclaration,
})
// main // main
expect(MedusaModule.getModuleInstance("moduleKey")).toEqual(moduleB) expect(MedusaModule.getModuleInstance("moduleKey")).toEqual(moduleB)
@@ -195,37 +239,49 @@ describe("Medusa Modules", () => {
}) })
it("should prevent two main modules being set as 'main'", async () => { it("should prevent two main modules being set as 'main'", async () => {
await MedusaModule.bootstrap("moduleKey", "@path", { await MedusaModule.bootstrap({
scope: MODULE_SCOPE.INTERNAL, moduleKey: "moduleKey",
resources: MODULE_RESOURCE_TYPE.ISOLATED, defaultPath: "@path",
resolve: "@path", declaration: {
alias: "mod_A", scope: MODULE_SCOPE.INTERNAL,
options: { resources: MODULE_RESOURCE_TYPE.ISOLATED,
abc: 123, resolve: "@path",
}, alias: "mod_A",
} as InternalModuleDeclaration) options: {
abc: 123,
},
} as InternalModuleDeclaration,
})
await MedusaModule.bootstrap("moduleKey", "@path", { await MedusaModule.bootstrap({
scope: MODULE_SCOPE.INTERNAL, moduleKey: "moduleKey",
resources: MODULE_RESOURCE_TYPE.ISOLATED, defaultPath: "@path",
resolve: "@path", declaration: {
main: true, scope: MODULE_SCOPE.INTERNAL,
alias: "mod_B", resources: MODULE_RESOURCE_TYPE.ISOLATED,
options: { resolve: "@path",
different_options: "abc", main: true,
}, alias: "mod_B",
} as InternalModuleDeclaration) options: {
different_options: "abc",
},
} as InternalModuleDeclaration,
})
const moduleC = MedusaModule.bootstrap("moduleKey", "@path", { const moduleC = MedusaModule.bootstrap({
scope: MODULE_SCOPE.INTERNAL, moduleKey: "moduleKey",
resources: MODULE_RESOURCE_TYPE.ISOLATED, defaultPath: "@path",
resolve: "@path", declaration: {
main: true, scope: MODULE_SCOPE.INTERNAL,
alias: "mod_C", resources: MODULE_RESOURCE_TYPE.ISOLATED,
options: { resolve: "@path",
moduleC: true, main: true,
}, alias: "mod_C",
} as InternalModuleDeclaration) options: {
moduleC: true,
},
} as InternalModuleDeclaration,
})
expect(moduleC).rejects.toThrow( expect(moduleC).rejects.toThrow(
"Module moduleKey already have a 'main' registered." "Module moduleKey already have a 'main' registered."
@@ -233,25 +289,33 @@ describe("Medusa Modules", () => {
}) })
it("should prevent the same alias be used for different instances of the same module", async () => { it("should prevent the same alias be used for different instances of the same module", async () => {
await MedusaModule.bootstrap("moduleKey", "@path", { await MedusaModule.bootstrap({
scope: MODULE_SCOPE.INTERNAL, moduleKey: "moduleKey",
resources: MODULE_RESOURCE_TYPE.ISOLATED, defaultPath: "@path",
resolve: "@path", declaration: {
alias: "module_alias", scope: MODULE_SCOPE.INTERNAL,
options: { resources: MODULE_RESOURCE_TYPE.ISOLATED,
different_options: "abc", resolve: "@path",
}, alias: "module_alias",
} as InternalModuleDeclaration) options: {
different_options: "abc",
},
} as InternalModuleDeclaration,
})
const moduleC = MedusaModule.bootstrap("moduleKey", "@path", { const moduleC = MedusaModule.bootstrap({
scope: MODULE_SCOPE.INTERNAL, moduleKey: "moduleKey",
resources: MODULE_RESOURCE_TYPE.ISOLATED, defaultPath: "@path",
resolve: "@path", declaration: {
alias: "module_alias", scope: MODULE_SCOPE.INTERNAL,
options: { resources: MODULE_RESOURCE_TYPE.ISOLATED,
moduleC: true, resolve: "@path",
}, alias: "module_alias",
} as InternalModuleDeclaration) options: {
moduleC: true,
},
} as InternalModuleDeclaration,
})
expect(moduleC).rejects.toThrow( expect(moduleC).rejects.toThrow(
"Module moduleKey already registed as 'module_alias'. Please choose a different alias." "Module moduleKey already registed as 'module_alias'. Please choose a different alias."
+39 -11
View File
@@ -6,6 +6,7 @@ import {
InternalModuleDeclaration, InternalModuleDeclaration,
LoadedModule, LoadedModule,
LoaderOptions, LoaderOptions,
MedusaContainer,
MODULE_RESOURCE_TYPE, MODULE_RESOURCE_TYPE,
MODULE_SCOPE, MODULE_SCOPE,
ModuleDefinition, ModuleDefinition,
@@ -15,14 +16,20 @@ import {
} from "@medusajs/types" } from "@medusajs/types"
import { import {
ContainerRegistrationKeys, ContainerRegistrationKeys,
ModulesSdkUtils, createMedusaContainer,
isObject, isObject,
ModulesSdkUtils,
} from "@medusajs/utils" } from "@medusajs/utils"
import { MODULE_PACKAGE_NAMES, Modules } from "./definitions" import {
MODULE_PACKAGE_NAMES,
ModuleRegistrationName,
Modules,
} from "./definitions"
import { MedusaModule } from "./medusa-module" import { MedusaModule } from "./medusa-module"
import { RemoteLink } from "./remote-link" import { RemoteLink } from "./remote-link"
import { RemoteQuery } from "./remote-query" import { RemoteQuery } from "./remote-query"
import { cleanGraphQLSchema } from "./utils" import { cleanGraphQLSchema } from "./utils"
import { asValue } from "awilix"
const LinkModulePackage = "@medusajs/link-modules" const LinkModulePackage = "@medusajs/link-modules"
@@ -57,7 +64,7 @@ export type SharedResources = {
} }
} }
async function loadModules(modulesConfig, injectedDependencies) { async function loadModules(modulesConfig, sharedContainer) {
const allModules = {} const allModules = {}
await Promise.all( await Promise.all(
@@ -85,14 +92,18 @@ async function loadModules(modulesConfig, injectedDependencies) {
declaration.resources = MODULE_RESOURCE_TYPE.SHARED declaration.resources = MODULE_RESOURCE_TYPE.SHARED
} }
const loaded = (await MedusaModule.bootstrap( const loaded = (await MedusaModule.bootstrap({
moduleName, moduleKey: moduleName,
path, defaultPath: path,
declaration, declaration,
undefined, sharedContainer,
injectedDependencies, moduleDefinition: definition,
definition })) as LoadedModule
)) as LoadedModule
const service = loaded[moduleName]
sharedContainer.register({
[service.__definition.registrationName]: asValue(service),
})
if (allModules[moduleName] && !Array.isArray(allModules[moduleName])) { if (allModules[moduleName] && !Array.isArray(allModules[moduleName])) {
allModules[moduleName] = [] allModules[moduleName] = []
@@ -153,6 +164,7 @@ function registerCustomJoinerConfigs(servicesConfig: ModuleJoinerConfig[]) {
export async function MedusaApp( export async function MedusaApp(
{ {
sharedContainer,
sharedResourcesConfig, sharedResourcesConfig,
servicesConfig, servicesConfig,
modulesConfigPath, modulesConfigPath,
@@ -162,6 +174,7 @@ export async function MedusaApp(
remoteFetchData, remoteFetchData,
injectedDependencies, injectedDependencies,
}: { }: {
sharedContainer?: MedusaContainer
sharedResourcesConfig?: SharedResources sharedResourcesConfig?: SharedResources
loadedModules?: LoadedModule[] loadedModules?: LoadedModule[]
servicesConfig?: ModuleJoinerConfig[] servicesConfig?: ModuleJoinerConfig[]
@@ -185,6 +198,8 @@ export async function MedusaApp(
notFound?: Record<string, Record<string, string>> notFound?: Record<string, Record<string, string>>
runMigrations: RunMigrationFn runMigrations: RunMigrationFn
}> { }> {
const sharedContainer_ = createMedusaContainer({}, sharedContainer)
const modules: MedusaModuleConfig = const modules: MedusaModuleConfig =
modulesConfig ?? modulesConfig ??
( (
@@ -222,7 +237,20 @@ export async function MedusaApp(
linkModuleOptions = linkModule linkModuleOptions = linkModule
} }
const allModules = await loadModules(modules, injectedDependencies) for (const injectedDependency of Object.keys(injectedDependencies)) {
sharedContainer_.register({
[injectedDependency]: asValue(injectedDependencies[injectedDependency]),
})
}
const allModules = await loadModules(modules, sharedContainer_)
// Share Event bus with link modules
injectedDependencies[ModuleRegistrationName.EVENT_BUS] =
sharedContainer_.resolve(ModuleRegistrationName.EVENT_BUS, {
allowUnregistered: true,
})
const { const {
remoteLink, remoteLink,
linkResolution, linkResolution,
+38 -16
View File
@@ -3,6 +3,7 @@ import {
InternalModuleDeclaration, InternalModuleDeclaration,
LinkModuleDefinition, LinkModuleDefinition,
LoadedModule, LoadedModule,
MedusaContainer,
MODULE_RESOURCE_TYPE, MODULE_RESOURCE_TYPE,
MODULE_SCOPE, MODULE_SCOPE,
ModuleDefinition, ModuleDefinition,
@@ -48,6 +49,23 @@ type ModuleAlias = {
main?: boolean main?: boolean
} }
export type ModuleBootstrapOptions = {
moduleKey: string
defaultPath: string
declaration?: InternalModuleDeclaration | ExternalModuleDeclaration
moduleExports?: ModuleExports
sharedContainer?: MedusaContainer
moduleDefinition?: ModuleDefinition
injectedDependencies?: Record<string, any>
}
export type LinkModuleBootstrapOptions = {
definition: LinkModuleDefinition
declaration?: InternalModuleDeclaration
moduleExports?: ModuleExports
injectedDependencies?: Record<string, any>
}
export class MedusaModule { export class MedusaModule {
private static instances_: Map<string, any> = new Map() private static instances_: Map<string, any> = new Map()
private static modules_: Map<string, ModuleAlias[]> = new Map() private static modules_: Map<string, ModuleAlias[]> = new Map()
@@ -146,14 +164,15 @@ export class MedusaModule {
MedusaModule.modules_.set(moduleKey, modules!) MedusaModule.modules_.set(moduleKey, modules!)
} }
public static async bootstrap<T>( public static async bootstrap<T>({
moduleKey: string, moduleKey,
defaultPath: string, defaultPath,
declaration?: InternalModuleDeclaration | ExternalModuleDeclaration, declaration,
moduleExports?: ModuleExports, moduleExports,
injectedDependencies?: Record<string, any>, sharedContainer,
moduleDefinition?: ModuleDefinition moduleDefinition,
): Promise<{ injectedDependencies,
}: ModuleBootstrapOptions): Promise<{
[key: string]: T [key: string]: T
}> { }> {
const hashKey = simpleHash( const hashKey = simpleHash(
@@ -193,11 +212,14 @@ export class MedusaModule {
} }
} }
const container = createMedusaContainer() const container = createMedusaContainer({}, sharedContainer)
if (injectedDependencies) { if (injectedDependencies) {
for (const service in injectedDependencies) { for (const service in injectedDependencies) {
container.register(service, asValue(injectedDependencies[service])) container.register(service, asValue(injectedDependencies[service]))
if (!container.hasRegistration(service)) {
container.register(service, asValue(injectedDependencies[service]))
}
} }
} }
@@ -255,19 +277,19 @@ export class MedusaModule {
return services return services
} }
public static async bootstrapLink( public static async bootstrapLink({
definition: LinkModuleDefinition, definition,
declaration?: InternalModuleDeclaration, declaration,
moduleExports?: ModuleExports, moduleExports,
injectedDependencies?: Record<string, any> injectedDependencies,
): Promise<{ }: LinkModuleBootstrapOptions): Promise<{
[key: string]: unknown [key: string]: unknown
}> { }> {
const moduleKey = definition.key const moduleKey = definition.key
const hashKey = simpleHash(stringifyCircular({ moduleKey, declaration })) const hashKey = simpleHash(stringifyCircular({ moduleKey, declaration }))
if (MedusaModule.instances_.has(hashKey)) { if (MedusaModule.instances_.has(hashKey)) {
return MedusaModule.instances_.get(hashKey) return { [moduleKey]: MedusaModule.instances_.get(hashKey) }
} }
if (MedusaModule.loading_.has(hashKey)) { if (MedusaModule.loading_.has(hashKey)) {
+4 -2
View File
@@ -34,6 +34,8 @@ export class RemoteQuery {
) )
} }
const servicesConfig_ = [...servicesConfig]
for (const mod of modulesLoaded) { for (const mod of modulesLoaded) {
if (!mod.__definition.isQueryable) { if (!mod.__definition.isQueryable) {
continue continue
@@ -48,12 +50,12 @@ export class RemoteQuery {
} }
this.modulesMap.set(serviceName, mod) this.modulesMap.set(serviceName, mod)
servicesConfig!.push(mod.__joinerConfig) servicesConfig_!.push(mod.__joinerConfig)
} }
this.customRemoteFetchData = customRemoteFetchData this.customRemoteFetchData = customRemoteFetchData
this.remoteJoiner = new RemoteJoiner( this.remoteJoiner = new RemoteJoiner(
servicesConfig as JoinerServiceConfig[], servicesConfig_ as JoinerServiceConfig[],
this.remoteFetchData.bind(this) this.remoteFetchData.bind(this)
) )
} }
+9 -7
View File
@@ -19,13 +19,15 @@ export const initialize = async (
): Promise<IPricingModuleService> => { ): Promise<IPricingModuleService> => {
const serviceKey = Modules.PRICING const serviceKey = Modules.PRICING
const loaded = await MedusaModule.bootstrap<IPricingModuleService>( const loaded = await MedusaModule.bootstrap<IPricingModuleService>({
serviceKey, moduleKey: serviceKey,
MODULE_PACKAGE_NAMES[Modules.PRICING], defaultPath: MODULE_PACKAGE_NAMES[Modules.PRICING],
options as InternalModuleDeclaration | ExternalModuleDeclaration, declaration: options as
moduleDefinition, | InternalModuleDeclaration
injectedDependencies | ExternalModuleDeclaration,
) injectedDependencies,
moduleExports: moduleDefinition,
})
return loaded[serviceKey] return loaded[serviceKey]
} }
+10 -8
View File
@@ -1,8 +1,8 @@
import { import {
ExternalModuleDeclaration, ExternalModuleDeclaration,
InternalModuleDeclaration, InternalModuleDeclaration,
MODULE_PACKAGE_NAMES,
MedusaModule, MedusaModule,
MODULE_PACKAGE_NAMES,
Modules, Modules,
} from "@medusajs/modules-sdk" } from "@medusajs/modules-sdk"
import { IProductModuleService, ModulesSdkTypes } from "@medusajs/types" import { IProductModuleService, ModulesSdkTypes } from "@medusajs/types"
@@ -20,13 +20,15 @@ export const initialize = async (
): Promise<IProductModuleService> => { ): Promise<IProductModuleService> => {
const serviceKey = Modules.PRODUCT const serviceKey = Modules.PRODUCT
const loaded = await MedusaModule.bootstrap<IProductModuleService>( const loaded = await MedusaModule.bootstrap<IProductModuleService>({
serviceKey, moduleKey: serviceKey,
MODULE_PACKAGE_NAMES[Modules.PRODUCT], defaultPath: MODULE_PACKAGE_NAMES[Modules.PRODUCT],
options as InternalModuleDeclaration | ExternalModuleDeclaration, declaration: options as
moduleDefinition, | InternalModuleDeclaration
injectedDependencies | ExternalModuleDeclaration,
) injectedDependencies,
moduleExports: moduleDefinition,
})
return loaded[serviceKey] return loaded[serviceKey]
} }
@@ -2,6 +2,7 @@ import {
ExternalModuleDeclaration, ExternalModuleDeclaration,
InternalModuleDeclaration, InternalModuleDeclaration,
MedusaModule, MedusaModule,
MODULE_PACKAGE_NAMES,
Modules, Modules,
} from "@medusajs/modules-sdk" } from "@medusajs/modules-sdk"
import { IEventBusService, IStockLocationService } from "@medusajs/types" import { IEventBusService, IStockLocationService } from "@medusajs/types"
@@ -15,13 +16,15 @@ export const initialize = async (
} }
): Promise<IStockLocationService> => { ): Promise<IStockLocationService> => {
const serviceKey = Modules.STOCK_LOCATION const serviceKey = Modules.STOCK_LOCATION
const loaded = await MedusaModule.bootstrap<IStockLocationService>( const loaded = await MedusaModule.bootstrap<IStockLocationService>({
serviceKey, moduleKey: serviceKey,
"@medusajs/stock-location", defaultPath: MODULE_PACKAGE_NAMES[Modules.STOCK_LOCATION],
options as InternalModuleDeclaration | ExternalModuleDeclaration, declaration: options as
moduleDefinition, | InternalModuleDeclaration
injectedDependencies | ExternalModuleDeclaration,
) injectedDependencies,
moduleExports: moduleDefinition,
})
return loaded[serviceKey] return loaded[serviceKey]
} }