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 { ...@@ -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 提供者构造函数参数列表中使用下列装饰器即可进行注入操作。 在 Nest 提供者构造函数参数列表中使用下列装饰器即可进行注入操作。
* `@InjectContext()` 注入全体上下文。等价于 `ctx.any()` * `@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 上下文
您将需要使用标识符 `KOISHI_CONTEXT` 进行注入操作,如下例。 您将需要使用函数 `getContextProvideToken()` 进行注入操作,如下例。
```ts ```ts
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
import { KoishiModule, KOISHI_CONTEXT } from 'koishi-nestjs'; import { KoishiModule, getContextProvideToken } from 'koishi-nestjs';
import { AppService } from './app.service'; import { AppService } from './app.service';
import { Context } from 'koishi'; import { Context } from 'koishi';
...@@ -157,7 +180,7 @@ import { Context } from 'koishi'; ...@@ -157,7 +180,7 @@ import { Context } from 'koishi';
providers: [ providers: [
{ {
provide: AppService, provide: AppService,
inject: [KOISHI_CONTEXT], inject: [getContextProvideToken()],
useFactory: (ctx: Context) => new AppService(ctx) useFactory: (ctx: Context) => new AppService(ctx)
} }
] ]
...@@ -165,7 +188,13 @@ import { Context } from 'koishi'; ...@@ -165,7 +188,13 @@ import { Context } from 'koishi';
export class AppModule {} 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 指令 ## 使用装饰器注册 Koishi 指令
......
export * from './src/koishi.constants';
export * from './src/koishi.decorators'; export * from './src/koishi.decorators';
export * from './src/koishi.interfaces'; export * from './src/koishi.interfaces';
export * from './src/koishi.service'; export * from './src/koishi.service';
export * from './src/koishi.module'; export * from './src/koishi.module';
export * from './src/koishi-context.factory';
{ {
"name": "koishi-nestjs", "name": "koishi-nestjs",
"version": "1.0.35", "version": "1.0.36",
"description": "Koishi.js as Nest.js Module", "description": "Koishi.js as Nest.js Module",
"main": "dist/index.js", "main": "dist/index.js",
"typings": "dist/index.d.ts", "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 // Injections
export const KOISHI_MODULE_OPTIONS = 'KOISHI_MODULE_OPTIONS'; export const KOISHI_MODULE_OPTIONS = 'KOISHI_MODULE_OPTIONS';
export const KOISHI_CONTEXT = 'KOISHI_CONTEXT'; 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 // metadatas
export const KoishiOnContextScope = 'KoishiOnContextScope'; export const KoishiOnContextScope = 'KoishiOnContextScope';
......
import { CustomDecorator, Inject, SetMetadata } from '@nestjs/common'; import { CustomDecorator, Inject, SetMetadata } from '@nestjs/common';
import { import {
KOISHI_CONTEXT, KOISHI_CONTEXT,
KOISHI_CONTEXT_CHANNEL,
KOISHI_CONTEXT_GUILD,
KOISHI_CONTEXT_PRIVATE,
KoishiCommandDefinition, KoishiCommandDefinition,
KoishiDoRegister, KoishiDoRegister,
KoishiOnContextScope, KoishiOnContextScope,
...@@ -18,12 +15,29 @@ import { ...@@ -18,12 +15,29 @@ import {
Selection, Selection,
} from './koishi.interfaces'; } from './koishi.interfaces';
import { Argv, Command } from 'koishi'; import { Argv, Command } from 'koishi';
import {
ContextScopeTypes,
getContextProvideToken,
} from './koishi-context.factory';
// Injections // Injections
export const InjectContext = () => Inject(KOISHI_CONTEXT); export const InjectContext = () => Inject(KOISHI_CONTEXT);
export const InjectContextPrivate = () => Inject(KOISHI_CONTEXT_PRIVATE); export const InjectContextSpecific = (
export const InjectContextChannel = () => Inject(KOISHI_CONTEXT_CHANNEL); scopeType?: ContextScopeTypes,
export const InjectContextGuild = () => Inject(KOISHI_CONTEXT_GUILD); 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>( export const SetExtraMetadata = <K = string, V = any>(
metadataKey: K, metadataKey: K,
......
...@@ -11,44 +11,22 @@ import { ...@@ -11,44 +11,22 @@ import {
KoishiModuleOptionsFactory, KoishiModuleOptionsFactory,
} from './koishi.interfaces'; } from './koishi.interfaces';
import { KoishiService } from './koishi.service'; import { KoishiService } from './koishi.service';
import { import { KOISHI_CONTEXT, KOISHI_MODULE_OPTIONS } from './koishi.constants';
KOISHI_CONTEXT,
KOISHI_CONTEXT_CHANNEL,
KOISHI_CONTEXT_GUILD,
KOISHI_CONTEXT_PRIVATE,
KOISHI_MODULE_OPTIONS,
} from './koishi.constants';
import { KoishiMiddleware } from './koishi.middleware'; import { KoishiMiddleware } from './koishi.middleware';
import { createServer } from 'http'; import { createServer } from 'http';
import { AddressInfo } from 'net'; import { AddressInfo } from 'net';
import { KoishiLoggerService } from './koishi-logger.service'; import { KoishiLoggerService } from './koishi-logger.service';
import { KoishiMetascanService } from './koishi-metascan.service'; import { KoishiMetascanService } from './koishi-metascan.service';
import { DiscoveryModule } from '@nestjs/core'; 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, provide: KOISHI_CONTEXT,
inject: [KoishiService], inject: [KoishiService],
useFactory: (koishiApp: KoishiService) => koishiApp.any(), 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({ @Module({
imports: [DiscoveryModule], imports: [DiscoveryModule],
providers: [ providers: [
...@@ -77,18 +55,9 @@ const koishiContextProviderPrivate: Provider = { ...@@ -77,18 +55,9 @@ const koishiContextProviderPrivate: Provider = {
KoishiLoggerService, KoishiLoggerService,
KoishiMetascanService, KoishiMetascanService,
koishiContextProvider, koishiContextProvider,
koishiContextProviderChannel,
koishiContextProviderGuild,
koishiContextProviderPrivate,
KoishiMiddleware, KoishiMiddleware,
], ],
exports: [ exports: [KoishiService, koishiContextProvider],
KoishiService,
koishiContextProvider,
koishiContextProviderChannel,
koishiContextProviderGuild,
koishiContextProviderPrivate,
],
}) })
export class KoishiModule implements NestModule { export class KoishiModule implements NestModule {
configure(consumer: MiddlewareConsumer) { configure(consumer: MiddlewareConsumer) {
...@@ -98,7 +67,11 @@ export class KoishiModule implements NestModule { ...@@ -98,7 +67,11 @@ export class KoishiModule implements NestModule {
static register(options: KoishiModuleOptions): DynamicModule { static register(options: KoishiModuleOptions): DynamicModule {
return { return {
module: KoishiModule, module: KoishiModule,
providers: [{ provide: KOISHI_MODULE_OPTIONS, useValue: options }], providers: [
{ provide: KOISHI_MODULE_OPTIONS, useValue: options },
...contextsToProvide,
],
exports: contextsToProvide,
global: options.isGlobal, global: options.isGlobal,
}; };
} }
...@@ -109,8 +82,10 @@ export class KoishiModule implements NestModule { ...@@ -109,8 +82,10 @@ export class KoishiModule implements NestModule {
imports: options.imports, imports: options.imports,
providers: [ providers: [
...this.createAsyncProviders(options), ...this.createAsyncProviders(options),
...contextsToProvide,
...(options.extraProviders || []), ...(options.extraProviders || []),
], ],
exports: contextsToProvide,
global: options.isGlobal, 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