Commit 513acaf0 authored by nanahira's avatar nanahira

add top level template

parent 38645bc3
......@@ -2,15 +2,18 @@ import {
BeforeEventName,
CommandConfigExtended,
CommandDefinitionFun,
ContextFunction,
EventName,
KoishiCommandDefinition,
KoishiCommandPutDef,
KoishiOnContextScope,
OnContextFunction,
TopLevelActionDef,
} from '../def';
import 'reflect-metadata';
import {
Argv,
Awaitable,
Command,
Dict,
FieldCollector,
......@@ -196,3 +199,11 @@ export const PutTemplate = (name: string, text: string | Dict<string>) =>
name,
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
import { CommandDefinitionFun, OnContextFunction } from './interfaces';
import {
CommandDefinitionFun,
ContextFunction,
OnContextFunction,
TopLevelActionDef,
} from './interfaces';
import { DoRegister } from '../registry';
import { Awaitable } from 'koishi';
export const KoishiOnContextScope = 'KoishiOnContextScope';
export const KoishiDoRegister = 'KoishiDoRegister';
......@@ -14,6 +20,7 @@ export interface MetadataArrayMap {
KoishiOnContextScope: OnContextFunction;
KoishiCommandDefinition: CommandDefinitionFun;
KoishiDoRegisterKeys: string;
KoishiTopLevelAction: TopLevelActionDef;
}
export interface MetadataMap {
......
......@@ -144,3 +144,5 @@ export interface TemplateConfig {
name: string;
text: Dict<string>;
}
export type TopLevelActionDef = (ctx: Context, obj: any) => void;
......@@ -7,6 +7,7 @@ import { reflector } from './meta/meta-fetch';
import { Context } from 'koishi';
import { getContextFromFilters } from './utility';
import { DoRegister } from './registry';
import _ from 'lodash';
export interface DoRegisterResult<T> extends DoRegister.Config {
key: keyof T & string;
......@@ -63,8 +64,23 @@ export class Registrar<T = any> {
if (autoScope) {
ctx = this.getScopeContext(ctx);
}
this.performTopActions(ctx, false);
return this.getAllFieldsToRegister().map((key) =>
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