feat: 复写api

This commit is contained in:
unanmed 2024-01-27 22:45:07 +08:00
parent 5119227a41
commit 483df57fdf

View File

@ -95,7 +95,14 @@ interface SystemInterfaceMap {
type InterfaceType = keyof SystemInterfaceMap; type InterfaceType = keyof SystemInterfaceMap;
interface PluginInterface {}
export interface IMota { export interface IMota {
rewrite: typeof rewrite;
rewriteSys: typeof rewriteSys;
Plugin: IPlugin;
/** /**
* *
* @param type * @param type
@ -138,6 +145,131 @@ export interface IMota {
register(type: InterfaceType, key: string, data: any): void; register(type: InterfaceType, key: string, data: any): void;
} }
export interface IPlugin {
/**
*
*/
init(): void;
/**
*
* @param plugin
*/
init(plugin: string): void;
/**
*
* @param plugin
*/
require<K extends keyof PluginInterface>(plugin: K): PluginInterface[K];
/**
*
* @param plugin
*/
require(plugin: string): any;
/**
*
*/
requireAll(): PluginInterface;
/**
*
* @param plugin
* @param data
* @param init plugin和data
*/
register<K extends keyof PluginInterface>(
plugin: K,
data: PluginInterface[K],
init?: (plugin: K, data: PluginInterface[K]) => void
): void;
/**
*
* @param plugin
* @param init
*/
register<K extends keyof PluginInterface>(
plugin: K,
init: (plugin: K) => PluginInterface[K]
): void;
/**
*
* @param plugin
* @param data
* @param init plugin和data
*/
register<K extends string, D>(
plugin: K,
data: D,
init?: (plugin: K, data: D) => void
): void;
/**
*
* @param plugin
* @param init
*/
register<K extends string>(plugin: K, init: (plugin: K) => any): void;
}
interface IPluginData {
/** 插件类型content表示直接注册了内容function表示注册了初始化函数内容从其返回值获取 */
type: 'content' | 'function';
data: any;
init?: (plugin: string, data?: any) => any;
}
class MPlugin {
private static plugins: Record<string, IPluginData> = {};
private static inited = false;
private static pluginData: Record<string, any> = {};
constructor() {
throw new Error(`System plugin class cannot be constructed.`);
}
static init() {
for (const [key, data] of Object.entries(this.plugins)) {
if (data.type === 'content') {
data.init?.(key, data.data);
} else {
data.data = data.init!(key);
}
this.pluginData[key] = data.data;
}
this.inited = true;
}
static require(key: string) {
if (!this.inited) {
throw new Error(`Cannot access plugin '${key}' before initialize.`);
}
if (!(key in this.plugins)) {
throw new Error(`Cannot resolve plugin require: key='${key}'`);
}
return this.plugins[key].data;
}
static requireAll() {
return this.pluginData;
}
static register(key: string, data: any, init?: any) {
if (typeof data === 'function') {
this.plugins[key] = {
type: 'function',
init: data,
data: void 0
};
} else {
this.plugins[key] = {
type: 'content',
data,
init
};
}
}
}
/** /**
* Mota * Mota
*/ */
@ -146,25 +278,14 @@ class Mota {
private static functions: Record<string, any> = {}; private static functions: Record<string, any> = {};
private static variables: Record<string, any> = {}; private static variables: Record<string, any> = {};
static rewrite = rewrite;
static rewriteSys = rewriteSys;
static Plugin = MPlugin;
constructor() { constructor() {
throw new Error(`System interface class cannot be constructed.`); throw new Error(`System interface class cannot be constructed.`);
} }
/**
*
* @param type
* @param key
*/
static require<
T extends InterfaceType,
K extends keyof SystemInterfaceMap[T]
>(type: T, key: K): SystemInterfaceMap[T][K];
/**
*
* @param type
* @param key
*/
static require(type: InterfaceType, key: string): any;
static require(type: InterfaceType, key: string): any { static require(type: InterfaceType, key: string): any {
const data = this.getByType(type)[key]; const data = this.getByType(type)[key];
if (!!data) return data; if (!!data) return data;
@ -175,31 +296,10 @@ class Mota {
} }
} }
/**
*
* @param type
*/
static requireAll<T extends InterfaceType>(type: T): SystemInterfaceMap[T] { static requireAll<T extends InterfaceType>(type: T): SystemInterfaceMap[T] {
return this.getByType(type) as SystemInterfaceMap[T]; return this.getByType(type) as SystemInterfaceMap[T];
} }
/**
*
* @param type
* @param key
* @param data
*/
static register<
T extends InterfaceType,
K extends keyof SystemInterfaceMap[T]
>(type: T, key: K, data: SystemInterfaceMap[T][K]): void;
/**
*
* @param type
* @param key
* @param data
*/
static register(type: InterfaceType, key: string, data: any): void;
static register(type: InterfaceType, key: string, data: any) { static register(type: InterfaceType, key: string, data: any) {
const obj = this.getByType(type); const obj = this.getByType(type);
if (key in obj) { if (key in obj) {
@ -219,6 +319,135 @@ class Mota {
} }
} }
type RewriteType = 'full' | 'front' | 'add';
type _F<F> = F extends (...params: infer P) => infer R ? [P, R] : never;
type _Func = (...params: any) => any;
/**
*
* @param base
* @param key base中叫什么
* @param type full表示全量复写front表示在原函数之前添加内容
* @param re full时表示将原函数完全覆盖front时表示将该函数添加到原函数之前
* @param bind base
* @param rebind base
*/
function rewrite<O, K extends SelectKey<O, _Func>, T = O>(
base: O,
key: K,
type: 'full' | 'front',
re: (this: T, ...params: [..._F<O[K]>[0], ...any[]]) => _F<O[K]>[1],
bind?: any,
rebind?: T
): (this: T, ...params: [..._F<O[K]>[0], ...any[]]) => _F<O[K]>[1];
/**
*
* @param base
* @param key base中叫什么
* @param type add表示在函数后追加
* @param re add时表示在原函数后面追加复写函数
*
* @param bind base
* @param rebind base
*/
function rewrite<O, K extends SelectKey<O, _Func>, T = O>(
base: O,
key: K,
type: 'add',
re: (
this: T,
...params: [_F<O[K]>[1], ..._F<O[K]>[0], ...any[]]
) => _F<O[K]>[1],
bind?: any,
rebind?: T
): (this: T, ...params: [..._F<O[K]>[0], ...any[]]) => _F<O[K]>[1];
function rewrite<O, K extends SelectKey<O, _Func>, T = O>(
base: O,
key: K,
type: RewriteType,
re: (this: T, ...params: [..._F<O[K]>[0], ...any[]]) => _F<O[K]>[1],
bind?: any,
rebind?: T
): (this: T, ...params: [..._F<O[K]>[0], ...any[]]) => _F<O[K]>[1] {
const func = base[key];
if (typeof func !== 'function') {
throw new Error(
`Cannot rewrite variable with type of '${typeof func}'.`
);
}
if (type === 'full') {
// @ts-ignore
return (base[key] = re.bind(rebind ?? base));
} else if (type === 'add') {
const origin = base[key];
function res(this: T, ...params: [..._F<O[K]>[0], ...any[]]) {
const v = (origin as _Func).call(bind ?? base, ...params);
// @ts-ignore
const ret = re.call(rebind ?? base, v, ...params);
return ret;
}
// @ts-ignore
return (base[key] = res);
} else {
const origin = base[key];
function res(this: T, ...params: [..._F<O[K]>[0], ...any[]]) {
// @ts-ignore
re.call(rebind ?? base, v, ...params);
const ret = (origin as _Func).call(bind ?? base, ...params);
return ret;
}
// @ts-ignore
return (base[key] = res);
}
}
type _FI<K extends keyof FunctionInterface> = FunctionInterface[K];
/**
*
* @param key
* @param type full表示全量复写front表示在原函数之前添加内容
* @param re full时表示将原函数完全覆盖front时表示将该函数添加到原函数之前
* @param bind base
* @param rebind base
*/
function rewriteSys<K extends keyof FunctionInterface, T>(
key: K,
type: 'full' | 'front',
re: (this: T, ...params: [..._F<_FI<K>>[0], ...any[]]) => _F<_FI<K>>[1],
bind?: any,
rebind?: T
): (this: T, ...params: [..._F<_FI<K>>[0], ...any[]]) => _F<_FI<K>>[1];
/**
*
* @param key
* @param type add表示在函数后追加
* @param re add时表示在原函数后面追加复写函数
*
* @param bind base
* @param rebind base
*/
function rewriteSys<K extends keyof FunctionInterface, T>(
key: K,
type: 'add',
re: (
this: T,
...params: [_F<_FI<K>>[1], ..._F<_FI<K>>[0], ...any[]]
) => _F<_FI<K>>[1],
bind?: any,
rebind?: T
): (this: T, ...params: [..._F<_FI<K>>[0], ...any[]]) => _F<_FI<K>>[1];
function rewriteSys<K extends keyof FunctionInterface, T>(
key: K,
type: RewriteType,
re: (this: T, ...params: [..._F<_FI<K>>[0], ...any[]]) => _F<_FI<K>>[1],
bind?: any,
rebind?: T
): (this: T, ...params: [..._F<_FI<K>>[0], ...any[]]) => _F<_FI<K>>[1] {
// @ts-ignore
return rewrite(Mota.requireAll('fn'), key, type, re, bind, rebind);
}
declare global { declare global {
interface Window { interface Window {
Mota: IMota; Mota: IMota;