Commit 513acaf0 authored by nanahira's avatar nanahira

add top level template

parent 38645bc3
...@@ -2,15 +2,18 @@ import { ...@@ -2,15 +2,18 @@ import {
BeforeEventName, BeforeEventName,
CommandConfigExtended, CommandConfigExtended,
CommandDefinitionFun, CommandDefinitionFun,
ContextFunction,
EventName, EventName,
KoishiCommandDefinition, KoishiCommandDefinition,
KoishiCommandPutDef, KoishiCommandPutDef,
KoishiOnContextScope, KoishiOnContextScope,
OnContextFunction, OnContextFunction,
TopLevelActionDef,
} from '../def'; } from '../def';
import 'reflect-metadata'; import 'reflect-metadata';
import { import {
Argv, Argv,
Awaitable,
Command, Command,
Dict, Dict,
FieldCollector, FieldCollector,
...@@ -196,3 +199,11 @@ export const PutTemplate = (name: string, text: string | Dict<string>) => ...@@ -196,3 +199,11 @@ export const PutTemplate = (name: string, text: string | Dict<string>) =>
name, name,
text: adaptLocaleDict(text), text: adaptLocaleDict(text),
}); });
export const TopLevelAction = (action: TopLevelActionDef): ClassDecorator =>
Metadata.append('KoishiTopLevelAction', action);
export const DefineTemplate = (name: string, text: string | Dict<string>) =>
TopLevelAction((ctx) =>
registerTemplate({ name, text: adaptLocaleDict(text) }, ctx),
);
// metadatas // metadatas
import { CommandDefinitionFun, OnContextFunction } from './interfaces'; import {
CommandDefinitionFun,
ContextFunction,
OnContextFunction,
TopLevelActionDef,
} from './interfaces';
import { DoRegister } from '../registry'; import { DoRegister } from '../registry';
import { Awaitable } from 'koishi';
export const KoishiOnContextScope = 'KoishiOnContextScope'; export const KoishiOnContextScope = 'KoishiOnContextScope';
export const KoishiDoRegister = 'KoishiDoRegister'; export const KoishiDoRegister = 'KoishiDoRegister';
...@@ -14,6 +20,7 @@ export interface MetadataArrayMap { ...@@ -14,6 +20,7 @@ export interface MetadataArrayMap {
KoishiOnContextScope: OnContextFunction; KoishiOnContextScope: OnContextFunction;
KoishiCommandDefinition: CommandDefinitionFun; KoishiCommandDefinition: CommandDefinitionFun;
KoishiDoRegisterKeys: string; KoishiDoRegisterKeys: string;
KoishiTopLevelAction: TopLevelActionDef;
} }
export interface MetadataMap { export interface MetadataMap {
......
...@@ -144,3 +144,5 @@ export interface TemplateConfig { ...@@ -144,3 +144,5 @@ export interface TemplateConfig {
name: string; name: string;
text: Dict<string>; text: Dict<string>;
} }
export type TopLevelActionDef = (ctx: Context, obj: any) => void;
...@@ -7,6 +7,7 @@ import { reflector } from './meta/meta-fetch'; ...@@ -7,6 +7,7 @@ import { reflector } from './meta/meta-fetch';
import { Context } from 'koishi'; import { Context } from 'koishi';
import { getContextFromFilters } from './utility'; import { getContextFromFilters } from './utility';
import { DoRegister } from './registry'; import { DoRegister } from './registry';
import _ from 'lodash';
export interface DoRegisterResult<T> extends DoRegister.Config { export interface DoRegisterResult<T> extends DoRegister.Config {
key: keyof T & string; key: keyof T & string;
...@@ -63,8 +64,23 @@ export class Registrar<T = any> { ...@@ -63,8 +64,23 @@ export class Registrar<T = any> {
if (autoScope) { if (autoScope) {
ctx = this.getScopeContext(ctx); ctx = this.getScopeContext(ctx);
} }
this.performTopActions(ctx, false);
return this.getAllFieldsToRegister().map((key) => return this.getAllFieldsToRegister().map((key) =>
this.register(ctx, key, true), this.register(ctx, key, true),
); );
} }
performTopActions(ctx: Context, autoScope = false) {
if (autoScope) {
ctx = this.getScopeContext(ctx);
}
let actions = reflector.getArray('KoishiTopLevelAction', this.obj);
if (this.alternativeObject) {
actions = actions.concat(
reflector.getArray('KoishiTopLevelAction', this.alternativeObject),
);
}
actions = _.uniq(actions);
actions.forEach((action) => action(ctx, this.obj));
}
} }
import { TopLevelAction } from '../src/decorators';
import { Registrar } from '../src/register';
import { App } from 'koishi';
@TopLevelAction((ctx, o) => (o.foo = 1))
@TopLevelAction((ctx, o) => (o.bar = 2))
class MyClass {
foo = 0;
bar = 0;
}
@TopLevelAction((ctx, o) => (o.baz = 3))
class MyAnotherClass extends MyClass {
baz = 0;
}
class UnrelatedClass {
foo = 0;
bar = 0;
}
describe('Top level action', () => {
it('should be applied to the class', () => {
const instance = new MyClass();
const registrar = new Registrar(instance);
const app = new App();
registrar.performTopActions(app);
expect(instance.foo).toBe(1);
expect(instance.bar).toBe(2);
});
it('should be applied to the class and its subclasses', () => {
const instance = new MyAnotherClass();
const registrar = new Registrar(instance);
const app = new App();
registrar.performTopActions(app);
expect(instance.foo).toBe(1);
expect(instance.bar).toBe(2);
expect(instance.baz).toBe(3);
});
it('should not be applied to the unrelated class', () => {
const instance = new UnrelatedClass();
const registrar = new Registrar(instance);
const app = new App();
registrar.performTopActions(app);
expect(instance.foo).toBe(0);
expect(instance.bar).toBe(0);
});
});
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