UNPKG

rap2itf

Version:
244 lines (243 loc) 9.61 kB
"use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); }; exports.__esModule = true; var json_schema_to_typescript_1 = require("json-schema-to-typescript"); var JSON5 = require("json5"); var _ = require("lodash"); function inferArraySchema(p, childProperties, common) { var rule = (p.rule && p.rule.trim()) || ''; if (Object.keys(childProperties).length !== 0) { // 如果有子孙那么肯定是 object return [ p.name, __assign(__assign({ type: 'array', items: { type: 'object', properties: childProperties, // 把 child 的 required 挪到 items 下面 required: common.required, additionalProperties: false } }, common), { required: [] }), ]; } else if (['+1', '1'].includes(rule) && p.value) { // 当 rule 为 +1 时 mockjs 从属性值 array 中顺序选取 1 个元素,作为最终值。 // 当 rule 为 1 时 mockjs 从属性值 array 中随机选取 1 个元素,作为最终值。 // 这时候这个属性的类型并非 array,而是 array 子元素的类型 // 子元素的类型可以从 value 中推断出来 try { var arr = JSON5.parse(p.value); if (Array.isArray(arr) && arr.length) { var type = _.chain(arr) .map(function (e) { return typeof e; }) .uniq() .value(); return [ p.name, __assign({ type: type }, common), ]; } else { // 解析失败,返回 any return [ p.name, __assign({ type: ['string', 'number', 'boolean', 'object'] }, common), ]; } } catch (error) { // 解析失败,返回 any return [ p.name, __assign({ type: ['string', 'number', 'boolean', 'object'] }, common), ]; } } else if (rule === '' && p.value) { // 当有无子孙、有值、且无生成规则时,默认做 hack 满足 rap2 无法表示 array<primitive> 的问题, // primitive 的具体类型通过 value 推断 try { var v = JSON5.parse(p.value); if (Array.isArray(v)) { // 如果是空数组返回 any[] if (!v.length) { return [ p.name, __assign({ type: 'array' }, common), ]; } // 如果是数组使用数组元素类型 var type = _.chain(v) .map(function (e) { return typeof e; }) .uniq() .value(); return [ p.name, __assign({ type: 'array', items: { type: type } }, common), ]; } else { // 如果不是数组直接使用 value 类型 var type = typeof v; return [ p.name, __assign({ type: 'array', items: { type: type } }, common), ]; } } catch (error) { // 解析失败 返回 any[] return [ p.name, __assign({ type: 'array' }, common), ]; } } else { // 无生成规则也无值,生成 any[] return [ p.name, __assign({ type: 'array' }, common), ]; } } var removeComment = function (str) { return str.replace(/\/\*|\*\//g, ''); }; function getRestfulPlaceHolders(itf) { var urlSplit = itf.url.split('/'); var restfulPlaceHolders = []; for (var i = 0; i < urlSplit.length; ++i) { var part = urlSplit[i]; var matchKeys = part.match(/(?:\{(.*)\}|\:(.*))/); if (!matchKeys) continue; var key = matchKeys[1] || matchKeys[2]; restfulPlaceHolders.push(key); } return restfulPlaceHolders; } function interfaceToJSONSchema(itf, scope) { var properties = itf.properties.filter(function (p) { return p.scope === scope; }); properties = __spreadArray(__spreadArray([], properties, true), [ { name: 'dummyroot', parentId: -2, id: -1, scope: scope, type: 'object' }, ], false); if (scope === 'request') { var placeHolders = getRestfulPlaceHolders(itf); properties = __spreadArray(__spreadArray([], properties, true), placeHolders.map(function (name, index) { return ({ name: name, parentId: -1, id: index + 100, scope: scope, type: 'string' }); }), true); } function findChildProperties(parentId) { return _.chain(properties) .filter(function (p) { return p.parentId === parentId; }) .map(function (p) { var type = p.type.toLowerCase().replace(/regexp|function/, 'string'); var childProperties = findChildProperties(p.id); var childItfs = properties.filter(function (x) { return x.parentId === p.id; }); // request 的时候按照实际标注,response 全部默认存在 var required = childItfs.filter(function (e) { return e.required; }).map(function (e) { return e.name; }); var common = { // 这里默认所有的属性都有值 additionalProperties: false, required: required.length ? required : undefined }; if (p.description) common.description = removeComment(p.description); /** * 处理枚举,支持以下形式:(目前为控制影响范围,只对 string、number 做处理) * value="@pick(['p1', 'p2'])" * issue地址:https://github.com/thx/rapper/issues/9 */ if (['string', 'number'].includes(type) && p.value) { var enumArr = []; var regResult = /^@pick\(([\s\S]+)\)$/.exec(p.value); try { if (regResult) { var result = regResult[1]; enumArr = eval(result); } } catch (err) { } if (Array.isArray(enumArr) && enumArr.length) { common["enum"] = enumArr; } } if (['string', 'number', 'integer', 'boolean', 'null'].includes(type)) { return [ p.name, __assign({ type: type }, common), ]; } else if (type === 'object') { return [ p.name, __assign({ type: type, properties: childProperties }, common), ]; } else if (type === 'array') { return inferArraySchema(p, childProperties, common); } else { // 解析失败,返回 any return [ p.name, __assign({ type: ['string', 'number', 'boolean', 'object'] }, common), ]; } }) .fromPairs() .value(); } var propertyChildren = findChildProperties(-2); var root = propertyChildren['dummyroot']; // 只有一个 key 为 _root_ 或者 __root__ 的数组时,代表想表达根节点是个数组 if (Object.keys(root.properties).length === 1 && (root.properties._root_ || root.properties.__root__)) { var _root_ = root.properties._root_ || root.properties.__root__; if (_root_.type === 'array') { return _root_; } } return root; } function convert(itf) { var reqJSONSchema = interfaceToJSONSchema(itf, 'request'); var resJSONSchema = interfaceToJSONSchema(itf, 'response'); var options = __assign(__assign({}, json_schema_to_typescript_1.DEFAULT_OPTIONS), { bannerComment: '' }); return Promise.all([ (0, json_schema_to_typescript_1.compile)(reqJSONSchema, 'Req', options), (0, json_schema_to_typescript_1.compile)(resJSONSchema, 'Res', options), ]); } exports["default"] = convert;