feat(providers): locking redis (#9544)
This commit is contained in:
committed by
GitHub
parent
e77a2ff032
commit
4a03bdbb86
@@ -82,11 +82,11 @@ async function loadModule(
|
||||
return
|
||||
}
|
||||
|
||||
return await loadInternalModule(
|
||||
return await loadInternalModule({
|
||||
container,
|
||||
resolution,
|
||||
logger,
|
||||
migrationOnly,
|
||||
loaderOnly
|
||||
)
|
||||
loaderOnly,
|
||||
})
|
||||
}
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import { ModuleExports } from "@medusajs/types"
|
||||
import { ModuleService } from "./services/module-service"
|
||||
import { Module } from "@medusajs/utils"
|
||||
|
||||
const moduleExports: ModuleExports = {
|
||||
service: ModuleService,
|
||||
}
|
||||
|
||||
export * from "./services/module-service"
|
||||
|
||||
export default Module("module-with-providers", moduleExports)
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
import { ModuleProviderService } from "./services/provider-service"
|
||||
import { ModuleProvider } from "@medusajs/utils"
|
||||
|
||||
export * from "./services/provider-service"
|
||||
|
||||
export default ModuleProvider("provider-1", {
|
||||
services: [ModuleProviderService],
|
||||
})
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
export class ModuleProviderService {
|
||||
static identifier = "provider-1"
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
import { ModuleProvider2Service } from "./services/provider-service"
|
||||
import { ModuleProvider } from "@medusajs/utils"
|
||||
|
||||
export * from "./services/provider-service"
|
||||
|
||||
export default ModuleProvider("provider-2", {
|
||||
services: [ModuleProvider2Service],
|
||||
})
|
||||
+1
@@ -0,0 +1 @@
|
||||
export class ModuleProvider2Service {}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
import { InternalModuleDeclaration } from "@medusajs/types"
|
||||
|
||||
export class ModuleService {
|
||||
constructor(
|
||||
public container: Record<any, any>,
|
||||
public moduleOptions: Record<any, any>,
|
||||
public moduleDeclaration: InternalModuleDeclaration
|
||||
) {}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { IModuleService, ModuleResolution } from "@medusajs/types"
|
||||
import { upperCaseFirst } from "@medusajs/utils"
|
||||
import { createMedusaContainer, upperCaseFirst } from "@medusajs/utils"
|
||||
import { join } from "path"
|
||||
import {
|
||||
ModuleWithDmlMixedWithoutJoinerConfigFixtures,
|
||||
@@ -7,79 +7,253 @@ import {
|
||||
ModuleWithJoinerConfigFixtures,
|
||||
ModuleWithoutJoinerConfigFixtures,
|
||||
} from "../__fixtures__"
|
||||
import { loadResources } from "../load-internal"
|
||||
import {
|
||||
getProviderRegistrationKey,
|
||||
loadInternalModule,
|
||||
loadResources,
|
||||
} from "../load-internal"
|
||||
import { ModuleProviderService as ModuleServiceWithProviderProvider1 } from "../__fixtures__/module-with-providers/provider-1"
|
||||
import { ModuleProvider2Service as ModuleServiceWithProviderProvider2 } from "../__fixtures__/module-with-providers/provider-2"
|
||||
import { ModuleService as ModuleServiceWithProvider } from "../__fixtures__/module-with-providers"
|
||||
|
||||
describe("load internal - load resources", () => {
|
||||
describe("when loading the module resources from a path", () => {
|
||||
test("should return the correct resources and generate the correct joiner config from a mix of DML entities and mikro orm entities", async () => {
|
||||
const { ModuleService, EntityModel, dmlEntity } =
|
||||
ModuleWithDmlMixedWithoutJoinerConfigFixtures
|
||||
describe("load internal", () => {
|
||||
describe("loadResources", () => {
|
||||
describe("when loading the module resources from a path", () => {
|
||||
test("should return the correct resources and generate the correct joiner config from a mix of DML entities and mikro orm entities", async () => {
|
||||
const { ModuleService, EntityModel, dmlEntity } =
|
||||
ModuleWithDmlMixedWithoutJoinerConfigFixtures
|
||||
|
||||
const moduleResolution: ModuleResolution = {
|
||||
resolutionPath: join(
|
||||
__dirname,
|
||||
"../__fixtures__/module-with-dml-mixed-without-joiner-config"
|
||||
),
|
||||
definition: {
|
||||
key: "module-with-dml-mixed-without-joiner-config",
|
||||
label: "Module with DML mixed without joiner config",
|
||||
defaultPackage: false,
|
||||
defaultModuleDeclaration: {
|
||||
scope: "internal",
|
||||
resources: "shared",
|
||||
const moduleResolution: ModuleResolution = {
|
||||
resolutionPath: join(
|
||||
__dirname,
|
||||
"../__fixtures__/module-with-dml-mixed-without-joiner-config"
|
||||
),
|
||||
definition: {
|
||||
key: "module-with-dml-mixed-without-joiner-config",
|
||||
label: "Module with DML mixed without joiner config",
|
||||
defaultPackage: false,
|
||||
defaultModuleDeclaration: {
|
||||
scope: "internal",
|
||||
resources: "shared",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
expect(
|
||||
(ModuleService.prototype as IModuleService).__joinerConfig
|
||||
).toBeUndefined()
|
||||
expect(
|
||||
(ModuleService.prototype as IModuleService).__joinerConfig
|
||||
).toBeUndefined()
|
||||
|
||||
const resources = await loadResources({
|
||||
moduleResolution,
|
||||
discoveryPath: moduleResolution.resolutionPath as string,
|
||||
const resources = await loadResources({
|
||||
moduleResolution,
|
||||
discoveryPath: moduleResolution.resolutionPath as string,
|
||||
})
|
||||
|
||||
expect(resources).toBeDefined()
|
||||
expect(resources.services).toHaveLength(1)
|
||||
expect(resources.services[0]).toEqual(ModuleService)
|
||||
expect(resources.models).toHaveLength(2)
|
||||
expect(resources.models).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({ name: upperCaseFirst(dmlEntity.name) }),
|
||||
expect.objectContaining({ name: upperCaseFirst(EntityModel.name) }),
|
||||
])
|
||||
)
|
||||
expect(resources.repositories).toHaveLength(0)
|
||||
expect(resources.loaders).toHaveLength(2)
|
||||
expect(resources.loaders).toEqual([
|
||||
expect.objectContaining({ name: "connectionLoader" }),
|
||||
expect.objectContaining({ name: "containerLoader" }),
|
||||
])
|
||||
expect(resources.moduleService).toEqual(ModuleService)
|
||||
|
||||
expect(
|
||||
(resources.moduleService.prototype as IModuleService).__joinerConfig
|
||||
).toBeDefined()
|
||||
|
||||
const generatedJoinerConfig = (
|
||||
resources.moduleService.prototype as IModuleService
|
||||
).__joinerConfig?.()!
|
||||
|
||||
expect(generatedJoinerConfig).toEqual(
|
||||
expect.objectContaining({
|
||||
serviceName: "module-with-dml-mixed-without-joiner-config",
|
||||
primaryKeys: ["id"],
|
||||
linkableKeys: {
|
||||
dml_entity_id: "DmlEntity",
|
||||
entity_model_id: "EntityModel",
|
||||
},
|
||||
alias: [
|
||||
{
|
||||
name: ["dml_entity", "dml_entities"],
|
||||
entity: "DmlEntity",
|
||||
args: {
|
||||
methodSuffix: "DmlEntities",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["entity_model", "entity_models"],
|
||||
entity: "EntityModel",
|
||||
args: {
|
||||
methodSuffix: "EntityModels",
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
expect(resources).toBeDefined()
|
||||
expect(resources.services).toHaveLength(1)
|
||||
expect(resources.services[0]).toEqual(ModuleService)
|
||||
expect(resources.models).toHaveLength(2)
|
||||
expect(resources.models).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({ name: upperCaseFirst(dmlEntity.name) }),
|
||||
expect.objectContaining({ name: upperCaseFirst(EntityModel.name) }),
|
||||
test("should return the correct resources and generate the correct joiner config from DML entities", async () => {
|
||||
const { ModuleService, entityModel, dmlEntity } =
|
||||
ModuleWithDmlWithoutJoinerConfigFixtures
|
||||
|
||||
const moduleResolution: ModuleResolution = {
|
||||
resolutionPath: join(
|
||||
__dirname,
|
||||
"../__fixtures__/module-with-dml-without-joiner-config"
|
||||
),
|
||||
definition: {
|
||||
key: "module-with-dml-without-joiner-config",
|
||||
label: "Module with DML without joiner config",
|
||||
defaultPackage: false,
|
||||
defaultModuleDeclaration: {
|
||||
scope: "internal",
|
||||
resources: "shared",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
expect(
|
||||
(ModuleService.prototype as IModuleService).__joinerConfig
|
||||
).toBeUndefined()
|
||||
|
||||
const resources = await loadResources({
|
||||
moduleResolution,
|
||||
discoveryPath: moduleResolution.resolutionPath as string,
|
||||
})
|
||||
|
||||
expect(resources).toBeDefined()
|
||||
expect(resources.services).toHaveLength(1)
|
||||
expect(resources.services[0]).toEqual(ModuleService)
|
||||
expect(resources.models).toHaveLength(2)
|
||||
expect(resources.models).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({ name: upperCaseFirst(dmlEntity.name) }),
|
||||
expect.objectContaining({ name: upperCaseFirst(entityModel.name) }),
|
||||
])
|
||||
)
|
||||
expect(resources.repositories).toHaveLength(0)
|
||||
expect(resources.loaders).toHaveLength(2)
|
||||
expect(resources.loaders).toEqual([
|
||||
expect.objectContaining({ name: "connectionLoader" }),
|
||||
expect.objectContaining({ name: "containerLoader" }),
|
||||
])
|
||||
)
|
||||
expect(resources.repositories).toHaveLength(0)
|
||||
expect(resources.loaders).toHaveLength(2)
|
||||
expect(resources.loaders).toEqual([
|
||||
expect.objectContaining({ name: "connectionLoader" }),
|
||||
expect.objectContaining({ name: "containerLoader" }),
|
||||
])
|
||||
expect(resources.moduleService).toEqual(ModuleService)
|
||||
expect(resources.moduleService).toEqual(ModuleService)
|
||||
|
||||
expect(
|
||||
(resources.moduleService.prototype as IModuleService).__joinerConfig
|
||||
).toBeDefined()
|
||||
expect(
|
||||
(resources.moduleService.prototype as IModuleService).__joinerConfig
|
||||
).toBeDefined()
|
||||
|
||||
const generatedJoinerConfig = (
|
||||
resources.moduleService.prototype as IModuleService
|
||||
).__joinerConfig?.()!
|
||||
const generatedJoinerConfig = (
|
||||
resources.moduleService.prototype as IModuleService
|
||||
).__joinerConfig?.()!
|
||||
|
||||
expect(generatedJoinerConfig).toEqual(
|
||||
expect.objectContaining({
|
||||
serviceName: "module-with-dml-mixed-without-joiner-config",
|
||||
expect(generatedJoinerConfig).toEqual(
|
||||
expect.objectContaining({
|
||||
serviceName: "module-with-dml-without-joiner-config",
|
||||
primaryKeys: ["id"],
|
||||
linkableKeys: {
|
||||
entity_model_id: "EntityModel",
|
||||
dml_entity_id: "DmlEntity",
|
||||
},
|
||||
alias: [
|
||||
{
|
||||
name: ["entity_model", "entity_models"],
|
||||
entity: "EntityModel",
|
||||
args: {
|
||||
methodSuffix: "EntityModels",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["dml_entity", "dml_entities"],
|
||||
entity: "DmlEntity",
|
||||
args: {
|
||||
methodSuffix: "DmlEntities",
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
test("should return the correct resources and generate the correct joiner config from mikro orm entities", async () => {
|
||||
const { ModuleService, EntityModel, Entity2 } =
|
||||
ModuleWithoutJoinerConfigFixtures
|
||||
|
||||
const moduleResolution: ModuleResolution = {
|
||||
resolutionPath: join(
|
||||
__dirname,
|
||||
"../__fixtures__/module-without-joiner-config"
|
||||
),
|
||||
definition: {
|
||||
key: "module-without-joiner-config",
|
||||
label: "Module without joiner config",
|
||||
defaultPackage: false,
|
||||
defaultModuleDeclaration: {
|
||||
scope: "internal",
|
||||
resources: "shared",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
expect(
|
||||
(ModuleService.prototype as IModuleService).__joinerConfig
|
||||
).toBeUndefined()
|
||||
|
||||
const resources = await loadResources({
|
||||
moduleResolution,
|
||||
discoveryPath: moduleResolution.resolutionPath as string,
|
||||
})
|
||||
|
||||
expect(resources).toBeDefined()
|
||||
expect(resources.services).toHaveLength(1)
|
||||
expect(resources.services[0]).toEqual(ModuleService)
|
||||
expect(resources.models).toHaveLength(2)
|
||||
expect(resources.models).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({ name: upperCaseFirst(EntityModel.name) }),
|
||||
expect.objectContaining({ name: upperCaseFirst(Entity2.name) }),
|
||||
])
|
||||
)
|
||||
expect(resources.repositories).toHaveLength(0)
|
||||
expect(resources.loaders).toHaveLength(2)
|
||||
expect(resources.loaders).toEqual([
|
||||
expect.objectContaining({ name: "connectionLoader" }),
|
||||
expect.objectContaining({ name: "containerLoader" }),
|
||||
])
|
||||
expect(resources.moduleService).toEqual(ModuleService)
|
||||
|
||||
expect(
|
||||
(resources.moduleService.prototype as IModuleService).__joinerConfig
|
||||
).toBeDefined()
|
||||
|
||||
const generatedJoinerConfig = (
|
||||
resources.moduleService.prototype as IModuleService
|
||||
).__joinerConfig?.()!
|
||||
|
||||
expect(generatedJoinerConfig).toEqual({
|
||||
serviceName: "module-without-joiner-config",
|
||||
primaryKeys: ["id"],
|
||||
linkableKeys: {
|
||||
dml_entity_id: "DmlEntity",
|
||||
entity2_id: "Entity2",
|
||||
entity_model_id: "EntityModel",
|
||||
},
|
||||
schema: "",
|
||||
alias: [
|
||||
{
|
||||
name: ["dml_entity", "dml_entities"],
|
||||
entity: "DmlEntity",
|
||||
name: ["entity2", "entity2s"],
|
||||
entity: "Entity2",
|
||||
args: {
|
||||
methodSuffix: "DmlEntities",
|
||||
methodSuffix: "Entity2s",
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -91,240 +265,181 @@ describe("load internal - load resources", () => {
|
||||
},
|
||||
],
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
test("should return the correct resources and generate the correct joiner config from DML entities", async () => {
|
||||
const { ModuleService, entityModel, dmlEntity } =
|
||||
ModuleWithDmlWithoutJoinerConfigFixtures
|
||||
|
||||
const moduleResolution: ModuleResolution = {
|
||||
resolutionPath: join(
|
||||
__dirname,
|
||||
"../__fixtures__/module-with-dml-without-joiner-config"
|
||||
),
|
||||
definition: {
|
||||
key: "module-with-dml-without-joiner-config",
|
||||
label: "Module with DML without joiner config",
|
||||
defaultPackage: false,
|
||||
defaultModuleDeclaration: {
|
||||
scope: "internal",
|
||||
resources: "shared",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
expect(
|
||||
(ModuleService.prototype as IModuleService).__joinerConfig
|
||||
).toBeUndefined()
|
||||
|
||||
const resources = await loadResources({
|
||||
moduleResolution,
|
||||
discoveryPath: moduleResolution.resolutionPath as string,
|
||||
})
|
||||
|
||||
expect(resources).toBeDefined()
|
||||
expect(resources.services).toHaveLength(1)
|
||||
expect(resources.services[0]).toEqual(ModuleService)
|
||||
expect(resources.models).toHaveLength(2)
|
||||
expect(resources.models).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({ name: upperCaseFirst(dmlEntity.name) }),
|
||||
expect.objectContaining({ name: upperCaseFirst(entityModel.name) }),
|
||||
])
|
||||
)
|
||||
expect(resources.repositories).toHaveLength(0)
|
||||
expect(resources.loaders).toHaveLength(2)
|
||||
expect(resources.loaders).toEqual([
|
||||
expect.objectContaining({ name: "connectionLoader" }),
|
||||
expect.objectContaining({ name: "containerLoader" }),
|
||||
])
|
||||
expect(resources.moduleService).toEqual(ModuleService)
|
||||
test("should return the correct resources and use the given joiner config", async () => {
|
||||
const { ModuleService, EntityModel, Entity2 } =
|
||||
ModuleWithJoinerConfigFixtures
|
||||
|
||||
expect(
|
||||
(resources.moduleService.prototype as IModuleService).__joinerConfig
|
||||
).toBeDefined()
|
||||
|
||||
const generatedJoinerConfig = (
|
||||
resources.moduleService.prototype as IModuleService
|
||||
).__joinerConfig?.()!
|
||||
|
||||
expect(generatedJoinerConfig).toEqual(
|
||||
expect.objectContaining({
|
||||
serviceName: "module-with-dml-without-joiner-config",
|
||||
primaryKeys: ["id"],
|
||||
linkableKeys: {
|
||||
entity_model_id: "EntityModel",
|
||||
dml_entity_id: "DmlEntity",
|
||||
const moduleResolution: ModuleResolution = {
|
||||
resolutionPath: join(
|
||||
__dirname,
|
||||
"../__fixtures__/module-with-joiner-config"
|
||||
),
|
||||
definition: {
|
||||
key: "module-without-joiner-config",
|
||||
label: "Module without joiner config",
|
||||
defaultPackage: false,
|
||||
defaultModuleDeclaration: {
|
||||
scope: "internal",
|
||||
resources: "shared",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
expect(
|
||||
(ModuleService.prototype as IModuleService).__joinerConfig
|
||||
).toBeDefined()
|
||||
|
||||
const resources = await loadResources({
|
||||
moduleResolution,
|
||||
discoveryPath: moduleResolution.resolutionPath as string,
|
||||
})
|
||||
|
||||
expect(resources).toBeDefined()
|
||||
expect(resources.services).toHaveLength(1)
|
||||
expect(resources.services[0]).toEqual(ModuleService)
|
||||
expect(resources.models).toHaveLength(2)
|
||||
expect(resources.models).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({ name: upperCaseFirst(EntityModel.name) }),
|
||||
expect.objectContaining({ name: upperCaseFirst(Entity2.name) }),
|
||||
])
|
||||
)
|
||||
expect(resources.repositories).toHaveLength(0)
|
||||
expect(resources.loaders).toHaveLength(2)
|
||||
expect(resources.loaders).toEqual([
|
||||
expect.objectContaining({ name: "connectionLoader" }),
|
||||
expect.objectContaining({ name: "containerLoader" }),
|
||||
])
|
||||
expect(resources.moduleService).toEqual(ModuleService)
|
||||
|
||||
const generatedJoinerConfig = (
|
||||
resources.moduleService.prototype as IModuleService
|
||||
).__joinerConfig?.()!
|
||||
|
||||
expect(generatedJoinerConfig).toEqual({
|
||||
serviceName: "module-service",
|
||||
primaryKeys: ["id"],
|
||||
linkableKeys: {},
|
||||
schema: "",
|
||||
alias: [
|
||||
{
|
||||
name: ["entity_model", "entity_models"],
|
||||
entity: "EntityModel",
|
||||
name: ["custom_name"],
|
||||
entity: "Custom",
|
||||
args: {
|
||||
methodSuffix: "EntityModels",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["dml_entity", "dml_entities"],
|
||||
entity: "DmlEntity",
|
||||
args: {
|
||||
methodSuffix: "DmlEntities",
|
||||
methodSuffix: "Customs",
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
test("should return the correct resources and generate the correct joiner config from mikro orm entities", async () => {
|
||||
const { ModuleService, EntityModel, Entity2 } =
|
||||
ModuleWithoutJoinerConfigFixtures
|
||||
|
||||
const moduleResolution: ModuleResolution = {
|
||||
resolutionPath: join(
|
||||
__dirname,
|
||||
"../__fixtures__/module-without-joiner-config"
|
||||
),
|
||||
definition: {
|
||||
key: "module-without-joiner-config",
|
||||
label: "Module without joiner config",
|
||||
defaultPackage: false,
|
||||
defaultModuleDeclaration: {
|
||||
scope: "internal",
|
||||
resources: "shared",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
expect(
|
||||
(ModuleService.prototype as IModuleService).__joinerConfig
|
||||
).toBeUndefined()
|
||||
|
||||
const resources = await loadResources({
|
||||
moduleResolution,
|
||||
discoveryPath: moduleResolution.resolutionPath as string,
|
||||
})
|
||||
|
||||
expect(resources).toBeDefined()
|
||||
expect(resources.services).toHaveLength(1)
|
||||
expect(resources.services[0]).toEqual(ModuleService)
|
||||
expect(resources.models).toHaveLength(2)
|
||||
expect(resources.models).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({ name: upperCaseFirst(EntityModel.name) }),
|
||||
expect.objectContaining({ name: upperCaseFirst(Entity2.name) }),
|
||||
])
|
||||
)
|
||||
expect(resources.repositories).toHaveLength(0)
|
||||
expect(resources.loaders).toHaveLength(2)
|
||||
expect(resources.loaders).toEqual([
|
||||
expect.objectContaining({ name: "connectionLoader" }),
|
||||
expect.objectContaining({ name: "containerLoader" }),
|
||||
])
|
||||
expect(resources.moduleService).toEqual(ModuleService)
|
||||
|
||||
expect(
|
||||
(resources.moduleService.prototype as IModuleService).__joinerConfig
|
||||
).toBeDefined()
|
||||
|
||||
const generatedJoinerConfig = (
|
||||
resources.moduleService.prototype as IModuleService
|
||||
).__joinerConfig?.()!
|
||||
|
||||
expect(generatedJoinerConfig).toEqual({
|
||||
serviceName: "module-without-joiner-config",
|
||||
primaryKeys: ["id"],
|
||||
linkableKeys: {
|
||||
entity2_id: "Entity2",
|
||||
entity_model_id: "EntityModel",
|
||||
},
|
||||
schema: "",
|
||||
alias: [
|
||||
{
|
||||
name: ["entity2", "entity2s"],
|
||||
entity: "Entity2",
|
||||
args: {
|
||||
methodSuffix: "Entity2s",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["entity_model", "entity_models"],
|
||||
entity: "EntityModel",
|
||||
args: {
|
||||
methodSuffix: "EntityModels",
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
test("should return the correct resources and use the given joiner config", async () => {
|
||||
const { ModuleService, EntityModel, Entity2 } =
|
||||
ModuleWithJoinerConfigFixtures
|
||||
|
||||
const moduleResolution: ModuleResolution = {
|
||||
resolutionPath: join(
|
||||
__dirname,
|
||||
"../__fixtures__/module-with-joiner-config"
|
||||
),
|
||||
definition: {
|
||||
key: "module-without-joiner-config",
|
||||
label: "Module without joiner config",
|
||||
defaultPackage: false,
|
||||
defaultModuleDeclaration: {
|
||||
scope: "internal",
|
||||
resources: "shared",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
expect(
|
||||
(ModuleService.prototype as IModuleService).__joinerConfig
|
||||
).toBeDefined()
|
||||
|
||||
const resources = await loadResources({
|
||||
moduleResolution,
|
||||
discoveryPath: moduleResolution.resolutionPath as string,
|
||||
})
|
||||
|
||||
expect(resources).toBeDefined()
|
||||
expect(resources.services).toHaveLength(1)
|
||||
expect(resources.services[0]).toEqual(ModuleService)
|
||||
expect(resources.models).toHaveLength(2)
|
||||
expect(resources.models).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({ name: upperCaseFirst(EntityModel.name) }),
|
||||
expect.objectContaining({ name: upperCaseFirst(Entity2.name) }),
|
||||
])
|
||||
)
|
||||
expect(resources.repositories).toHaveLength(0)
|
||||
expect(resources.loaders).toHaveLength(2)
|
||||
expect(resources.loaders).toEqual([
|
||||
expect.objectContaining({ name: "connectionLoader" }),
|
||||
expect.objectContaining({ name: "containerLoader" }),
|
||||
])
|
||||
expect(resources.moduleService).toEqual(ModuleService)
|
||||
|
||||
const generatedJoinerConfig = (
|
||||
resources.moduleService.prototype as IModuleService
|
||||
).__joinerConfig?.()!
|
||||
|
||||
expect(generatedJoinerConfig).toEqual({
|
||||
serviceName: "module-service",
|
||||
primaryKeys: ["id"],
|
||||
linkableKeys: {},
|
||||
schema: "",
|
||||
alias: [
|
||||
{
|
||||
name: ["custom_name"],
|
||||
entity: "Custom",
|
||||
args: {
|
||||
methodSuffix: "Customs",
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("loadInternalModule", () => {
|
||||
test("should load the module and its providers using their identifier", async () => {
|
||||
const moduleResolution: ModuleResolution = {
|
||||
resolutionPath: join(
|
||||
__dirname,
|
||||
"../__fixtures__/module-with-providers"
|
||||
),
|
||||
moduleDeclaration: {
|
||||
scope: "internal",
|
||||
resources: "shared",
|
||||
},
|
||||
definition: {
|
||||
key: "module-with-providers",
|
||||
label: "Module with providers",
|
||||
defaultPackage: false,
|
||||
defaultModuleDeclaration: {
|
||||
scope: "internal",
|
||||
resources: "shared",
|
||||
},
|
||||
},
|
||||
options: {
|
||||
providers: [
|
||||
{
|
||||
resolve: join(
|
||||
__dirname,
|
||||
"../__fixtures__/module-with-providers/provider-1"
|
||||
),
|
||||
id: "provider-1-id",
|
||||
options: {
|
||||
api_key: "test",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
const container = createMedusaContainer()
|
||||
await loadInternalModule({
|
||||
container: container,
|
||||
resolution: moduleResolution,
|
||||
logger: console as any,
|
||||
})
|
||||
|
||||
const moduleService = container.resolve(moduleResolution.definition.key)
|
||||
const provider = (moduleService as any).container[
|
||||
getProviderRegistrationKey(
|
||||
ModuleServiceWithProviderProvider1.identifier
|
||||
)
|
||||
]
|
||||
|
||||
expect(moduleService).toBeInstanceOf(ModuleServiceWithProvider)
|
||||
expect(provider).toBeInstanceOf(ModuleServiceWithProviderProvider1)
|
||||
})
|
||||
|
||||
test("should load the module and its providers using the provided id", async () => {
|
||||
const moduleResolution: ModuleResolution = {
|
||||
resolutionPath: join(
|
||||
__dirname,
|
||||
"../__fixtures__/module-with-providers"
|
||||
),
|
||||
moduleDeclaration: {
|
||||
scope: "internal",
|
||||
resources: "shared",
|
||||
},
|
||||
definition: {
|
||||
key: "module-with-providers",
|
||||
label: "Module with providers",
|
||||
defaultPackage: false,
|
||||
defaultModuleDeclaration: {
|
||||
scope: "internal",
|
||||
resources: "shared",
|
||||
},
|
||||
},
|
||||
options: {
|
||||
providers: [
|
||||
{
|
||||
resolve: join(
|
||||
__dirname,
|
||||
"../__fixtures__/module-with-providers/provider-2"
|
||||
),
|
||||
id: "provider-2-id",
|
||||
options: {
|
||||
api_key: "test",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
const container = createMedusaContainer()
|
||||
await loadInternalModule({
|
||||
container: container,
|
||||
resolution: moduleResolution,
|
||||
logger: console as any,
|
||||
})
|
||||
|
||||
const moduleService = container.resolve(moduleResolution.definition.key)
|
||||
const provider = (moduleService as any).container[
|
||||
getProviderRegistrationKey(moduleResolution.options!.providers![0].id)
|
||||
]
|
||||
|
||||
expect(moduleService).toBeInstanceOf(ModuleServiceWithProvider)
|
||||
expect(provider).toBeInstanceOf(ModuleServiceWithProviderProvider2)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -7,6 +7,9 @@ import {
|
||||
MedusaContainer,
|
||||
ModuleExports,
|
||||
ModuleLoaderFunction,
|
||||
ModuleProvider,
|
||||
ModuleProviderExports,
|
||||
ModuleProviderLoaderFunction,
|
||||
ModuleResolution,
|
||||
} from "@medusajs/types"
|
||||
import {
|
||||
@@ -15,6 +18,8 @@ import {
|
||||
defineJoinerConfig,
|
||||
DmlEntity,
|
||||
dynamicImport,
|
||||
isString,
|
||||
MedusaModuleProviderType,
|
||||
MedusaModuleType,
|
||||
ModulesSdkUtils,
|
||||
toMikroOrmEntities,
|
||||
@@ -29,7 +34,7 @@ type ModuleResource = {
|
||||
services: Function[]
|
||||
models: Function[]
|
||||
repositories: Function[]
|
||||
loaders: ModuleLoaderFunction[]
|
||||
loaders: ModuleLoaderFunction[] | ModuleProviderLoaderFunction[]
|
||||
moduleService: Constructor<any>
|
||||
normalizedPath: string
|
||||
}
|
||||
@@ -39,22 +44,36 @@ type MigrationFunction = (
|
||||
moduleDeclaration?: InternalModuleDeclaration
|
||||
) => Promise<void>
|
||||
|
||||
type ResolvedModule = ModuleExports & {
|
||||
discoveryPath: string
|
||||
}
|
||||
|
||||
type ResolvedModuleProvider = ModuleProviderExports & {
|
||||
discoveryPath: string
|
||||
}
|
||||
|
||||
export const moduleProviderRegistrationKeyPrefix = "__providers__"
|
||||
|
||||
/**
|
||||
* Return the key used to register a module provider in the container
|
||||
* @param {string} moduleKey
|
||||
* @return {string}
|
||||
*/
|
||||
export function getProviderRegistrationKey(moduleKey: string): string {
|
||||
return moduleProviderRegistrationKeyPrefix + moduleKey
|
||||
}
|
||||
|
||||
export async function resolveModuleExports({
|
||||
resolution,
|
||||
}: {
|
||||
resolution: ModuleResolution
|
||||
}): Promise<
|
||||
| (ModuleExports & {
|
||||
discoveryPath: string
|
||||
})
|
||||
| { error: any }
|
||||
> {
|
||||
}): Promise<ResolvedModule | ResolvedModuleProvider | { error: any }> {
|
||||
let resolvedModuleExports: ModuleExports
|
||||
try {
|
||||
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
|
||||
resolvedModuleExports = resolution.moduleExports
|
||||
resolvedModuleExports = resolution.moduleExports as ModuleExports
|
||||
resolvedModuleExports.discoveryPath = resolution.resolutionPath as string
|
||||
} else {
|
||||
const module = await dynamicImport(resolution.resolutionPath as string)
|
||||
@@ -62,10 +81,12 @@ export async function resolveModuleExports({
|
||||
if ("discoveryPath" in module) {
|
||||
const reExportedLoadedModule = await dynamicImport(module.discoveryPath)
|
||||
const discoveryPath = module.discoveryPath
|
||||
resolvedModuleExports = reExportedLoadedModule.default
|
||||
resolvedModuleExports =
|
||||
reExportedLoadedModule.default ?? reExportedLoadedModule
|
||||
resolvedModuleExports.discoveryPath = discoveryPath as string
|
||||
} else {
|
||||
resolvedModuleExports = (module as { default: ModuleExports }).default
|
||||
resolvedModuleExports =
|
||||
(module as { default: ModuleExports }).default ?? module
|
||||
resolvedModuleExports.discoveryPath =
|
||||
resolution.resolutionPath as string
|
||||
}
|
||||
@@ -90,13 +111,79 @@ export async function resolveModuleExports({
|
||||
}
|
||||
}
|
||||
|
||||
export async function loadInternalModule(
|
||||
container: MedusaContainer,
|
||||
resolution: ModuleResolution,
|
||||
logger: Logger,
|
||||
migrationOnly?: boolean,
|
||||
loaderOnly?: boolean
|
||||
async function loadInternalProvider(
|
||||
args: {
|
||||
container: MedusaContainer
|
||||
resolution: ModuleResolution
|
||||
logger: Logger
|
||||
migrationOnly?: boolean
|
||||
loaderOnly?: boolean
|
||||
},
|
||||
providers: ModuleProvider[]
|
||||
): Promise<{ error?: Error } | void> {
|
||||
const { container, resolution, logger, migrationOnly } = args
|
||||
|
||||
const errors: { error?: Error }[] = []
|
||||
for (const provider of providers) {
|
||||
const providerRes = provider.resolve as ModuleProviderExports
|
||||
|
||||
const canLoadProvider =
|
||||
providerRes && (isString(providerRes) || !providerRes?.services)
|
||||
|
||||
if (!canLoadProvider) {
|
||||
continue
|
||||
}
|
||||
|
||||
const res = await loadInternalModule({
|
||||
container,
|
||||
resolution: {
|
||||
...resolution,
|
||||
moduleExports: !isString(providerRes) ? providerRes : undefined,
|
||||
definition: {
|
||||
...resolution.definition,
|
||||
key: provider.id,
|
||||
},
|
||||
resolutionPath: isString(provider.resolve) ? provider.resolve : false,
|
||||
},
|
||||
logger,
|
||||
migrationOnly,
|
||||
loadingProviders: true,
|
||||
})
|
||||
|
||||
if (res) {
|
||||
errors.push(res)
|
||||
}
|
||||
}
|
||||
|
||||
const errorMessages = errors.map((e) => e.error?.message).join("\n")
|
||||
return errors.length
|
||||
? {
|
||||
error: {
|
||||
name: "ModuleProviderError",
|
||||
message: `Errors while loading module providers for module ${resolution.definition.key}:\n${errorMessages}`,
|
||||
stack: errors.map((e) => e.error?.stack).join("\n"),
|
||||
},
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
|
||||
export async function loadInternalModule(args: {
|
||||
container: MedusaContainer
|
||||
resolution: ModuleResolution
|
||||
logger: Logger
|
||||
migrationOnly?: boolean
|
||||
loaderOnly?: boolean
|
||||
loadingProviders?: boolean
|
||||
}): Promise<{ error?: Error } | void> {
|
||||
const {
|
||||
container,
|
||||
resolution,
|
||||
logger,
|
||||
migrationOnly,
|
||||
loaderOnly,
|
||||
loadingProviders,
|
||||
} = args
|
||||
|
||||
const keyName = !loaderOnly
|
||||
? resolution.definition.key
|
||||
: resolution.definition.key + "__loaderOnly"
|
||||
@@ -121,7 +208,12 @@ export async function loadInternalModule(
|
||||
})
|
||||
}
|
||||
|
||||
if (!loadedModule?.service && !moduleResources.moduleService) {
|
||||
const loadedModule_ = loadedModule as ModuleExports
|
||||
if (
|
||||
!loadingProviders &&
|
||||
!loadedModule_?.service &&
|
||||
!moduleResources.moduleService
|
||||
) {
|
||||
container.register({
|
||||
[keyName]: asValue(undefined),
|
||||
})
|
||||
@@ -133,20 +225,6 @@ export async function loadInternalModule(
|
||||
}
|
||||
}
|
||||
|
||||
if (migrationOnly) {
|
||||
const moduleService_ = moduleResources.moduleService ?? loadedModule.service
|
||||
|
||||
// Partially loaded module, only register the service __joinerConfig function to be able to resolve it later
|
||||
const moduleService = {
|
||||
__joinerConfig: moduleService_.prototype.__joinerConfig,
|
||||
}
|
||||
|
||||
container.register({
|
||||
[keyName]: asValue(moduleService),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
const localContainer = createMedusaContainer()
|
||||
|
||||
const dependencies = resolution?.dependencies ?? []
|
||||
@@ -177,6 +255,44 @@ export async function loadInternalModule(
|
||||
)
|
||||
}
|
||||
|
||||
// if module has providers, load them
|
||||
let providerOptions: any = undefined
|
||||
if (!loadingProviders) {
|
||||
const providers = (resolution?.options?.providers as any[]) ?? []
|
||||
|
||||
const res = await loadInternalProvider(
|
||||
{
|
||||
...args,
|
||||
container: localContainer,
|
||||
},
|
||||
providers
|
||||
)
|
||||
|
||||
if (res?.error) {
|
||||
return res
|
||||
}
|
||||
} else {
|
||||
providerOptions = (resolution?.options?.providers as any[]).find(
|
||||
(p) => p.id === resolution.definition.key
|
||||
)?.options
|
||||
}
|
||||
|
||||
if (migrationOnly && !loadingProviders) {
|
||||
const moduleService_ =
|
||||
moduleResources.moduleService ?? loadedModule_.service
|
||||
|
||||
// Partially loaded module, only register the service __joinerConfig function to be able to resolve it later
|
||||
const moduleService = {
|
||||
__joinerConfig: moduleService_.prototype.__joinerConfig,
|
||||
}
|
||||
|
||||
container.register({
|
||||
[keyName]: asValue(moduleService),
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
const loaders = moduleResources.loaders ?? loadedModule?.loaders ?? []
|
||||
const error = await runLoaders(loaders, {
|
||||
container,
|
||||
@@ -185,24 +301,56 @@ export async function loadInternalModule(
|
||||
resolution,
|
||||
loaderOnly,
|
||||
keyName,
|
||||
providerOptions,
|
||||
})
|
||||
|
||||
if (error) {
|
||||
return error
|
||||
}
|
||||
|
||||
const moduleService = moduleResources.moduleService ?? loadedModule.service
|
||||
if (loadingProviders) {
|
||||
const loadedProvider_ = loadedModule as ModuleProviderExports
|
||||
|
||||
container.register({
|
||||
[keyName]: asFunction((cradle) => {
|
||||
;(moduleService as any).__type = MedusaModuleType
|
||||
return new moduleService(
|
||||
localContainer.cradle,
|
||||
resolution.options,
|
||||
resolution.moduleDeclaration
|
||||
let moduleProviderServices = moduleResources.moduleService
|
||||
? [moduleResources.moduleService]
|
||||
: loadedProvider_.services ?? loadedProvider_
|
||||
|
||||
if (!moduleProviderServices) {
|
||||
return
|
||||
}
|
||||
|
||||
for (const moduleProviderService of moduleProviderServices) {
|
||||
const modProvider_ = moduleProviderService as any
|
||||
|
||||
modProvider_.identifier ??= keyName
|
||||
modProvider_.__type = MedusaModuleProviderType
|
||||
const registrationKey = getProviderRegistrationKey(
|
||||
modProvider_.identifier
|
||||
)
|
||||
}).singleton(),
|
||||
})
|
||||
container.register({
|
||||
[registrationKey]: asFunction((cradle) => {
|
||||
;(moduleProviderService as any).__type = MedusaModuleType
|
||||
return new moduleProviderService(
|
||||
localContainer.cradle,
|
||||
resolution.options,
|
||||
resolution.moduleDeclaration
|
||||
)
|
||||
}).singleton(),
|
||||
})
|
||||
}
|
||||
} else {
|
||||
const moduleService = moduleResources.moduleService ?? loadedModule_.service
|
||||
container.register({
|
||||
[keyName]: asFunction((cradle) => {
|
||||
;(moduleService as any).__type = MedusaModuleType
|
||||
return new moduleService(
|
||||
localContainer.cradle,
|
||||
resolution.options,
|
||||
resolution.moduleDeclaration
|
||||
)
|
||||
}).singleton(),
|
||||
})
|
||||
}
|
||||
|
||||
if (loaderOnly) {
|
||||
// The expectation is only to run the loader as standalone, so we do not need to register the service and we need to cleanup all services
|
||||
@@ -220,46 +368,114 @@ export async function loadModuleMigrations(
|
||||
revertMigration?: MigrationFunction
|
||||
generateMigration?: MigrationFunction
|
||||
}> {
|
||||
const loadedModule = await resolveModuleExports({
|
||||
const mainLoadedModule = await resolveModuleExports({
|
||||
resolution: { ...resolution, moduleExports },
|
||||
})
|
||||
|
||||
if ("error" in loadedModule) {
|
||||
throw loadedModule.error
|
||||
}
|
||||
const loadedServices = [mainLoadedModule] as (
|
||||
| ResolvedModule
|
||||
| ResolvedModuleProvider
|
||||
)[]
|
||||
|
||||
try {
|
||||
let runMigrations = loadedModule.runMigrations
|
||||
let revertMigration = loadedModule.revertMigration
|
||||
let generateMigration = loadedModule.generateMigration
|
||||
if (Array.isArray(resolution?.options?.providers)) {
|
||||
for (const provider of (resolution.options as any).providers) {
|
||||
const providerRes = provider.resolve as ModuleProviderExports
|
||||
|
||||
if (!runMigrations || !revertMigration) {
|
||||
const moduleResources = await loadResources({
|
||||
moduleResolution: resolution,
|
||||
discoveryPath: loadedModule.discoveryPath,
|
||||
loadedModuleLoaders: loadedModule?.loaders,
|
||||
})
|
||||
const canLoadProvider =
|
||||
providerRes && (isString(providerRes) || !providerRes?.services)
|
||||
|
||||
const migrationScriptOptions = {
|
||||
moduleName: resolution.definition.key,
|
||||
models: moduleResources.models,
|
||||
pathToMigrations: join(moduleResources.normalizedPath, "migrations"),
|
||||
if (!canLoadProvider) {
|
||||
continue
|
||||
}
|
||||
|
||||
runMigrations ??= ModulesSdkUtils.buildMigrationScript(
|
||||
migrationScriptOptions
|
||||
)
|
||||
const loadedProvider = await resolveModuleExports({
|
||||
resolution: {
|
||||
...resolution,
|
||||
moduleExports: !isString(providerRes) ? providerRes : undefined,
|
||||
definition: {
|
||||
...resolution.definition,
|
||||
key: provider.id,
|
||||
},
|
||||
resolutionPath: isString(provider.resolve) ? provider.resolve : false,
|
||||
},
|
||||
})
|
||||
loadedServices.push(loadedProvider as ResolvedModuleProvider)
|
||||
}
|
||||
}
|
||||
|
||||
revertMigration ??= ModulesSdkUtils.buildRevertMigrationScript(
|
||||
migrationScriptOptions
|
||||
)
|
||||
if ("error" in mainLoadedModule) {
|
||||
throw mainLoadedModule.error
|
||||
}
|
||||
|
||||
generateMigration ??= ModulesSdkUtils.buildGenerateMigrationScript(
|
||||
migrationScriptOptions
|
||||
)
|
||||
const runMigrationsFn: ((...args) => Promise<any>)[] = []
|
||||
const revertMigrationFn: ((...args) => Promise<any>)[] = []
|
||||
const generateMigrationFn: ((...args) => Promise<any>)[] = []
|
||||
|
||||
try {
|
||||
const migrationScripts: any[] = []
|
||||
for (const loadedModule of loadedServices) {
|
||||
let runMigrationsCustom = loadedModule.runMigrations
|
||||
let revertMigrationCustom = loadedModule.revertMigration
|
||||
let generateMigrationCustom = loadedModule.generateMigration
|
||||
|
||||
runMigrationsCustom && runMigrationsFn.push(runMigrationsCustom)
|
||||
revertMigrationCustom && revertMigrationFn.push(revertMigrationCustom)
|
||||
generateMigrationCustom &&
|
||||
generateMigrationFn.push(generateMigrationCustom)
|
||||
|
||||
if (!runMigrationsCustom || !revertMigrationCustom) {
|
||||
const moduleResources = await loadResources({
|
||||
moduleResolution: resolution,
|
||||
discoveryPath: loadedModule.discoveryPath,
|
||||
loadedModuleLoaders: loadedModule?.loaders,
|
||||
})
|
||||
|
||||
migrationScripts.push({
|
||||
moduleName: resolution.definition.key,
|
||||
models: moduleResources.models,
|
||||
pathToMigrations: join(moduleResources.normalizedPath, "migrations"),
|
||||
})
|
||||
}
|
||||
|
||||
for (const migrationScriptOptions of migrationScripts) {
|
||||
const migrationUp =
|
||||
runMigrationsCustom ??
|
||||
ModulesSdkUtils.buildMigrationScript(migrationScriptOptions)
|
||||
runMigrationsFn.push(migrationUp)
|
||||
|
||||
const migrationDown =
|
||||
revertMigrationCustom ??
|
||||
ModulesSdkUtils.buildRevertMigrationScript(migrationScriptOptions)
|
||||
revertMigrationFn.push(migrationDown)
|
||||
|
||||
const genMigration =
|
||||
generateMigrationCustom ??
|
||||
ModulesSdkUtils.buildGenerateMigrationScript(migrationScriptOptions)
|
||||
generateMigrationFn.push(genMigration)
|
||||
}
|
||||
}
|
||||
|
||||
return { runMigrations, revertMigration, generateMigration }
|
||||
const runMigrations = async (...args) => {
|
||||
for (const migration of runMigrationsFn.filter(Boolean)) {
|
||||
await migration.apply(migration, args)
|
||||
}
|
||||
}
|
||||
const revertMigration = async (...args) => {
|
||||
for (const migration of revertMigrationFn.filter(Boolean)) {
|
||||
await migration.apply(migration, args)
|
||||
}
|
||||
}
|
||||
const generateMigration = async (...args) => {
|
||||
for (const migration of generateMigrationFn.filter(Boolean)) {
|
||||
await migration.apply(migration, args)
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
runMigrations,
|
||||
revertMigration,
|
||||
generateMigration,
|
||||
}
|
||||
} catch {
|
||||
return {}
|
||||
}
|
||||
@@ -308,7 +524,7 @@ export async function loadResources({
|
||||
moduleResolution: ModuleResolution
|
||||
discoveryPath: string
|
||||
logger?: Logger
|
||||
loadedModuleLoaders?: ModuleLoaderFunction[]
|
||||
loadedModuleLoaders?: ModuleLoaderFunction[] | ModuleProviderLoaderFunction[]
|
||||
}): Promise<ModuleResource> {
|
||||
logger ??= console as unknown as Logger
|
||||
loadedModuleLoaders ??= []
|
||||
@@ -324,7 +540,8 @@ export async function loadResources({
|
||||
|
||||
const [moduleService, services, models, repositories] = await Promise.all([
|
||||
dynamicImport(modulePath).then((moduleExports) => {
|
||||
return moduleExports.default.service
|
||||
const mod = moduleExports.default ?? moduleExports
|
||||
return mod.service
|
||||
}),
|
||||
importAllFromDir(resolve(normalizedPath, "services")).catch(
|
||||
defaultOnFail
|
||||
@@ -365,11 +582,14 @@ export async function loadResources({
|
||||
migrationPath: normalizedPath + "/migrations",
|
||||
})
|
||||
|
||||
generateJoinerConfigIfNecessary({
|
||||
moduleResolution,
|
||||
service: moduleService,
|
||||
models: potentialModels,
|
||||
})
|
||||
// if a module service is provided, we generate a joiner config
|
||||
if (moduleService) {
|
||||
generateJoinerConfigIfNecessary({
|
||||
moduleResolution,
|
||||
service: moduleService,
|
||||
models: potentialModels,
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
services: potentialServices,
|
||||
@@ -390,7 +610,15 @@ export async function loadResources({
|
||||
|
||||
async function runLoaders(
|
||||
loaders: Function[] = [],
|
||||
{ localContainer, container, logger, resolution, loaderOnly, keyName }
|
||||
{
|
||||
localContainer,
|
||||
container,
|
||||
logger,
|
||||
resolution,
|
||||
loaderOnly,
|
||||
keyName,
|
||||
providerOptions,
|
||||
}
|
||||
): Promise<void | { error: Error }> {
|
||||
try {
|
||||
for (const loader of loaders) {
|
||||
@@ -398,8 +626,9 @@ async function runLoaders(
|
||||
{
|
||||
container: localContainer,
|
||||
logger,
|
||||
options: resolution.options,
|
||||
options: providerOptions ?? resolution.options,
|
||||
dataLoaderOnly: loaderOnly,
|
||||
moduleOptions: providerOptions ? resolution.options : undefined,
|
||||
},
|
||||
resolution.moduleDeclaration as InternalModuleDeclaration
|
||||
)
|
||||
@@ -418,14 +647,17 @@ async function runLoaders(
|
||||
}
|
||||
|
||||
function prepareLoaders({
|
||||
loadedModuleLoaders = [] as ModuleLoaderFunction[],
|
||||
loadedModuleLoaders = [] as
|
||||
| ModuleLoaderFunction[]
|
||||
| ModuleProviderLoaderFunction[],
|
||||
models,
|
||||
repositories,
|
||||
services,
|
||||
moduleResolution,
|
||||
migrationPath,
|
||||
}) {
|
||||
const finalLoaders: ModuleLoaderFunction[] = []
|
||||
const finalLoaders: (ModuleLoaderFunction | ModuleProviderLoaderFunction)[] =
|
||||
[]
|
||||
|
||||
const toObjectReducer = (acc, curr) => {
|
||||
acc[curr.name] = curr
|
||||
|
||||
@@ -510,7 +510,7 @@ async function MedusaApp_({
|
||||
modulePath: moduleResolution.resolutionPath as string,
|
||||
container: sharedContainer,
|
||||
options: moduleResolution.options,
|
||||
moduleExports: moduleResolution.moduleExports,
|
||||
moduleExports: moduleResolution.moduleExports as ModuleExports,
|
||||
}
|
||||
|
||||
if (action === "revert") {
|
||||
|
||||
Reference in New Issue
Block a user