feat(modules-sdk): Remote Query (#4463)

* feat: Remote Query
This commit is contained in:
Carlos R. L. Rodrigues
2023-07-19 15:35:36 -03:00
committed by GitHub
parent 95c538c675
commit 5a8a889c6d
57 changed files with 1286 additions and 423 deletions
@@ -3,27 +3,49 @@ import {
MODULE_RESOURCE_TYPE,
MODULE_SCOPE,
} from "@medusajs/types"
import { MedusaModule } from "../../medusa-module"
const mockRegisterMedusaModule = jest
.fn()
.mockImplementation(() => Promise.resolve([]))
const mockModuleLoader = jest.fn().mockImplementation(() => Promise.resolve({}))
import { MedusaModule } from "../../medusa-module"
import { asValue } from "awilix"
const mockRegisterMedusaModule = jest.fn().mockImplementation(() => {
return {
moduleKey: {
definition: {
key: "moduleKey",
registrationName: "moduleKey",
},
moduleDeclaration: {
scope: MODULE_SCOPE.INTERNAL,
resources: MODULE_RESOURCE_TYPE.SHARED,
},
},
}
})
const mockModuleLoader = jest.fn().mockImplementation(({ container }) => {
container.register({
moduleKey: asValue({}),
})
return Promise.resolve({})
})
jest.mock("./../../loaders", () => ({
registerMedusaModule: jest
.fn()
.mockImplementation((...args) => mockRegisterMedusaModule()),
moduleLoader: jest.fn().mockImplementation((...args) => mockModuleLoader()),
moduleLoader: jest
.fn()
.mockImplementation((...args) => mockModuleLoader.apply(this, args)),
}))
describe("Medusa Module", () => {
describe("Medusa Modules", () => {
beforeEach(() => {
MedusaModule.clearInstances()
jest.resetModules()
jest.clearAllMocks()
})
it("MedusaModule bootstrap - Singleton instances", async () => {
it("should create singleton instances", async () => {
await MedusaModule.bootstrap("moduleKey", "@path", {
scope: MODULE_SCOPE.INTERNAL,
resources: MODULE_RESOURCE_TYPE.ISOLATED,
@@ -57,4 +79,182 @@ describe("Medusa Module", () => {
expect(mockRegisterMedusaModule).toBeCalledTimes(2)
expect(mockModuleLoader).toBeCalledTimes(2)
})
it("should prevent the module being loaded multiple times under concurrent requests", async () => {
const load: any = []
for (let i = 5; i--; ) {
load.push(
MedusaModule.bootstrap("moduleKey", "@path", {
scope: MODULE_SCOPE.INTERNAL,
resources: MODULE_RESOURCE_TYPE.ISOLATED,
resolve: "@path",
options: {
abc: 123,
},
} as InternalModuleDeclaration)
)
}
const intances = Promise.all(load)
expect(mockRegisterMedusaModule).toBeCalledTimes(1)
expect(mockModuleLoader).toBeCalledTimes(1)
expect(intances[(await intances).length - 1]).toBe(intances[0])
})
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", {
scope: MODULE_SCOPE.INTERNAL,
resources: MODULE_RESOURCE_TYPE.ISOLATED,
resolve: "@path",
options: {
abc: 123,
},
} as InternalModuleDeclaration)
const moduleB = await MedusaModule.bootstrap("moduleKey", "@path", {
scope: MODULE_SCOPE.INTERNAL,
resources: MODULE_RESOURCE_TYPE.ISOLATED,
resolve: "@path",
options: {
different_options: "abc",
},
} as InternalModuleDeclaration)
expect(MedusaModule.getModuleInstance("moduleKey")).toEqual(moduleA)
})
it("should return the module flagged as 'main' when multiple instances are available", async () => {
const moduleA = await MedusaModule.bootstrap("moduleKey", "@path", {
scope: MODULE_SCOPE.INTERNAL,
resources: MODULE_RESOURCE_TYPE.ISOLATED,
resolve: "@path",
options: {
abc: 123,
},
} as InternalModuleDeclaration)
const moduleB = await MedusaModule.bootstrap("moduleKey", "@path", {
scope: MODULE_SCOPE.INTERNAL,
resources: MODULE_RESOURCE_TYPE.ISOLATED,
resolve: "@path",
main: true,
options: {
different_options: "abc",
},
} as InternalModuleDeclaration)
expect(MedusaModule.getModuleInstance("moduleKey")).toEqual(moduleB)
})
it("should retrieve the module by their given alias", async () => {
const moduleA = await MedusaModule.bootstrap("moduleKey", "@path", {
scope: MODULE_SCOPE.INTERNAL,
resources: MODULE_RESOURCE_TYPE.ISOLATED,
resolve: "@path",
alias: "mod_A",
options: {
abc: 123,
},
} as InternalModuleDeclaration)
const moduleB = await MedusaModule.bootstrap("moduleKey", "@path", {
scope: MODULE_SCOPE.INTERNAL,
resources: MODULE_RESOURCE_TYPE.ISOLATED,
resolve: "@path",
main: true,
alias: "mod_B",
options: {
different_options: "abc",
},
} as InternalModuleDeclaration)
const moduleC = await MedusaModule.bootstrap("moduleKey", "@path", {
scope: MODULE_SCOPE.INTERNAL,
resources: MODULE_RESOURCE_TYPE.ISOLATED,
resolve: "@path",
alias: "mod_C",
options: {
moduleC: true,
},
} as InternalModuleDeclaration)
// main
expect(MedusaModule.getModuleInstance("moduleKey")).toEqual(moduleB)
expect(MedusaModule.getModuleInstance("moduleKey", "mod_A")).toEqual(
moduleA
)
expect(MedusaModule.getModuleInstance("moduleKey", "mod_B")).toEqual(
moduleB
)
expect(MedusaModule.getModuleInstance("moduleKey", "mod_C")).toEqual(
moduleC
)
})
it("should prevent two main modules being set as 'main'", async () => {
await MedusaModule.bootstrap("moduleKey", "@path", {
scope: MODULE_SCOPE.INTERNAL,
resources: MODULE_RESOURCE_TYPE.ISOLATED,
resolve: "@path",
alias: "mod_A",
options: {
abc: 123,
},
} as InternalModuleDeclaration)
await MedusaModule.bootstrap("moduleKey", "@path", {
scope: MODULE_SCOPE.INTERNAL,
resources: MODULE_RESOURCE_TYPE.ISOLATED,
resolve: "@path",
main: true,
alias: "mod_B",
options: {
different_options: "abc",
},
} as InternalModuleDeclaration)
const moduleC = MedusaModule.bootstrap("moduleKey", "@path", {
scope: MODULE_SCOPE.INTERNAL,
resources: MODULE_RESOURCE_TYPE.ISOLATED,
resolve: "@path",
main: true,
alias: "mod_C",
options: {
moduleC: true,
},
} as InternalModuleDeclaration)
expect(moduleC).rejects.toThrow(
"Module moduleKey already have a 'main' registered."
)
})
it("should prevent the same alias be used for different instances of the same module", async () => {
await MedusaModule.bootstrap("moduleKey", "@path", {
scope: MODULE_SCOPE.INTERNAL,
resources: MODULE_RESOURCE_TYPE.ISOLATED,
resolve: "@path",
alias: "module_alias",
options: {
different_options: "abc",
},
} as InternalModuleDeclaration)
const moduleC = MedusaModule.bootstrap("moduleKey", "@path", {
scope: MODULE_SCOPE.INTERNAL,
resources: MODULE_RESOURCE_TYPE.ISOLATED,
resolve: "@path",
alias: "module_alias",
options: {
moduleC: true,
},
} as InternalModuleDeclaration)
expect(moduleC).rejects.toThrow(
"Module moduleKey already registed as 'module_alias'. Please choose a different alias."
)
})
})