UNPKG

ts-api-core

Version:

Nodejs api framework core

596 lines 24.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SubObjectConverter = exports.JsonObjectSrcConverter = exports.DateSrcConverter = exports.IntSrcConverter = exports.BoolCalcSrcConverter = exports.BoolValueSrcConverter = exports.EqualValueFilterSrcConverter = exports.ExcludeFieldSrcConverter = exports.SrcConverterBase = exports.src = exports.SrcParams = exports.ModelHelper = void 0; const error_1 = require("../base/error"); const model_hump_helper_1 = require("./model.hump.helper"); /** * 数据模型转化 * @author yangyxd 2021.03.16 */ // eslint-disable-next-line @typescript-eslint/no-extraneous-class class ModelHelper { /** * 将输入的一个any对象转化为指定的对象 * @param data 输入对象 * @param ouputClass 要输入的类型 * @param skeepNull 跳过空字段(输入数据为空时,保留现在数据) * @param mergeAllField 合并所有字段 * @param convSubFieldName 是否转变子对象的名称 * @returns */ static toModel(data, ouputClass, skeepNull = false, mergeAllField = false, convSubFieldName) { const result = new ouputClass(); if (data !== null && data !== undefined) { if (Array.isArray(data)) { throw new error_1.SysError("data不应该是数组", "ModelHelper.toModel"); } if (mergeAllField === true) { this.initModel(data, result, true, convSubFieldName); } else { this.initObject(result, data, Object.keys(result), skeepNull, convSubFieldName, undefined, mergeAllField); } } return result; } /** * 将输入的一个any对象数组转化为指定的对象数组 * @param data 输入对象 * @param ouputClass 要输入的类型 * @param convert 转换器 * @param skeepNull 跳过空字段(输入数据为空时,保留现在数据) * @param mergeAllField 合并所有字段 * @param convSubFieldName 是否转变子对象的名称 * @returns */ static toArrayModel(data, ouputClass, convert, skeepNull = false, mergeAllField = false, convSubFieldName) { const result = new Array(); if (data !== undefined) { // 类型信息缓存,提升性能 let cacheInfo; if (Array.isArray(data)) { data.forEach((ee) => { let item = new ouputClass(); if (mergeAllField === true) { this.initModel(ee, item, true, convSubFieldName, undefined, cacheInfo, (keys) => { cacheInfo = this.initObjectCacheInfo(item, ee, keys, true); return cacheInfo; }); } else { const keys = Object.keys(item); if (cacheInfo === undefined) { cacheInfo = this.initObjectCacheInfo(item, ee, keys); } this.initObject(item, ee, keys, skeepNull, convSubFieldName, cacheInfo, mergeAllField); } if (convert !== undefined) { convert.data = ee; item = convert.execute(item); if (item === undefined) { return; } } result.push(item); }); } else { let item = new ouputClass(); if (mergeAllField === true) { this.initModel(data, item, true, convSubFieldName); } else { this.initObject(item, data, Object.keys(item), skeepNull, convSubFieldName, undefined, mergeAllField); } if (convert !== undefined) { convert.data = data; item = convert.execute(item); if (item === undefined) { return []; } } result.push(item); } } return result; } /** * 从源数据中初始化数据,对两者进行合并,现有数据优先 * @param sourceData 源数据 * @param data 要初始化的数据 * @param mergeAllField 是否合并来源数据的所有字段,包括在T中不存在的字段 * @param convSubFieldName 是否转变子对象的字段名称 * @param convFieldName 是否转换字段名称 */ // eslint-disable-next-line max-params static initModel(sourceData, data, mergeAllField = false, convSubFieldName, convFieldName, cacheInfo, doInitCacheInfo) { if (data === null || data === undefined || sourceData === undefined || sourceData === null) { return; } const keys = cacheInfo === undefined || cacheInfo[2] === undefined ? Object.keys(data) : cacheInfo[2]; if (mergeAllField === true && cacheInfo === undefined) { this.mergeAllFields(sourceData, data, keys, convFieldName); } let _cacheInfo = cacheInfo; if (cacheInfo === undefined && doInitCacheInfo !== undefined) { _cacheInfo = doInitCacheInfo(keys); } this.initObject(data, sourceData, keys, true, convSubFieldName, _cacheInfo, mergeAllField); } /** * 合并所有字段 * @param sourceData 源数据 * @param data 输出数据 * @param keys 字段列表 * @param convFieldName 是否转换字段名称(坨峰转换),默认 `true` */ static mergeAllFields(sourceData, data, keys, convFieldName) { var _a; if (sourceData === undefined || sourceData === null) { return; } const _keys = {}; const _tmpMap = {}; keys.forEach((ee, i) => { _keys[ee.toLowerCase()] = i; }); // 处理字段名有变化的情况 (_a = ModelHelper.getClassMap(data.constructor.name, data)) === null || _a === void 0 ? void 0 : _a.forEach((value) => { _tmpMap[value.name.toLowerCase()] = true; }); for (const e in sourceData) { const _key = e.toLowerCase(); if (_tmpMap[_key] === true || _keys[_key]) { continue; } keys.push(convFieldName === false ? e : model_hump_helper_1.ModelHumpHelper.get(_key)); } } static initObjectRegKeys(_regKeys, result, keys, skeepNull = false) { if (_regKeys) { // 将注册的字段加入keys中,原因是由于没有默认值,可能字段不存在 _regKeys.forEach((k) => { const { propertyName } = k; if (!keys.includes(propertyName)) { keys.push(propertyName); } // 初始化处理有注解的字段 const srcValue = result[propertyName]; if (srcValue === null || srcValue === undefined || !skeepNull) { if (k.array) { result[propertyName] = []; } else if (k.classType !== undefined) { result[propertyName] = new k.classType(); } } else if (k.array) { if (!Array.isArray(srcValue)) { result[propertyName] = [srcValue]; } } else if (k.classType !== undefined) { if (typeof srcValue !== "object") { result[propertyName] = new k.classType(); } } }); } } static initObjectCacheInfo(result, item, keys, useKeys = false) { const _regKeys = this.getClassMap(result.constructor.name, result); // 忽略来源数据字段大小写 const _numberItem = {}; for (const e in item) { if (typeof result[e] === 'number') { _numberItem[e] = true; } } return [_regKeys, _numberItem, useKeys ? keys : undefined]; } static initObject(result, item, srcKeys, skeepNull = false, convFieldName, cacheInfo, mergeAllField = false) { var _a; const [_regKeys, _numberItem, _cachekeys] = cacheInfo !== null && cacheInfo !== void 0 ? cacheInfo : this.initObjectCacheInfo(result, item, srcKeys); const keys = _cachekeys !== null && _cachekeys !== void 0 ? _cachekeys : srcKeys; this.initObjectRegKeys(_regKeys, result, keys, skeepNull); // 忽略来源数据字段大小写 const _newItem = {}; for (const e in item) { _newItem[e.toLowerCase()] = item[e]; } // 给result赋值 const keyLen = keys.length; // eslint-disable-next-line no-plusplus for (let j = 0; j < keyLen; j++) { const _key = keys[j]; const params = _regKeys === null || _regKeys === void 0 ? void 0 : _regKeys.get(_key); const _srcKey = (_a = params === null || params === void 0 ? void 0 : params.name) !== null && _a !== void 0 ? _a : _key; const _srcKeys = _srcKey.split("."); let v = _srcKeys.length > 1 ? this.getChildrenValue(_newItem, _srcKeys) : _newItem[_srcKey.toLowerCase()]; const vNotIsDate = v ? !(v instanceof Date) : false; if (v !== undefined && v !== null) { const vIsArray = Array.isArray(v); // 如果原数据存在且类型为数组或对象时,输出数据也是数组时, 处理为数组 let _v = result[_key]; const flag = vIsArray && (v.length === 0 || typeof v[0] === "object"); if (Array.isArray(_v) && (typeof v === "object" || flag)) { // 数组处理,处理的时候会抛弃空项 if (!(params === null || params === void 0 ? void 0 : params.classType)) { continue; } let obj = new params.classType(); const _keys = Object.keys(obj); if (mergeAllField === true) { this.mergeAllFields(vIsArray ? (v.length > 0 ? v[0] : undefined) : v, obj, _keys, convFieldName); } // 如果数组不为空,说明本身就有数据。这里丢掉原来数据 if (_v.length > 0) { _v = []; result[_key] = _v; } if (vIsArray) { // 数组转数组 for (const _item of v) { obj = new params.classType(); this.initObject(obj, _item, _keys, skeepNull, convFieldName, cacheInfo, mergeAllField); obj = params.executeConvert(_item, obj); if (obj) { _v.push(obj); } } } else { // 对象转成数组 this.initObject(obj, v, _keys, skeepNull, convFieldName, cacheInfo, mergeAllField); obj = params.executeConvert(v, obj); if (obj) { _v.push(obj); } } continue; } else if (vNotIsDate && typeof _v === "object" && typeof v === "object") { // 对象转对象 const _keys = Object.keys(_v); if (mergeAllField === true) { this.mergeAllFields(v, _v, _keys, convFieldName); } this.initObject(_v, v, _keys, skeepNull, convFieldName, cacheInfo, mergeAllField); if (params === null || params === void 0 ? void 0 : params.convert) { const _tmpValue = params.executeConvert(v, _v); if (skeepNull && (_tmpValue === null || _tmpValue === undefined)) { continue; } result[_key] = _tmpValue; } continue; } } // 普通类型或为空 if (params === null || params === void 0 ? void 0 : params.convert) { v = params.executeConvert(result, v); if (v === undefined) { continue; } } if (v === null || v === undefined) { if (skeepNull || Array.isArray(result[_key])) { continue; } } if (convFieldName === true && vNotIsDate && typeof v === "object") { result[_key] = this.convObjectFieldName(v); } else if (_numberItem[_key]) { const tmpValue = Number(v); result[_key] = Number.isNaN(tmpValue) ? v : tmpValue; } else { result[_key] = v; } } } // 转换对象字段名 static convObjectFieldName(v) { const _v = {}; for (const e in v) { const k = model_hump_helper_1.ModelHumpHelper.get(e.toLowerCase()); if (typeof v[e] === "object") { _v[k] = this.convObjectFieldName(v[e]); } else { _v[k] = v[e]; } } return _v; } static getChildrenValue(data, keys) { var _a; if (data === undefined) { return data; } let result = (_a = data[keys[0].toLowerCase()]) !== null && _a !== void 0 ? _a : data[keys[0]]; keys.slice(1).forEach((e) => { var _a; if (result) { result = (_a = result[e]) !== null && _a !== void 0 ? _a : result[e.toLowerCase()]; } }); return result; } static getClassParams(className, fieldName) { const map = ModelHelper._maps.get(className); return map ? map.get(fieldName) : undefined; } /** 获取对象的所有 keys ,包括 src 注解部分 */ static getObjectKeys(obj) { const keys = Object.keys(obj); const _regKeys = this.getClassMap(obj.constructor.name, obj); if (_regKeys) { // 将注册的字段加入keys中,原因是由于没有默认值,可能字段不存在 _regKeys.forEach((k) => { if (!keys.includes(k.propertyName)) { keys.push(k.propertyName); } }); } return keys; } static getClassMap(className, object) { var _a; let values = ModelHelper._maps.get(className); if ((object === null || object === void 0 ? void 0 : object.__proto__) && !ModelHelper._initedClassMap[className]) { // 没有初始化过类型信息,寻找父类中的字段 values = values !== null && values !== void 0 ? values : new Map(); let superCls = object.__proto__; while (superCls) { const name = superCls.constructor.__proto__.name; superCls = superCls.__proto__; if (!name) { break; } (_a = this._maps.get(name)) === null || _a === void 0 ? void 0 : _a.forEach((item) => { if (values === null || values === void 0 ? void 0 : values.has(item.propertyName)) { return; } values === null || values === void 0 ? void 0 : values.set(item.propertyName, item); }); } if (values.size > 0) { ModelHelper._maps.set(className, values); } ModelHelper._initedClassMap[className] = true; } return values; } /** 将有 @src 装饰器的字段合并 */ static mergeClassMapField(className, doSetValue) { const _map = ModelHelper.getClassMap(className); if (_map && doSetValue !== undefined) { _map.forEach((k) => { doSetValue(k.name, k.propertyName, k); }); } } } exports.ModelHelper = ModelHelper; // 注册的注解参数 <类名, <name, value>> ModelHelper._maps = new Map(); // 记录已经初始化过类型信息的类 ModelHelper._initedClassMap = {}; class SrcParams { /** 执行转换器,如果返回 undefined ,则会忽略字段, 不进行处理 */ executeConvert(owner, value) { if (this.convert) { this.convert.data = owner; return this.convert.execute(value); } return value; } } exports.SrcParams = SrcParams; /** * src 注解,用于标识来源数据的信息 * @param name 源数据中的字段名称, 为空则使用本地字段名 * @param classType 目标对象类型(如果转换后需要是个对象时使用) * @param array 是否是数组 * @param convert 转换器类型 * @param ...args 转换器参数, 不同的转换器,参数不同 * @returns */ function src(name = undefined, classType, array = false, convert, ...args) { return function (target, propertyName) { const item = new SrcParams(); item.name = name ? name : propertyName; item.propertyName = propertyName; item.array = array; item.classType = classType; if (convert) { item.convert = new convert(...args); } let itemClass = ModelHelper._maps.get(target.constructor.name); if (!itemClass) { itemClass = new Map(); ModelHelper._maps.set(target.constructor.name, itemClass); } itemClass.set(propertyName, item); }; } exports.src = src; /** 来源数据转换器基类 */ class SrcConverterBase { } exports.SrcConverterBase = SrcConverterBase; /** 直接排除掉某个字段的转换器 */ class ExcludeFieldSrcConverter extends SrcConverterBase { execute(v) { return undefined; } } exports.ExcludeFieldSrcConverter = ExcludeFieldSrcConverter; /** 数据筛选转换器, 来源数据指定字段的值与参数值一致时返回来源值,否则返回 undefined */ class EqualValueFilterSrcConverter extends SrcConverterBase { /** 数据筛选转换器, 来源数据指定字段的值与参数值一致时返回来源值,否则返回 undefined */ constructor(field, value) { super(); this.field = field; this.value = value; } execute(v) { if (typeof this.data === "object") { // eslint-disable-next-line eqeqeq if (this.data[this.field] == this.value) { return v; } } return undefined; } } exports.EqualValueFilterSrcConverter = EqualValueFilterSrcConverter; /** 布尔值转换器 */ class BoolValueSrcConverter extends SrcConverterBase { constructor(trueValue) { super(); this.trueValue = trueValue; } execute(v) { return Array.isArray(this.trueValue) ? this.trueValue.includes(v) : v === this.trueValue; } } exports.BoolValueSrcConverter = BoolValueSrcConverter; /** 布尔值计算转换器 */ class BoolCalcSrcConverter extends SrcConverterBase { constructor(calcCallBack) { super(); this.calcCallBack = calcCallBack; } execute(v) { return this.calcCallBack ? this.calcCallBack(v) : false; } } exports.BoolCalcSrcConverter = BoolCalcSrcConverter; /** 数值型转换器 */ class IntSrcConverter extends SrcConverterBase { constructor(calcCallBack) { super(); this.calcCallBack = calcCallBack; } execute(v) { if (this.calcCallBack) { return this.calcCallBack(v); } if (v === true) { return 1; } if (v === false) { return 0; } return Number(v); } } exports.IntSrcConverter = IntSrcConverter; /** 日期型转换器 */ class DateSrcConverter extends SrcConverterBase { execute(v) { if (v) { if (v instanceof Date) { return v; } else if (typeof v === 'string') { return new Date(v); } else if (typeof v === 'number') { return new Date(v); } } return undefined; } } exports.DateSrcConverter = DateSrcConverter; /** JSON字符串转对象 - 转换器 */ class JsonObjectSrcConverter extends SrcConverterBase { /** * @param convSubFieldName 是否转变子对象的字段名称 */ constructor(convSubFieldName = false) { super(); this.convSubFieldName = convSubFieldName; } execute(v) { if (v && typeof v === "string") { const result = JSON.parse(v); if (result && this.convSubFieldName === true) { const isArray = Array.isArray(result); const newResult = isArray ? [] : {}; if (isArray) { const items = newResult; let cacheData; result.forEach((e) => { const v2 = {}; ModelHelper.initModel(e, v2, true, true, undefined, cacheData, (keys) => { cacheData = ModelHelper.initObjectCacheInfo(e, v2, keys, true); return cacheData; }); items.push(v2); }); } else { ModelHelper.initModel(result, newResult, true, true); } return newResult; } else { return result; } } else { return v; } } } exports.JsonObjectSrcConverter = JsonObjectSrcConverter; /** * 子对象转换至父级 - 转换器 * 注意: * 如果目标是数组,则会将数组内容设置到装饰器的字段中 * 如果目标是对象,则会将对象的内容设置到装饰器所在的类中,而不改变装饰器所有字段本身 */ class SubObjectConverter extends SrcConverterBase { /** * @param convSubFieldName 是否转变子对象的字段名称 */ constructor(convSubFieldName = false, convFieldName) { super(); this.convSubFieldName = convSubFieldName; this.convFieldName = convFieldName; } execute(v) { if (v) { if (Array.isArray(v)) { const items = []; v.forEach((e) => { if (typeof e === "object") { const v2 = {}; ModelHelper.initModel(e, v2, true, this.convSubFieldName, this.convFieldName); items.push(v2); } else { items.push(e); } }); return items; } else if (typeof v === "object") { ModelHelper.initModel(v, this.data, true, this.convSubFieldName, this.convFieldName); } } return undefined; } } exports.SubObjectConverter = SubObjectConverter; //# sourceMappingURL=model.helper.js.map