const Mock = require('mockjs'); const filter = require('./power-string.js').filter; const stringUtils = require('./power-string.js').utils; const json5 = require('json5'); const Ajv = require('ajv'); /** * 作用:解析规则串 key ,然后根据规则串的规则以及路径找到在 json 中对应的数据 * 规则串:$.{key}.{body||params}.{dataPath} 其中 body 为返回数据,params 为请求数据,datapath 为数据的路径 * 数组:$.key.body.data.arr[0]._id (获取 key 所指向请求的返回数据的 arr 数组的第 0 项元素的 _id 属性) * 对象:$.key.body.data.obj._id ((获取 key 所指向请求的返回数据的 obj 对象的 _id 属性)) * * @param String key 规则串 * @param Object json 数据 * @returns */ function simpleJsonPathParse(key, json) { if (!key || typeof key !== 'string' || key.indexOf('$.') !== 0 || key.length <= 2) { return null; } let keys = key.substr(2).split('.'); keys = keys.filter(item => { return item; }); for (let i = 0, l = keys.length; i < l; i++) { try { let m = keys[i].match(/(.*?)\[([0-9]+)\]/); if (m) { json = json[m[1]][m[2]]; } else { json = json[keys[i]]; } } catch (e) { json = ''; break; } } return json; } // 全局变量 {{ global.value }} // value 是在环境变量中定义的字段 function handleGlobalWord(word, json) { if (!word || typeof word !== 'string' || word.indexOf('global.') !== 0) return word; let keys = word.split('.'); keys = keys.filter(item => { return item; }); return json[keys[0]][keys[1]] || word; } function handleMockWord(word) { if (!word || typeof word !== 'string' || word[0] !== '@') return word; return Mock.mock(word); } /** * * @param {*} data * @param {*} handleValueFn 处理参数值函数 */ function handleJson(data, handleValueFn) { if (!data) { return data; } if (typeof data === 'string') { return handleValueFn(data); } else if (typeof data === 'object') { for (let i in data) { data[i] = handleJson(data[i], handleValueFn); } } else { return data; } return data; } function handleValueWithFilter(context) { return function(match) { if (match[0] === '@') { return handleMockWord(match); } else if (match.indexOf('$.') === 0) { return simpleJsonPathParse(match, context); } else if (match.indexOf('global.') === 0) { return handleGlobalWord(match, context); } else { return match; } }; } function handleFilter(str, match, context) { match = match.trim(); try { let a = filter(match, handleValueWithFilter(context)); return a; } catch (err) { return str; } } function handleParamsValue(val, context = {}) { const variableRegexp = /\{\{\s*([^}]+?)\}\}/g; if (!val || typeof val !== 'string') { return val; } val = val.trim(); let match = val.match(/^\{\{([^\}]+)\}\}$/); if (!match) { // val ==> @name 或者 $.body if (val[0] === '@' || val[0] === '$') { return handleFilter(val, val, context); } } else { return handleFilter(val, match[1], context); } return val.replace(variableRegexp, (str, match) => { return handleFilter(str, match, context); }); } exports.handleJson = handleJson; exports.handleParamsValue = handleParamsValue; exports.simpleJsonPathParse = simpleJsonPathParse; exports.handleMockWord = handleMockWord; exports.joinPath = (domain, joinPath) => { let l = domain.length; if (domain[l - 1] === '/') { domain = domain.substr(0, l - 1); } if (joinPath[0] !== '/') { joinPath = joinPath.substr(1); } return domain + joinPath; }; // exports.safeArray = arr => { // return Array.isArray(arr) ? arr : []; // }; function safeArray(arr) { return Array.isArray(arr) ? arr : []; } exports.safeArray = safeArray; exports.isJson5 = function isJson5(json) { if (!json) return false; try { json = json5.parse(json); return json; } catch (e) { return false; } }; function isJson(json) { if (!json) return false; try { json = JSON.parse(json); return json; } catch (e) { return false; } } exports.isJson = isJson; exports.unbase64 = function(base64Str) { try { return stringUtils.unbase64(base64Str); } catch (err) { return base64Str; } }; exports.json_parse = function(json) { try { return JSON.parse(json); } catch (err) { return json; } }; exports.json_format = function(json) { try { return JSON.stringify(JSON.parse(json), null, ' '); } catch (e) { return json; } }; exports.ArrayToObject = function(arr) { let obj = {}; safeArray(arr).forEach(item => { obj[item.name] = item.value; }); return obj; }; exports.timeago = function(timestamp) { let minutes, hours, days, seconds, mouth, year; const timeNow = parseInt(new Date().getTime() / 1000); seconds = timeNow - timestamp; if (seconds > 86400 * 30 * 12) { year = parseInt(seconds / (86400 * 30 * 12)); } else { year = 0; } if (seconds > 86400 * 30) { mouth = parseInt(seconds / (86400 * 30)); } else { mouth = 0; } if (seconds > 86400) { days = parseInt(seconds / 86400); } else { days = 0; } if (seconds > 3600) { hours = parseInt(seconds / 3600); } else { hours = 0; } minutes = parseInt(seconds / 60); if (year > 0) { return year + '年前'; } else if (mouth > 0 && year <= 0) { return mouth + '月前'; } else if (days > 0 && mouth <= 0) { return days + '天前'; } else if (days <= 0 && hours > 0) { return hours + '小时前'; } else if (hours <= 0 && minutes > 0) { return minutes + '分钟前'; } else if (minutes <= 0 && seconds > 0) { if (seconds < 30) { return '刚刚'; } else { return seconds + '秒前'; } } else { return '刚刚'; } }; // json schema 验证器 exports.schemaValidator = function(schema, params) { try { const ajv = new Ajv({ format: false, meta: false }); let metaSchema = require('ajv/lib/refs/json-schema-draft-04.json'); ajv.addMetaSchema(metaSchema); ajv._opts.defaultMeta = metaSchema.id; ajv._refs['http://json-schema.org/schema'] = 'http://json-schema.org/draft-04/schema'; var localize = require('ajv-i18n'); schema = schema || { type: 'object', title: 'empty object', properties: {} }; const validate = ajv.compile(schema); let valid = validate(params); let message = ''; if (!valid) { localize.zh(validate.errors); message += ajv.errorsText(validate.errors, { separator: '\n' }); } return { valid: valid, message: message }; } catch (e) { return { valid: false, message: e.message }; } };