NestJS中使用nestjs-plugin-module实现插件系统

1. 安装依赖

npm install @brewww/nestjs-plugin-module

2. 定义插件接口

首先,我们需要定义一个插件接口,这个接口定义了插件需要实现的方法。

hello/plugin.interface.ts

export interface HelloServicePlugin {
  helloworld(): string;
  hello(name: string): string;
}

3. 定义模块和提供者

接下来,我们需要定义一个模块和一个提供者,这里提供者引用了上面的插件实例,并且调用插件实例中的方法。
另外提供者还提供了一个 setHelloServicePlugin() 方法,用来在后面动态设置插件实例。

hello/hello.service.ts

import { Injectable } from '@nestjs/common';
import { HelloServicePlugin } from './plugin.interface';

@Injectable({})
export class HelloService {
  private helloServicePlugin: HelloServicePlugin;

  public async setHelloServicePlugin(helloServicePlugin: HelloServicePlugin) {
    this.helloServicePlugin = helloServicePlugin;
  }

  helloworld(): string {
    return this.helloServicePlugin.helloworld();
  }
  hello(name: string): string {
    return this.helloServicePlugin.hello(name);
  }
}

hello.module.ts

import { Module } from '@nestjs/common';
import { HelloService } from './hello.service';

@Module({
  providers: [
    {
      provide: 'HelloService',
      useClass: HelloService,
    },
  ],
  exports: ['HelloService'],
})
export class HelloModule {}

4. 创建插件

4.1 首先创建 plugins/hello-plugin/src 目录,然后在目录下创建 hello.plugin.ts 文件,实现 HelloServicePlugin 接口,并实现其中的方法。
另外插件实现类还引用了上面模块中的提供者,并在其 load() 方法中调用提供者中的 setHelloServicePlugin() 方法,将插件实例设置到提供者中。

plugins/hello-plugin/src/hello.plugin.ts

import { Inject, Injectable, Logger } from '@nestjs/common';

import { BasePlugin } from '@brewww/nestjs-plugin-module';
import { HelloServicePlugin } from '../../../hello/plugin.interface';
import { HelloService } from '../../../hello/hello.service';
import { pluginModule } from '../package.json';

@Injectable()
export class MyHelloServicePlugin
  extends BasePlugin
  implements HelloServicePlugin
{
  private readonly logger = new Logger(MyHelloServicePlugin.name);

  @Inject('HelloService')
  private helloService: HelloService;
  constructor() {
    super(pluginModule);
  }

  public helloworld(): string {
    return 'Hello World';
  }
  public hello(name: string): string {
    return 'Hello ' + name;
  }

  async load(): Promise<void> {
    this.logger.debug(`MyHelloServicePlugin.load ...`);
    this.helloService.setHelloServicePlugin(this);
    return Promise.resolve();
  }
}
  • 这里注意一下,我们需要修改tsconfig.json,并添加以下配置项
"resolveJsonModule": true

4.2 在 plugins/hello-plugin/src 目录下创建 index.ts 文件,在其中引入 MyHelloServicePlugin 类,并导出它。

plugins/hello-plugin/src/index.ts

import { MyHelloServicePlugin } from './hello.plugin';
export { MyHelloServicePlugin };

4.3 在 plugins/hello-plugin 目录下创建 package.json 文件,在其中定义插件的名称和显示名称。

plugins/hello-plugin/package.json

{
  "pluginModule": {
    "name": "my-hello-plugin",
    "displayName": "My Hello Plugin"
  }
}

5. 配置插件模块

app.module.ts

import { Module, forwardRef } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { PluginModule } from '@brewww/nestjs-plugin-module';
import { HelloModule } from './hello/hello.module';
import * as path from 'path';

@Module({
  imports: [
    PluginModule.registerAsync({
      imports: [forwardRef(() => HelloModule)],
      directories: [path.resolve(__dirname, './plugins')],
    }),
    HelloModule,
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}
  • 这里使用PluginModule.registerAsync()方法注册插件模块,并传入HelloModule模块,这样HelloModule中的提供者就可以被插件模块中的插件使用。

6. 测试插件

作为测试,我们在controller中注入HelloService,并调用其中的方法,看是否能够正确输出结果。

app.controller.ts

import { Controller, Get, Inject } from '@nestjs/common';
import { AppService } from './app.service';
import { HelloService } from './hello/hello.service';

@Controller()
export class AppController {
  constructor(
    private readonly appService: AppService,
    @Inject('HelloService')
    private readonly helloService: HelloService,
  ) {}

  @Get()
  async getHello() {
    console.log(this.helloService.helloworld());
    console.log(this.helloService.hello('kongxx'));

    return this.appService.getHello();
  }
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容