ts-api-core
Version:
Nodejs api framework core
596 lines • 24.4 kB
JavaScript
"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