Commit 5a2257f6 authored by nanahira's avatar nanahira

restrict possible decorated plugins

parent 1413edf7
...@@ -12,6 +12,7 @@ import { ...@@ -12,6 +12,7 @@ import {
KoishiSystemInjectSymKeys, KoishiSystemInjectSymKeys,
ProvideOptions, ProvideOptions,
SystemInjectFun, SystemInjectFun,
TypedMethodDecorator,
} from './def'; } from './def';
import { TopLevelAction } from 'koishi-decorators'; import { TopLevelAction } from 'koishi-decorators';
import { ModelClassType, ModelRegistrar } from 'minato-decorators'; import { ModelClassType, ModelRegistrar } from 'minato-decorators';
...@@ -126,11 +127,11 @@ export const PluginName = (name: string) => ...@@ -126,11 +127,11 @@ export const PluginName = (name: string) =>
export const If = <T>( export const If = <T>(
func: Condition<boolean, T, [Record<string, any>]>, func: Condition<boolean, T, [Record<string, any>]>,
): MethodDecorator => Metadata.append('KoishiIf', func); ): TypedMethodDecorator<T> => Metadata.append('KoishiIf', func);
export const For = <T>( export const For = <T>(
func: Condition<Iterable<Record<string, any>>, T, [Record<string, any>]>, func: Condition<Iterable<Record<string, any>>, T, [Record<string, any>]>,
): MethodDecorator => Metadata.append('KoishiFor', func); ): TypedMethodDecorator<T> => Metadata.append('KoishiFor', func);
export const UseModel = (...models: ModelClassType[]): ClassDecorator => export const UseModel = (...models: ModelClassType[]): ClassDecorator =>
TopLevelAction((ctx) => { TopLevelAction((ctx) => {
......
...@@ -47,3 +47,9 @@ export type MapPluginToConfig<M extends Dict<PluginClass>> = { ...@@ -47,3 +47,9 @@ export type MapPluginToConfig<M extends Dict<PluginClass>> = {
export type MapPluginToConfigWithSelection<M extends Dict<PluginClass>> = { export type MapPluginToConfigWithSelection<M extends Dict<PluginClass>> = {
[K in keyof M]: ClassPluginConfig<M[K]> & Selection; [K in keyof M]: ClassPluginConfig<M[K]> & Selection;
}; };
export type TypedMethodDecorator<T> = <P>(
target: T,
propertyKey: string | symbol,
descriptor: TypedPropertyDescriptor<P>,
) => void;
...@@ -8,6 +8,7 @@ import { ...@@ -8,6 +8,7 @@ import {
KoishiServiceProvideSym, KoishiServiceProvideSym,
KoishiSystemInjectSym, KoishiSystemInjectSym,
KoishiSystemInjectSymKeys, KoishiSystemInjectSymKeys,
PluginClass,
ThirdEyeSym, ThirdEyeSym,
} from './def'; } from './def';
import { reflector } from './meta/meta-fetch'; import { reflector } from './meta/meta-fetch';
...@@ -18,7 +19,8 @@ import { PluginName, PluginSchema, UsingService } from './decorators'; ...@@ -18,7 +19,8 @@ import { PluginName, PluginSchema, UsingService } from './decorators';
export interface KoishiPluginRegistrationOptions<T = any> { export interface KoishiPluginRegistrationOptions<T = any> {
name?: string; name?: string;
schema?: Schema<any, T> | Type<T>; schema?: Schema<T> | Type<T>;
Config?: Schema<T> | Type<T>;
using?: (keyof Context.Services)[]; using?: (keyof Context.Services)[];
} }
...@@ -47,13 +49,18 @@ export interface LifecycleEvents { ...@@ -47,13 +49,18 @@ export interface LifecycleEvents {
onDisconnect?(): void | Promise<void>; onDisconnect?(): void | Promise<void>;
} }
export function DefinePlugin<T = any>( export function DefinePlugin<T>(
options?: KoishiPluginRegistrationOptions<T>,
): <C extends PluginClass<T>>(
plugin: C,
) => C & KoishiPluginRegistrationOptions<T>;
export function DefinePlugin<T>(
options: KoishiPluginRegistrationOptions<T> = {}, options: KoishiPluginRegistrationOptions<T> = {},
) { ) {
return function < return function <
C extends { C extends {
new (...args: any[]): any; new (...args: any[]): any;
} & KoishiPluginRegistrationOptions<T>, },
>(originalClass: C) { >(originalClass: C) {
if (options.name) { if (options.name) {
PluginName(options.name)(originalClass); PluginName(options.name)(originalClass);
......
...@@ -24,7 +24,7 @@ class MyPlugin2 extends BasePlugin<{ ...@@ -24,7 +24,7 @@ class MyPlugin2 extends BasePlugin<{
prefix: string; prefix: string;
commands: { name: string; return: string }[]; commands: { name: string; return: string }[];
}> { }> {
@For<MyPlugin2>(({ config }) => config.commands) @For(({ config }) => config.commands)
@If<MyPlugin2>((_, def) => def.name !== 'badthing') @If<MyPlugin2>((_, def) => def.name !== 'badthing')
@UseCommand('{{name}}') @UseCommand('{{name}}')
onCommand( onCommand(
......
import { RegisterSchema, SchemaProperty } from '..'; import { RegisterSchema, SchemaProperty, StarterPlugin } from '..';
import { Assets, Bot, Cache, Context } from 'koishi'; import { Assets, Bot, Cache, Context } from 'koishi';
import { import { Inject, PluginName, UsingService } from '../src/decorators';
Inject,
PluginName,
PluginSchema,
UsingService,
} from '../src/decorators';
import { DefinePlugin } from '../src/register'; import { DefinePlugin } from '../src/register';
@RegisterSchema() @RegisterSchema()
...@@ -15,12 +10,11 @@ class Config { ...@@ -15,12 +10,11 @@ class Config {
} }
describe('InjectUsing', () => { describe('InjectUsing', () => {
@PluginSchema(Config)
@PluginName('foo-plugin') @PluginName('foo-plugin')
@UsingService('router') @UsingService('router')
@DefinePlugin({ using: ['database'] }) @DefinePlugin({ using: ['database'], schema: Config })
@UsingService('http') @UsingService('http')
class MyPlugin { class MyPlugin extends StarterPlugin(Config) {
@Inject(true) @Inject(true)
cache: Cache; cache: Cache;
......
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