feat(medusa): Validate module required properties (#3029)

This commit is contained in:
Carlos R. L. Rodrigues
2023-01-15 13:08:08 -03:00
committed by GitHub
parent 142c8aa70f
commit f6ec05f3f9
2 changed files with 112 additions and 4 deletions

View File

@@ -95,6 +95,10 @@ describe("modules loader", () => {
resources: MODULE_RESOURCE_TYPE.SHARED,
},
},
moduleDeclaration: {
scope: MODULE_SCOPE.INTERNAL,
resources: MODULE_RESOURCE_TYPE.SHARED,
},
},
}
@@ -123,6 +127,10 @@ describe("modules loader", () => {
resources: MODULE_RESOURCE_TYPE.SHARED,
},
},
moduleDeclaration: {
scope: MODULE_SCOPE.INTERNAL,
resources: MODULE_RESOURCE_TYPE.SHARED,
},
},
}
@@ -162,6 +170,10 @@ describe("modules loader", () => {
resources: MODULE_RESOURCE_TYPE.SHARED,
},
},
moduleDeclaration: {
scope: MODULE_SCOPE.INTERNAL,
resources: MODULE_RESOURCE_TYPE.SHARED,
},
},
}
@@ -194,6 +206,10 @@ describe("modules loader", () => {
resources: MODULE_RESOURCE_TYPE.SHARED,
},
},
moduleDeclaration: {
scope: MODULE_SCOPE.INTERNAL,
resources: MODULE_RESOURCE_TYPE.SHARED,
},
},
}
@@ -228,6 +244,10 @@ describe("modules loader", () => {
resources: MODULE_RESOURCE_TYPE.SHARED,
},
},
moduleDeclaration: {
scope: MODULE_SCOPE.INTERNAL,
resources: MODULE_RESOURCE_TYPE.SHARED,
},
},
}
@@ -242,4 +262,74 @@ describe("modules loader", () => {
)
}
})
it("throws error if no scope is defined to the module", async () => {
expect.assertions(1)
const moduleResolutions: Record<string, ModuleResolution> = {
testService: {
resolutionPath: "@modules/no-service",
definition: {
registrationName: "testService",
key: "testService",
defaultPackage: "testService",
label: "TestService",
isRequired: true,
defaultModuleDeclaration: {
scope: MODULE_SCOPE.INTERNAL,
resources: MODULE_RESOURCE_TYPE.SHARED,
},
},
// @ts-ignore
moduleDeclaration: {
resources: MODULE_RESOURCE_TYPE.SHARED,
},
},
}
const configModule = buildConfigModule({
moduleResolutions,
})
try {
await registerModules({ container, configModule, logger: Logger })
} catch (err) {
expect(err.message).toEqual(
"The module TestService has to define its scope (internal | external)"
)
}
})
it("throws error if resources is not set when scope is defined as internal", async () => {
expect.assertions(1)
const moduleResolutions: Record<string, ModuleResolution> = {
testService: {
resolutionPath: "@modules/no-service",
definition: {
registrationName: "testService",
key: "testService",
defaultPackage: "testService",
label: "TestService",
isRequired: true,
defaultModuleDeclaration: {
scope: MODULE_SCOPE.INTERNAL,
resources: MODULE_RESOURCE_TYPE.SHARED,
},
},
// @ts-ignore
moduleDeclaration: {
scope: MODULE_SCOPE.INTERNAL,
},
},
}
const configModule = buildConfigModule({
moduleResolutions,
})
try {
await registerModules({ container, configModule, logger: Logger })
} catch (err) {
expect(err.message).toEqual(
"The module TestService is missing its resources config"
)
}
})
})

View File

@@ -22,9 +22,27 @@ const registerModule = async (
configModule: ConfigModule,
logger: Logger
): Promise<{ error?: Error } | void> => {
const constainerName = resolution.definition.registrationName
const { scope, resources } = resolution.moduleDeclaration ?? {}
if (!scope || (scope === MODULE_SCOPE.INTERNAL && !resources)) {
let message = `The module ${resolution.definition.label} has to define its scope (internal | external)`
if (scope && !resources) {
message = `The module ${resolution.definition.label} is missing its resources config`
}
container.register({
[constainerName]: asValue(false),
})
return {
error: new Error(message),
}
}
if (!resolution.resolutionPath) {
container.register({
[resolution.definition.registrationName]: asValue(false),
[constainerName]: asValue(false),
})
return
@@ -48,8 +66,8 @@ const registerModule = async (
}
if (
resolution.moduleDeclaration?.scope === MODULE_SCOPE.INTERNAL &&
resolution.moduleDeclaration?.resources === MODULE_RESOURCE_TYPE.SHARED
scope === MODULE_SCOPE.INTERNAL &&
resources === MODULE_RESOURCE_TYPE.SHARED
) {
const moduleModels = loadedModule?.models || null
if (moduleModels) {
@@ -61,7 +79,7 @@ const registerModule = async (
// TODO: "cradle" should only contain dependent Modules and the EntityManager if module scope is shared
container.register({
[resolution.definition.registrationName]: asFunction((cradle) => {
[constainerName]: asFunction((cradle) => {
return new moduleService(
cradle,
resolution.options,