Commit 5a47b011 authored by nanahira's avatar nanahira

remake with typed-reflector

parent 5c236463
......@@ -10,7 +10,8 @@
"license": "MIT",
"dependencies": {
"koishi-utils-schemagen": "^1.1.9",
"reflect-metadata": "^0.1.13"
"reflect-metadata": "^0.1.13",
"typed-reflector": "^1.0.2"
},
"devDependencies": {
"@koishijs/plugin-adapter-onebot": "^4.0.0-beta.0",
......@@ -2941,6 +2942,14 @@
"node": ">= 0.6"
}
},
"node_modules/typed-reflector": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/typed-reflector/-/typed-reflector-1.0.2.tgz",
"integrity": "sha512-dyhBLKAbT0O/OEIJXQw+IqAH9ddFk0iV4gJP5XvcgcfJ0xxyx4krx1visZtH8YoFe86piRKgO9VPs/Ktzfdb0w==",
"dependencies": {
"reflect-metadata": "^0.1.13"
}
},
"node_modules/typescript": {
"version": "4.4.4",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz",
......@@ -5267,6 +5276,14 @@
"mime-types": "~2.1.24"
}
},
"typed-reflector": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/typed-reflector/-/typed-reflector-1.0.2.tgz",
"integrity": "sha512-dyhBLKAbT0O/OEIJXQw+IqAH9ddFk0iV4gJP5XvcgcfJ0xxyx4krx1visZtH8YoFe86piRKgO9VPs/Ktzfdb0w==",
"requires": {
"reflect-metadata": "^0.1.13"
}
},
"typescript": {
"version": "4.4.4",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz",
......
......@@ -2,6 +2,7 @@ import {
CommandDefinitionFun,
CommandPutConfig,
CommandPutConfigMap,
DoRegisterConfig,
EventName,
GenerateMappingStruct,
KoishiCommandDefinition,
......@@ -14,25 +15,18 @@ import {
KoishiServiceProvideSym,
KoishiSystemInjectSym,
KoishiSystemInjectSymKeys,
MetadataGenericMap,
MetadataMap,
OnContextFunction,
Selection,
} from './def';
import 'reflect-metadata';
import { App, Argv, Command, Context, FieldCollector, Session } from 'koishi';
import {
AppendMetadata,
AppendMetadataUnique,
ConcatMetadata,
SetMetadata,
} from './meta/metadata.decorators';
import { PluginClass } from './register';
import { Metadata } from './meta/metadata.decorators';
// Register methods
export const DoRegister = (
value: MetadataGenericMap['KoishiDoRegister'],
): MethodDecorator =>
SetMetadata(KoishiDoRegister, value, KoishiDoRegisterKeys);
export const DoRegister = (value: DoRegisterConfig): MethodDecorator =>
Metadata.set(KoishiDoRegister, value, KoishiDoRegisterKeys);
export const UseMiddleware = (prepend?: boolean): MethodDecorator =>
DoRegister(GenerateMappingStruct('middleware', prepend));
......@@ -78,7 +72,7 @@ export function UseCommand(
export const OnContext = (
ctxFun: OnContextFunction,
): MethodDecorator & ClassDecorator =>
AppendMetadata(KoishiOnContextScope, ctxFun);
Metadata.append(KoishiOnContextScope, ctxFun);
export const OnUser = (...values: string[]) =>
OnContext((ctx) => ctx.user(...values));
......@@ -104,7 +98,7 @@ export const OnSelection = (selection: Selection) =>
// Command definition
export const CommandDef = (def: CommandDefinitionFun): MethodDecorator =>
AppendMetadata(KoishiCommandDefinition, def);
Metadata.append(KoishiCommandDefinition, def);
export const CommandDescription = (desc: string) =>
CommandDef((cmd) => {
......@@ -197,7 +191,7 @@ export function Inject(name?: keyof Context.Services): PropertyDecorator {
}
}
const serviceName = name || (key as keyof Context.Services);
const dec = SetMetadata(
const dec = Metadata.set(
KoishiServiceInjectSym,
serviceName,
KoishiServiceInjectSymKeys,
......@@ -211,11 +205,11 @@ export function Provide(
options?: Context.Options,
): ClassDecorator {
Context.service(name, options);
return AppendMetadataUnique(KoishiServiceProvideSym, name);
return Metadata.appendUnique(KoishiServiceProvideSym, name);
}
const InjectSystem = (fun: (obj: PluginClass) => any) =>
SetMetadata(KoishiSystemInjectSym, fun, KoishiSystemInjectSymKeys);
Metadata.set(KoishiSystemInjectSym, fun, KoishiSystemInjectSymKeys);
export const InjectContext = (select?: Selection) =>
InjectSystem((obj) => {
......
......@@ -142,24 +142,3 @@ export type CommandPutConfig<
> = MappingStruct<CommandPutConfigMap, K>;
export type CommandDefinitionFun = (cmd: Command) => Command;
// metadata map
export type MetadataArrayValueMap = {
[K in keyof MetadataArrayMap]: MetadataArrayMap[K][];
};
export type MetadataGenericMap = MetadataArrayValueMap & MetadataMap;
export type MetadataArrayValue<
K extends keyof MetadataArrayValueMap
> = MetadataArrayValueMap[K];
export type MetadataKey = keyof MetadataArrayMap | keyof MetadataMap;
export type MetadataMapValue<
K extends MetadataKey
> = K extends keyof MetadataArrayValueMap
? MetadataArrayValue<K>
: K extends keyof MetadataMap
? MetadataMap[K]
: never;
import {
MetadataArrayMap,
MetadataArrayValue,
MetadataGenericMap,
MetadataMapValue,
} from '../def';
import 'reflect-metadata';
import { Reflector } from 'typed-reflector';
import { MetadataArrayMap, MetadataMap } from '../def';
export function getMetadata<K extends keyof MetadataGenericMap>(
metadataKey: K,
instance: any,
key?: string | symbol,
): MetadataMapValue<K> {
const instanceClass = instance.constructor;
if (key) {
return Reflect.getMetadata(metadataKey, instanceClass, key);
} else {
return Reflect.getMetadata(metadataKey, instanceClass);
}
}
export function getMetadataArray<K extends keyof MetadataArrayMap>(
metadataKey: K,
instance: any,
key?: string | symbol,
): MetadataArrayValue<K> {
return getMetadata(metadataKey, instance, key) || [];
}
export function getPropertyMetadata<K extends keyof MetadataArrayMap, I = any>(
metadataKey: K,
instance: I,
originalClass: any,
key: keyof I & (string | symbol),
): MetadataArrayValue<K> {
const valueFromClass = getMetadataArray(metadataKey, originalClass);
const valueFromProperty = getMetadataArray(metadataKey, instance, key);
return [...valueFromClass, ...valueFromProperty] as MetadataArrayValue<K>;
}
export const reflector = new Reflector<MetadataMap, MetadataArrayMap>();
import {
MetadataArrayMap,
MetadataArrayValue,
MetadataArrayValueMap,
MetadataGenericMap,
MetadataKey,
} from '../def';
import 'reflect-metadata';
import { MetadataSetter } from 'typed-reflector';
import { MetadataArrayMap, MetadataMap } from '../def';
export type AllDecorators = MethodDecorator &
ClassDecorator &
PropertyDecorator;
function getMetadataInDecorator<
K extends MetadataKey,
VM extends Partial<MetadataGenericMap> = MetadataGenericMap
>(metaKey: K, target: any, key?: any): VM[K] {
const targetClass = target.constructor;
if (key) {
return Reflect.getMetadata(metaKey, targetClass, key);
} else {
return Reflect.getMetadata(metaKey, targetClass);
}
}
function setMetadataInDecorator<
K extends MetadataKey,
VM extends Partial<MetadataGenericMap> = MetadataGenericMap
>(metaKey: K, value: VM[K], target: any, key?: any) {
const targetClass = target.constructor;
if (key) {
return Reflect.defineMetadata(metaKey, value, targetClass, key);
} else {
return Reflect.defineMetadata(metaKey, value, targetClass);
}
}
function TransformMetadata<
K extends MetadataKey,
VM extends Partial<MetadataGenericMap> = MetadataGenericMap
>(
metadataKey: K,
metadataValueFun: (oldValue: VM[K]) => VM[K],
keysIndexMeta?: keyof MetadataArrayMap,
): AllDecorators {
return (target: any, key?: any, descriptor?: any) => {
const oldValue: VM[K] = getMetadataInDecorator(metadataKey, target, key);
const newValue = metadataValueFun(oldValue);
setMetadataInDecorator(metadataKey, newValue, target, key);
if (keysIndexMeta) {
const keysDec = AppendMetadataUnique(keysIndexMeta, key);
keysDec(target);
}
if (descriptor) {
return descriptor;
}
return target;
};
}
export const SetMetadata = <K extends keyof MetadataGenericMap>(
metadataKey: K,
metadataValue: MetadataGenericMap[K],
keysIndexMeta?: keyof MetadataArrayMap,
): AllDecorators =>
TransformMetadata<K>(metadataKey, () => metadataValue, keysIndexMeta);
export const AppendMetadata = <K extends keyof MetadataArrayMap>(
metadataKey: K,
metadataValue: MetadataArrayMap[K],
keysIndexMeta?: keyof MetadataArrayMap,
): AllDecorators =>
TransformMetadata<K, MetadataArrayValueMap>(
metadataKey,
(arr) => {
const newArr = arr || [];
newArr.push(metadataValue);
return newArr;
},
keysIndexMeta,
);
export const AppendMetadataUnique = <K extends keyof MetadataArrayMap>(
metadataKey: K,
metadataValue: MetadataArrayMap[K],
keysIndexMeta?: keyof MetadataArrayMap,
): AllDecorators =>
TransformMetadata<K, MetadataArrayValueMap>(
metadataKey,
(arr) => {
const newArr = arr || [];
if (newArr.includes(metadataValue)) {
return newArr;
}
newArr.push(metadataValue);
return newArr;
},
keysIndexMeta,
);
export const ConcatMetadata = <K extends keyof MetadataArrayValueMap>(
metadataKey: K,
metadataValue: MetadataArrayValue<K>,
keysIndexMeta?: keyof MetadataArrayMap,
): AllDecorators =>
TransformMetadata<K, MetadataArrayValueMap>(
metadataKey,
(arr) => ((arr || []) as any[]).concat(metadataValue),
keysIndexMeta,
);
export const Metadata = new MetadataSetter<MetadataMap, MetadataArrayMap>();
......@@ -16,7 +16,7 @@ import {
Type,
} from './def';
import { schemaFromClass, schemaTransform } from 'koishi-utils-schemagen';
import { getMetadata, getMetadataArray } from './meta/meta-fetch';
import { reflector } from './meta/meta-fetch';
import { applySelector } from './utility/utility';
export interface KoishiPluginRegistrationOptions<T = any> {
......@@ -61,10 +61,10 @@ export function KoishiPlugin<T = any>(
_handleSystemInjections() {
// console.log('Handling system injection');
const injectKeys = getMetadataArray(KoishiSystemInjectSymKeys, this);
const injectKeys = reflector.getArray(KoishiSystemInjectSymKeys, this);
for (const key of injectKeys) {
// console.log(`Processing ${key}`);
const valueFunction = getMetadata(KoishiSystemInjectSym, this, key);
const valueFunction = reflector.get(KoishiSystemInjectSym, this, key);
Object.defineProperty(this, key, {
configurable: true,
enumerable: true,
......@@ -75,10 +75,10 @@ export function KoishiPlugin<T = any>(
_handleServiceInjections() {
// console.log('Handling service injection');
const injectKeys = getMetadataArray(KoishiServiceInjectSymKeys, this);
const injectKeys = reflector.getArray(KoishiServiceInjectSymKeys, this);
for (const key of injectKeys) {
// console.log(`Processing ${key}`);
const name = getMetadata(KoishiServiceInjectSym, this, key);
const name = reflector.get(KoishiServiceInjectSym, this, key);
Object.defineProperty(this, key, {
enumerable: true,
configurable: true,
......@@ -171,14 +171,14 @@ export function KoishiPlugin<T = any>(
async _registerDeclarationsFor(methodKey: keyof C & string) {
// console.log(`Handling declaration for ${methodKey}`);
const regData = getMetadata(KoishiDoRegister, this, methodKey);
const regData = reflector.get(KoishiDoRegister, this, methodKey);
if (!regData) {
return;
}
// console.log(`Type: ${regData.type}`);
const baseContext = getContextFromFilters(
this.__ctx,
getMetadataArray(KoishiOnContextScope, this, methodKey),
reflector.getArray(KoishiOnContextScope, this, methodKey),
);
switch (regData.type) {
case 'middleware':
......@@ -224,7 +224,7 @@ export function KoishiPlugin<T = any>(
commandData.desc,
commandData.config,
);
const commandDefs = getMetadataArray(
const commandDefs = reflector.getArray(
KoishiCommandDefinition,
this,
methodKey,
......@@ -254,7 +254,7 @@ export function KoishiPlugin<T = any>(
}
async _registerDeclarations() {
const methodKeys = getMetadataArray(
const methodKeys = reflector.getArray(
KoishiDoRegisterKeys,
this,
) as (keyof C & string)[];
......@@ -268,7 +268,7 @@ export function KoishiPlugin<T = any>(
_handleServiceProvide(connect = true) {
// console.log(`Handling service provide`);
const providingServices = getMetadataArray(
const providingServices = reflector.getArray(
KoishiServiceProvideSym,
originalClass,
);
......@@ -307,7 +307,7 @@ export function KoishiPlugin<T = any>(
constructor(...args: any[]) {
const originalCtx: Context = args[0];
const rawConfig = args[1];
const contextFilters = getMetadataArray(
const contextFilters = reflector.getArray(
KoishiOnContextScope,
originalClass,
);
......
......@@ -2,7 +2,7 @@
"compilerOptions": {
"outDir": "dist",
"module": "commonjs",
"target": "es2021",
"target": "es2020",
"esModuleInterop": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
......
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