add config module
This commit is contained in:
parent
b2189a8c5f
commit
88ba3f5a16
@ -1,8 +1,11 @@
|
|||||||
import { DynamicModule, Module } from '@nestjs/common';
|
import { DynamicModule, Module } from '@nestjs/common';
|
||||||
|
|
||||||
|
import { Configure } from '../config/configure';
|
||||||
|
|
||||||
@Module({})
|
@Module({})
|
||||||
export class CoreModule {
|
export class CoreModule {
|
||||||
static forRoot(): DynamicModule {
|
static async forRoot(configure: Configure): Promise<DynamicModule> {
|
||||||
|
await configure.store('app.name');
|
||||||
return {
|
return {
|
||||||
module: CoreModule,
|
module: CoreModule,
|
||||||
global: true,
|
global: true,
|
||||||
|
92
src/modules/core/helpers/app.ts
Normal file
92
src/modules/core/helpers/app.ts
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
import { BadGatewayException, Global, Module, ModuleMetadata, Type } from '@nestjs/common';
|
||||||
|
|
||||||
|
import { APP_FILTER, APP_INTERCEPTOR, APP_PIPE } from '@nestjs/core';
|
||||||
|
import { useContainer } from 'class-validator';
|
||||||
|
|
||||||
|
import { omit } from 'lodash';
|
||||||
|
|
||||||
|
import { ConfigModule } from '@/modules/config/config.module';
|
||||||
|
import { Configure } from '@/modules/config/configure';
|
||||||
|
|
||||||
|
import { DEFAULT_VALIDATION_CONFIG } from '@/modules/content/constants';
|
||||||
|
|
||||||
|
import { CoreModule } from '../core.module';
|
||||||
|
import { AppFilter } from '../providers/app.filter';
|
||||||
|
import { AppInterceptor } from '../providers/app.interceptor';
|
||||||
|
import { AppPipe } from '../providers/app.pipe';
|
||||||
|
import { App, CreateOptions } from '../types';
|
||||||
|
|
||||||
|
import { CreateModule } from './utils';
|
||||||
|
|
||||||
|
export const app: App = { configure: new Configure() };
|
||||||
|
|
||||||
|
export const createApp = (options: CreateOptions) => async (): Promise<App> => {
|
||||||
|
const { config, builder } = options;
|
||||||
|
|
||||||
|
await app.configure.initialize(config.factories, config.storage);
|
||||||
|
|
||||||
|
if (!app.configure.has('app')) {
|
||||||
|
throw new BadGatewayException('App config not exists');
|
||||||
|
}
|
||||||
|
|
||||||
|
const BootModule = await createBootModule(app.configure, options);
|
||||||
|
|
||||||
|
app.container = await builder({ configure: app.configure, BootModule });
|
||||||
|
|
||||||
|
if (app.configure.has('app.prefix')) {
|
||||||
|
app.container.setGlobalPrefix(await app.configure.get<string>('app.prefix'));
|
||||||
|
}
|
||||||
|
useContainer(app.container.select(BootModule), { fallbackOnErrors: true });
|
||||||
|
return app;
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function createBootModule(
|
||||||
|
configure: Configure,
|
||||||
|
options: Pick<CreateOptions, 'globals' | 'providers' | 'modules'>,
|
||||||
|
): Promise<Type<any>> {
|
||||||
|
const { globals = {}, providers = [] } = options;
|
||||||
|
const modules = await options.modules(configure);
|
||||||
|
const imports: ModuleMetadata['imports'] = (
|
||||||
|
await Promise.all([
|
||||||
|
...modules,
|
||||||
|
ConfigModule.forRoot(configure),
|
||||||
|
await CoreModule.forRoot(configure),
|
||||||
|
])
|
||||||
|
).map((item) => {
|
||||||
|
if ('module' in item) {
|
||||||
|
const meta = omit(item, ['module', 'global']);
|
||||||
|
Module(meta)(item.module);
|
||||||
|
if (item.global) {
|
||||||
|
Global()(item.module);
|
||||||
|
}
|
||||||
|
return item.module;
|
||||||
|
}
|
||||||
|
return item;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (globals.pipe !== null) {
|
||||||
|
const pipe = globals.pipe
|
||||||
|
? globals.pipe(configure)
|
||||||
|
: new AppPipe(DEFAULT_VALIDATION_CONFIG);
|
||||||
|
providers.push({ provide: APP_PIPE, useValue: pipe });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (globals.intercepter !== null) {
|
||||||
|
providers.push({
|
||||||
|
provide: APP_INTERCEPTOR,
|
||||||
|
useClass: globals.intercepter ?? AppInterceptor,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (globals.filter !== null) {
|
||||||
|
providers.push({
|
||||||
|
provide: APP_FILTER,
|
||||||
|
useClass: AppFilter,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return CreateModule('BootModule', () => ({
|
||||||
|
imports,
|
||||||
|
providers,
|
||||||
|
}));
|
||||||
|
}
|
@ -1,3 +1,4 @@
|
|||||||
|
import { Module, ModuleMetadata, Type } from '@nestjs/common';
|
||||||
import deepmerge from 'deepmerge';
|
import deepmerge from 'deepmerge';
|
||||||
import { isNil } from 'lodash';
|
import { isNil } from 'lodash';
|
||||||
|
|
||||||
@ -39,3 +40,18 @@ export function isAsyncFunction<T, P extends Array<any>>(
|
|||||||
const AsyncFunction = (async () => {}).constructor;
|
const AsyncFunction = (async () => {}).constructor;
|
||||||
return callback instanceof AsyncFunction === true;
|
return callback instanceof AsyncFunction === true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function CreateModule(
|
||||||
|
target: string | Type<any>,
|
||||||
|
metaSetter: () => ModuleMetadata = () => ({}),
|
||||||
|
): Type<any> {
|
||||||
|
let ModuleClass: Type<any>;
|
||||||
|
if (typeof target === 'string') {
|
||||||
|
ModuleClass = class {};
|
||||||
|
Object.defineProperty(ModuleClass, 'name', { value: target });
|
||||||
|
} else {
|
||||||
|
ModuleClass = target;
|
||||||
|
}
|
||||||
|
Module(metaSetter())(ModuleClass);
|
||||||
|
return ModuleClass;
|
||||||
|
}
|
||||||
|
37
src/modules/core/types.ts
Normal file
37
src/modules/core/types.ts
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import { ModuleMetadata, PipeTransform, Type } from '@nestjs/common';
|
||||||
|
import { NestFastifyApplication } from '@nestjs/platform-fastify';
|
||||||
|
|
||||||
|
import { Configure } from '../config/configure';
|
||||||
|
import { ConfigStorageOption, ConfigureFactory } from '../config/types';
|
||||||
|
|
||||||
|
export type App = {
|
||||||
|
container?: NestFastifyApplication;
|
||||||
|
|
||||||
|
configure: Configure;
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface CreateOptions {
|
||||||
|
modules: (configure: Configure) => Promise<Required<ModuleMetadata['imports']>>;
|
||||||
|
|
||||||
|
builder: ContainerBuilder;
|
||||||
|
|
||||||
|
globals?: {
|
||||||
|
pipe?: (configure: Configure) => PipeTransform<any> | null;
|
||||||
|
|
||||||
|
intercepter?: Type<any> | null;
|
||||||
|
|
||||||
|
filter?: Type<any> | null;
|
||||||
|
};
|
||||||
|
|
||||||
|
providers?: ModuleMetadata['providers'];
|
||||||
|
|
||||||
|
config: {
|
||||||
|
factories: Record<string, ConfigureFactory<RecordAny>>;
|
||||||
|
|
||||||
|
storage: ConfigStorageOption;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ContainerBuilder {
|
||||||
|
(params: { configure: Configure; BootModule: Type<any> }): Promise<NestFastifyApplication>;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user