Commit c40530d4 authored by nanahira's avatar nanahira

improve context injection

parent 3eba77df
Pipeline #6173 passed with stages
in 44 seconds
......@@ -128,25 +128,48 @@ export class AppService implements OnModuleInit {
}
```
### 注入某一特定上下文
```ts
import { Injectable } from '@nestjs/common';
import { InjectContextGuild } from 'koishi-nestjs';
import { Context } from 'koishi';
@Injectable()
export class AppService implements OnModuleInit {
constructor(@InjectContextGuild('1111111111') private ctx: Context) {}
onModuleInit() {
this.ctx.on('message', (session) => {})
}
}
```
### 装饰器定义
在 Nest 提供者构造函数参数列表中使用下列装饰器即可进行注入操作。
* `@InjectContext()` 注入全体上下文。等价于 `ctx.any()`
* `@InjectContextPrivate()` 注入私聊上下文。等价于 `ctx.private()`
* `@InjectContextPrivate(...values[]: string)` 注入私聊上下文。等价于 `ctx.private(...values)`
* `@InjectContextChannel(...values[]: string)` 注入频道上下文。等价于 `ctx.channel(...values)`
* `@InjectContextChannel()` 注入频道上下文。等价于 `ctx.channel()`
* `@InjectContextGuild(...values[]: string)` 注入群组上下文。等价于 `ctx.guild(...values)`
* `@InjectContextGuild()` 注入群组上下文。等价于 `ctx.guild()`
* `@InjectContextSelf(...values[]: string)` 注入群组上下文。等价于 `ctx.self(...values)`
* `@InjectContextUser(...values[]: string)` 注入群组上下文。等价于 `ctx.user(...values)`
* `@InjectContextPlatform(...values[]: string)` 注入平台上下文。等价于 `ctx.platform(...values)`
### 在自定义提供者注入 Koishi 上下文
您将需要使用标识符 `KOISHI_CONTEXT` 进行注入操作,如下例。
您将需要使用函数 `getContextProvideToken()` 进行注入操作,如下例。
```ts
import { Module } from '@nestjs/common';
import { KoishiModule, KOISHI_CONTEXT } from 'koishi-nestjs';
import { KoishiModule, getContextProvideToken } from 'koishi-nestjs';
import { AppService } from './app.service';
import { Context } from 'koishi';
......@@ -157,7 +180,7 @@ import { Context } from 'koishi';
providers: [
{
provide: AppService,
inject: [KOISHI_CONTEXT],
inject: [getContextProvideToken()],
useFactory: (ctx: Context) => new AppService(ctx)
}
]
......@@ -165,7 +188,13 @@ import { Context } from 'koishi';
export class AppModule {}
```
您也可以使用 `KOISHI_CONTEXT_PRIVATE` `KOISHI_CONTEXT_CHANNEL` `KOISHI_CONTEXT_GUILD` 注入不同作用域的上下文。
#### 函数定义
`getContextProvideToken(scopeType?: ContextScopeTypes, values: string[] = [])`
* `scopeType` 作用域类型,可以是 `private` `channel` `guild` `self` `user` `platform` 之一。留空表示全局上下文。
* `values` 作用域值。例如 `getContextProvideToken('platform', ['onebot'])` 等价于 `ctx.platform('onebot')` .
## 使用装饰器注册 Koishi 指令
......
export * from './src/koishi.constants';
export * from './src/koishi.decorators';
export * from './src/koishi.interfaces';
export * from './src/koishi.service';
export * from './src/koishi.module';
export * from './src/koishi-context.factory';
{
"name": "koishi-nestjs",
"version": "1.0.35",
"version": "1.0.36",
"description": "Koishi.js as Nest.js Module",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
......
import { Context } from 'koishi';
import { Provider, Scope } from '@nestjs/common';
import { KOISHI_CONTEXT } from './koishi.constants';
export type ContextScopeTypes =
| 'guild'
| 'channel'
| 'platform'
| 'user'
| 'self'
| 'private';
function constructProvideToken(
scopeType: ContextScopeTypes,
values: string[] = [],
) {
return `KOISHI_CONTEXT_${scopeType}_${values.join('_')}`;
}
function createContextProvider(
scopeType: ContextScopeTypes,
values: string[] = [],
) {
return {
provide: constructProvideToken(scopeType, values),
inject: [KOISHI_CONTEXT],
// scope: Scope.TRANSIENT,
useFactory: (ctx: Context) => ctx[scopeType](...values),
};
}
export const contextsToProvide: Provider<Context>[] = [];
const contextTokensSet = new Set<string>();
export function getContextProvideToken(
scopeType?: ContextScopeTypes,
values: string[] = [],
) {
if (!scopeType) {
return KOISHI_CONTEXT;
}
const token = constructProvideToken(scopeType, values);
if (!contextTokensSet.has(token)) {
contextTokensSet.add(token);
contextsToProvide.push(createContextProvider(scopeType, values));
}
return token;
}
// Injections
export const KOISHI_MODULE_OPTIONS = 'KOISHI_MODULE_OPTIONS';
export const KOISHI_CONTEXT = 'KOISHI_CONTEXT';
export const KOISHI_CONTEXT_PRIVATE = 'KOISHI_CONTEXT_PRIVATE';
export const KOISHI_CONTEXT_CHANNEL = 'KOISHI_CONTEXT_CHANNEL';
export const KOISHI_CONTEXT_GUILD = 'KOISHI_CONTEXT_GUILD';
// metadatas
export const KoishiOnContextScope = 'KoishiOnContextScope';
......
import { CustomDecorator, Inject, SetMetadata } from '@nestjs/common';
import {
KOISHI_CONTEXT,
KOISHI_CONTEXT_CHANNEL,
KOISHI_CONTEXT_GUILD,
KOISHI_CONTEXT_PRIVATE,
KoishiCommandDefinition,
KoishiDoRegister,
KoishiOnContextScope,
......@@ -18,12 +15,29 @@ import {
Selection,
} from './koishi.interfaces';
import { Argv, Command } from 'koishi';
import {
ContextScopeTypes,
getContextProvideToken,
} from './koishi-context.factory';
// Injections
export const InjectContext = () => Inject(KOISHI_CONTEXT);
export const InjectContextPrivate = () => Inject(KOISHI_CONTEXT_PRIVATE);
export const InjectContextChannel = () => Inject(KOISHI_CONTEXT_CHANNEL);
export const InjectContextGuild = () => Inject(KOISHI_CONTEXT_GUILD);
export const InjectContextSpecific = (
scopeType?: ContextScopeTypes,
values: string[] = [],
) => Inject(getContextProvideToken(scopeType, values));
export const InjectContextPrivate = (...values: string[]) =>
InjectContextSpecific('private', values);
export const InjectContextChannel = (...values: string[]) =>
InjectContextSpecific('channel', values);
export const InjectContextGuild = (...values: string[]) =>
InjectContextSpecific('guild', values);
export const InjectContextSelf = (...values: string[]) =>
InjectContextSpecific('self', values);
export const InjectContextPlatform = (...values: string[]) =>
InjectContextSpecific('platform', values);
export const InjectContextUser = (...values: string[]) =>
InjectContextSpecific('user', values);
export const SetExtraMetadata = <K = string, V = any>(
metadataKey: K,
......
......@@ -11,44 +11,22 @@ import {
KoishiModuleOptionsFactory,
} from './koishi.interfaces';
import { KoishiService } from './koishi.service';
import {
KOISHI_CONTEXT,
KOISHI_CONTEXT_CHANNEL,
KOISHI_CONTEXT_GUILD,
KOISHI_CONTEXT_PRIVATE,
KOISHI_MODULE_OPTIONS,
} from './koishi.constants';
import { KOISHI_CONTEXT, KOISHI_MODULE_OPTIONS } from './koishi.constants';
import { KoishiMiddleware } from './koishi.middleware';
import { createServer } from 'http';
import { AddressInfo } from 'net';
import { KoishiLoggerService } from './koishi-logger.service';
import { KoishiMetascanService } from './koishi-metascan.service';
import { DiscoveryModule } from '@nestjs/core';
import { Context } from 'koishi';
import { contextsToProvide } from './koishi-context.factory';
const koishiContextProvider: Provider = {
const koishiContextProvider: Provider<Context> = {
provide: KOISHI_CONTEXT,
inject: [KoishiService],
useFactory: (koishiApp: KoishiService) => koishiApp.any(),
};
const koishiContextProviderChannel: Provider = {
provide: KOISHI_CONTEXT_CHANNEL,
inject: [KoishiService],
useFactory: (koishiApp: KoishiService) => koishiApp.channel(),
};
const koishiContextProviderGuild: Provider = {
provide: KOISHI_CONTEXT_GUILD,
inject: [KoishiService],
useFactory: (koishiApp: KoishiService) => koishiApp.guild(),
};
const koishiContextProviderPrivate: Provider = {
provide: KOISHI_CONTEXT_PRIVATE,
inject: [KoishiService],
useFactory: (koishiApp: KoishiService) => koishiApp.private(),
};
@Module({
imports: [DiscoveryModule],
providers: [
......@@ -77,18 +55,9 @@ const koishiContextProviderPrivate: Provider = {
KoishiLoggerService,
KoishiMetascanService,
koishiContextProvider,
koishiContextProviderChannel,
koishiContextProviderGuild,
koishiContextProviderPrivate,
KoishiMiddleware,
],
exports: [
KoishiService,
koishiContextProvider,
koishiContextProviderChannel,
koishiContextProviderGuild,
koishiContextProviderPrivate,
],
exports: [KoishiService, koishiContextProvider],
})
export class KoishiModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
......@@ -98,7 +67,11 @@ export class KoishiModule implements NestModule {
static register(options: KoishiModuleOptions): DynamicModule {
return {
module: KoishiModule,
providers: [{ provide: KOISHI_MODULE_OPTIONS, useValue: options }],
providers: [
{ provide: KOISHI_MODULE_OPTIONS, useValue: options },
...contextsToProvide,
],
exports: contextsToProvide,
global: options.isGlobal,
};
}
......@@ -109,8 +82,10 @@ export class KoishiModule implements NestModule {
imports: options.imports,
providers: [
...this.createAsyncProviders(options),
...contextsToProvide,
...(options.extraProviders || []),
],
exports: contextsToProvide,
global: options.isGlobal,
};
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment