From ec635b9ae6de85b30781dbdc56daa6126bdfb9b1 Mon Sep 17 00:00:00 2001 From: MrKBear Date: Fri, 21 Jan 2022 17:30:08 +0800 Subject: [PATCH] (#56) Add Core Data. --- miniprogram/core/Data.ts | 250 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 250 insertions(+) create mode 100644 miniprogram/core/Data.ts diff --git a/miniprogram/core/Data.ts b/miniprogram/core/Data.ts new file mode 100644 index 0000000..40a5f24 --- /dev/null +++ b/miniprogram/core/Data.ts @@ -0,0 +1,250 @@ + +/** + * 数据层键值设置 + */ +interface IDataParamSettingItem { + + /** + * 类型 + */ + type: any; + + /** + * 键值是否可以获取 + */ + isGet: boolean; + + /** + * 键值是否可以设置 + */ + isSet: boolean; + + /** + * 是否仅为异步获取 + */ + isGetAsync?: boolean; + + /** + * 是否仅为异步设置 + */ + isSetAsync?: boolean; +} + +/** + * 数据层参数类型 + */ +interface IDataParamSetting { + [x: string]: IDataParamSettingItem +} + +type IGet = () => T; +type IGetAsync = () => Promise; +type ISet = (data: T) => INone; +type ISetAsync = (data: T) => Promise; + +type INone = undefined | void | unknown; + +/** + * 注册表结构 + */ +type IRegistryItem = { + + /** + * 获取方法 + */ + get: S["isGetAsync"] extends true ? INone : S["isGet"] extends true ? IGet : INone; + + /** + * 异步获取方法 + */ + getAsync: S["isGet"] extends true ? IGetAsync : INone; + + /** + * 设置方法 + */ + set: S["isSetAsync"] extends true ? INone : S["isSet"] extends true ? ISet : INone; + + /** + * 异步设置方法 + */ + setAsync: S["isSet"] extends true ? ISetAsync : INone; +} + +/** + * 注册表参数类型 + */ +type IRegistry = { + [P in keyof D]: IRegistryItem; +} + +type IRegistryPartial = { + [P in keyof D]?: Partial>; +} + + +type IAutoSelect = IF extends true ? A : B; + +/** + * Core 数据层架构 + * + * 使用示例: + * ```typescript + * class TestData extends Data<{ + * test: { + * type: number, + * isGet: true, + * isSet: true, + * isGetAsync: true + * } + * }> { + * public onLoad() { + * let dataObject = {key: 1} + * this.getter("test", () => 1); + * this.registerKeyFromObject("test", "key", dataObject); + * } + * } + * ``` + */ +class Data { + + /** + * getter setter 注册表 + */ + private registryList: IRegistryPartial = {}; + + /** + * 加载函数 + */ + public onLoad(): any {}; + + /** + * 注册一个 Setter 到键值上 + * @param key 注册的键值 + * @param setter 注册的 Setter + * @param isAsync 是否为异步函数 + */ + protected setter (key: KEY, setter: IRegistryItem["set"]): this + protected setter (key: KEY, setter: IRegistryItem["setAsync"], isAsync: true): this + protected setter< + KEY extends keyof D, + ASYNC extends boolean + > ( + key: KEY, + setter: IAutoSelect["setAsync"], IRegistryItem["set"]>, + isAsync?: ASYNC + ): this { + + // 如果此键值不存在,新建 + if (!this.registryList[key]) this.registryList[key] = {}; + + // 设置异步 setter + if (isAsync) this.registryList[key]!.setAsync = setter as IRegistryItem["setAsync"]; + + // 设置同步 setter + else this.registryList[key]!.set = setter as IRegistryItem["set"]; + + return this; + } + + /** + * 注册一个 Getter 到键值上 + * @param key 注册的键值 + * @param getter 注册的 Getter + * @param isAsync 是否为异步函数 + */ + protected getter (key: KEY, getter: IRegistryItem["get"]): this + protected getter (key: KEY, getter: IRegistryItem["getAsync"], isAsync: true): this + protected getter< + KEY extends keyof D, + ASYNC extends boolean + > ( + key: KEY, + getter: IAutoSelect["getAsync"], IRegistryItem["get"]>, + isAsync?: ASYNC + ): this { + + // 如果此键值不存在,新建 + if (!this.registryList[key]) this.registryList[key] = {}; + + // 设置异步 getter + if (isAsync) this.registryList[key]!.getAsync = getter as IRegistryItem["getAsync"]; + + // 设置同步 getter + else this.registryList[key]!.get = getter as IRegistryItem["get"]; + + return this; + } + + /** + * 将对象的键值关联到 Data 层中 + * @param key Data 层键值 + * @param keyFromObject 对象源键值 + * @param object 关联对象 + */ + protected registerKeyFromObject< + KEY extends keyof D, + F extends keyof O, + O extends {[K in F]: D[KEY]["type"]} + > (key: KEY, keyFromObject: F, object: O) { + + // 注册同步获取 + this.getter(key, () => { + return object[keyFromObject] + }); + + // 注册同步设置 + this.setter(key, (data: any) => { + object[keyFromObject] = data + }) + } + + /** + * 导出数据对象 + * @returns 数据对象 + */ + public export(): IRegistry { + this.autoFillFunction(); + return this.registryList as IRegistry; + } + + /** + * 自动填充缺失的异步函数 + * 在注册表中搜索全部的同步函数 + * 并自动填充对应的异步函数 + * 此函数会在 export 前静默执行 + */ + protected autoFillFunction(): void { + + // 填充函数 + const fillFunction = (key: KEY): void => { + + const item = this.registryList[key] as IRegistryItem; + if (!item) return; + + // 检验 getter + if (item.get && !item.getAsync) { + item.getAsync = this.syncFn2AsyncFn(item.get as IGet); + } + + // 检验 setter + if (item.set && !item.setAsync) { + item.setAsync = this.syncFn2AsyncFn(item.set as ISet); + } + } + + // 在注册表中查找 + for (const key in this.registryList) fillFunction(key); + } + + /** + * 将同步函数转换为异步函数 + * @param fn 同步函数 + */ + protected syncFn2AsyncFn | ISet)> (fn: H): + IAutoSelect ? true : false, IGetAsync, ISetAsync> { + const asyncFn = async (...param: [D]) => { + return fn(...param); + }; + return asyncFn as any; + } +} \ No newline at end of file