fix(server): deal with nested optional modules (#7101)

This commit is contained in:
forehalo
2024-05-29 08:12:59 +00:00
parent bffbb1ea9f
commit d853fc879d

View File

@@ -1,6 +1,11 @@
import { join } from 'node:path'; import { join } from 'node:path';
import { Logger, Module } from '@nestjs/common'; import {
DynamicModule,
ForwardReference,
Logger,
Module,
} from '@nestjs/common';
import { ScheduleModule } from '@nestjs/schedule'; import { ScheduleModule } from '@nestjs/schedule';
import { ServeStaticModule } from '@nestjs/serve-static'; import { ServeStaticModule } from '@nestjs/serve-static';
import { get } from 'lodash-es'; import { get } from 'lodash-es';
@@ -49,17 +54,20 @@ export const FunctionalityModules = [
HelpersModule, HelpersModule,
]; ];
export class AppModuleBuilder { function filterOptionalModule(
private readonly modules: AFFiNEModule[] = []; config: AFFiNEConfig,
constructor(private readonly config: AFFiNEConfig) {} module: AFFiNEModule | Promise<DynamicModule> | ForwardReference<any>
) {
// can't deal with promise or forward reference
if (module instanceof Promise || 'forwardRef' in module) {
return module;
}
use(...modules: AFFiNEModule[]): this { const requirements = getOptionalModuleMetadata(module, 'requires');
modules.forEach(m => {
const requirements = getOptionalModuleMetadata(m, 'requires');
// if condition not set or condition met, include the module // if condition not set or condition met, include the module
if (requirements?.length) { if (requirements?.length) {
const nonMetRequirements = requirements.filter(c => { const nonMetRequirements = requirements.filter(c => {
const value = get(this.config, c); const value = get(config, c);
return ( return (
value === undefined || value === undefined ||
value === null || value === null ||
@@ -68,26 +76,45 @@ export class AppModuleBuilder {
}); });
if (nonMetRequirements.length) { if (nonMetRequirements.length) {
const name = 'module' in m ? m.module.name : m.name; const name = 'module' in module ? module.module.name : module.name;
new Logger(name).warn( new Logger(name).warn(
`${name} is not enabled because of the required configuration is not satisfied.`, `${name} is not enabled because of the required configuration is not satisfied.`,
'Unsatisfied configuration:', 'Unsatisfied configuration:',
...nonMetRequirements.map(config => ` AFFiNE.${config}`) ...nonMetRequirements.map(config => ` AFFiNE.${config}`)
); );
return; return null;
} }
} }
const predicator = getOptionalModuleMetadata(m, 'if'); const predicator = getOptionalModuleMetadata(module, 'if');
if (predicator && !predicator(this.config)) { if (predicator && !predicator(config)) {
return; return null;
} }
const contribution = getOptionalModuleMetadata(m, 'contributesTo'); const contribution = getOptionalModuleMetadata(module, 'contributesTo');
if (contribution) { if (contribution) {
ADD_ENABLED_FEATURES(contribution); ADD_ENABLED_FEATURES(contribution);
} }
const subModules = getOptionalModuleMetadata(module, 'imports');
const filteredSubModules = subModules
?.map(subModule => filterOptionalModule(config, subModule))
.filter(Boolean);
Reflect.defineMetadata('imports', filteredSubModules, module);
return module;
}
export class AppModuleBuilder {
private readonly modules: AFFiNEModule[] = [];
constructor(private readonly config: AFFiNEConfig) {}
use(...modules: AFFiNEModule[]): this {
modules.forEach(m => {
const result = filterOptionalModule(this.config, m);
if (result) {
this.modules.push(m); this.modules.push(m);
}
}); });
return this; return this;